热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android背景可滑动登录界面

Android背景可滑动登录界面废话不多说,先看下实现后的效果:这里写图片描述实现思路看到上边gif图的效果,主要列举一下实现过程过程中遇到的难点。如何使键盘弹出时候不遮挡底部登录
Android 背景可滑动登录界面

废话不多说,先看下实现后的效果:

《Android 背景可滑动登录界面》 这里写图片描述

实现思路

看到上边 gif 图的效果,主要列举一下实现过程过程中遇到的难点。

  1. 如何使键盘弹出时候不遮挡底部登录布局;
  2. 当键盘弹出的时候如何不压缩背景图片或者背景延伸至「屏幕以外」;

从 「 windowSoftInputMode 」 说起

相信大家都清楚,Google 官方提供给开发者控制软键盘显示隐藏的方法不多,「windowSoftInputMode」算是我们可控制的软键盘弹出模式的方法之一。关于其属性的说明Google 官方和网上的教程说了很多,他的属性值由两部分组成,形如「 stateHidden|adjustResize 」的格式,其前半部分(事实上也可写在后边)表示所设置的 Activity 进入时软键盘的状态,后半部分表示软键盘弹出的时候页面是如何调整的。
下边分别列出几个可选属性及其含义:

属性含义
stateUnspecified软件弹出状态为系统根据配置的页面主题选择默认的设置,也就是说为默认属性值
stateUnchanged软键盘被保持无论它上次在该页面的状态,也就是说退出该页面的时候是可见或隐藏,当主窗口出现在前面时仍然是值钱的状态。
stateHidden首次创建进入该页面的时候,软键盘被隐藏。
stateAlwaysHidden无论什么情况下进入该页面软键盘总是隐藏状态。
stateVisible首次创建进入该页面的时候,软键盘显示。
stateAlwaysVisible无论什么情况下进入该页面软键盘总是显示状态。
adjustUnspecified页面适应软键盘弹起的时候默认属性,它包括两种情况,一种是页面不可滚动的时候,他压缩布局以保证获取焦点的输入框可见,一种是页面可滚动的时候,他将向上滚动布局,直到输入框可见。
adjustResize页面总是调整屏幕的大小以便留出软键盘的空间。这一属性会重新绘制view
adjustPan设置成adjustPan的时候键盘会去找当前界面的焦点,并始终焦点放在键盘的上方,使获得焦点的view可见。当前窗口的内容将自动移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分

通过上述列表我们可以了解到 windowSoftInputMode 的几个属性值的含义。我们可以根据具体的需求来选择合适属性。However ! 产品需求永远比属性来的奇葩。比如说我们想要实现的的这个效果:

  1. 软键盘弹出不遮挡全部的输入布局,并不是单纯的留出一个输入框控件
  2. 软键盘被弹起的时候背景不能被压缩,或者向上滑动

首先看第一个需求:我们可以使用 adjustResize 属性来达到效果,可以看到这样图片已经被自动向上移动了,ok,如果效果您还算满意,那我就没什么好说的了,但是我们老板和产品以及 UI 说这样不好,背景不能压缩也就是我们说的第二个需求。当时我心中就有一种 mmp 想对他们说。但是呢作为一个敢于挑战的 Android 程序员来说这个小小的需求并不算什么。

《Android 背景可滑动登录界面》 这里写图片描述

对于第二个需求,首先我们要了解为什么图片会被上滑,是因为我们配置了 adjustResize 属性,系统自动根据键盘所需要的空间向上移动整个页面的布局,并调整页面布局的大小以满足不被软键盘隐藏的效果。举个栗子:

手机屏幕的高为1920px,那么整个Activity的布局高度也为1920px。当设置该属性后点击界面中的EditText,此时弹出软键盘其高度为800px。为了完整地显示此软键盘,系统会调整Activity布局的高度为1920px-800px=1120px。

注意这里说了会调整布局的大小,根据以往的经验,系统自动调节的布局都不是我们想要的结果,比如各种可滑动 View 嵌套的问题。那么这个需求能否依据这个思路来结局呢?

当 windowSoftInputMode 被设置为 adjustResize 时候,当布局调整的时候被调整的布局均会重绘制,并走了onMeasure,onSizeChanged,onLayout
当 windowSoftInputMode 被设置为 adjustPan 时候,当布局调整的时候被调整的布局均会重绘制,并走了onMeasure, onLayout

这里只需要注意 两者都走了 onMeasure 方法,至于 adjustPan 没走 onSizeChanged ,我们会在之后关于软键盘弹出的监控的文章中详细说明。

那么我们就利用其走了 onMeasure 方法,来「阻止」系统自动调整的布局大小。由于我们背景用了 ViewPager,所以我们需要重写 ViewPager 的 OnMeasure 方法。

public class AutoViewPager extends ViewPager {
private int mScreenHeight;
public AutoViewPager(Context context) {
this(context,null);
}
public AutoViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
mScreenHeight = DensityUtil.getHeight(getContext());
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(mScreenHeight, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}

DensityUtil.getHeight 方法是获取屏幕高度的方法。

public static int getHeight(Context context) {
DisplayMetrics dm = new DisplayMetrics();
WindowManager mWm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
mWm.getDefaultDisplay().getMetrics(dm);
int screenHeight = dm.heightPixels;
return screenHeight;
}

经过这样的设置我们就讲背景 ViewPager 的高度写死为屏幕的高度。这样当键盘弹出的时候ViewPager 的大小就会变了。 经过测试我们这个方法就就可以组织背景向上移动了。其实我们并没有组织系统对控件的重绘,而是改变了最终重绘的 ViewPager 的高度大小,给用户的感觉就是我的背景没有改变。

最后附送实现的布局代码:


xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/rl_root"
android:layout_
android:layout_
android:orientation="vertical">
android:layout_
android:layout_>
android:id="@+id/login_bg_banner"
android:layout_
android:layout_/>
android:id="@+id/ll_dot"
android:layout_
android:layout_
android:layout_centerHorizOntal="true"
android:layout_gravity="center_horizontal">
android:id="@+id/iv_dot_1"
android:layout_
android:layout_
android:layout_marginRight="8dp"
android:background="@drawable/banner_dot_shape_select"/>
android:id="@+id/iv_dot_2"
android:layout_
android:layout_
android:layout_marginRight="8dp"
android:background="@drawable/bander_dot_shape_noselect"/>
android:id="@+id/iv_dot_3"
android:layout_
android:layout_
android:background="@drawable/bander_dot_shape_noselect"/>


android:id="@+id/activity_login"
android:layout_
android:layout_
android:layout_alignParentBottom="true"
android:paddingBottom="@dimen/login_margin_bottom"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:background="@drawable/login_shape"
android:orientation="vertical">
android:layout_
android:layout_
android:orientation="vertical">
android:layout_
android:layout_>
android:id="@+id/rl_phone_name"
android:layout_
android:layout_>
android:id="@+id/tv_area_code"

android:layout_
android:layout_
android:layout_centerVertical="true"
android:layout_marginLeft="@dimen/login_tv_margin_left"
android:padding="5dp"
android:text="+86">


android:layout_
android:layout_
android:layout_centerHorizOntal="true"
android:layout_centerVertical="true"
android:layout_marginLeft="@dimen/login_line_margin"
android:layout_toRightOf="@id/tv_area_code"
android:background="@color/gray"/>
android:id="@+id/et_phone_num"
android:layout_
android:layout_
android:layout_marginLeft="@dimen/login_et_margin_left"
android:background="@null"
android:hint="请输入您的手机号码"
android:inputType="phone"
android:maxLength="11"
android:maxLines="1"
android:paddingBottom="20dp"
android:paddingTop="20dp"
android:textColor="@color/black"
android:textColorHint="@color/gray"
android:textCursorDrawable="@null"
android:textSize="@dimen/font_normal">



android:id="@+id/line_phone_num"
android:layout_
android:layout_
android:layout_below="@+id/rl_phone_name"
android:layout_centerHorizOntal="true"
android:layout_marginLeft="@dimen/login_line_margin"
android:layout_marginRight="@dimen/login_line_margin"
android:background="@color/gray"/>
android:id="@+id/rl_check_num"
android:layout_
android:layout_
android:layout_alignLeft="@+id/line_phone_num"
android:layout_alignRight="@+id/line_phone_num"
android:layout_below="@+id/line_phone_num">
android:id="@+id/et_check_num"
android:layout_
android:layout_
android:layout_centerInParent="true"
android:layout_toLeftOf="@+id/btn_get_check"
android:background="@null"
android:hint="请输入验证码"
android:inputType="number"
android:maxLength="4"
android:maxLines="1"
android:paddingBottom="20dp"
android:paddingLeft="120dp"
android:paddingTop="20dp"
android:textColor="@color/black"
android:textColorHint="@color/gray"
android:textCursorDrawable="@null"
android:textSize="@dimen/font_normal"/>
android:id="@+id/btn_get_check"
android:layout_
android:layout_
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginBottom="@dimen/login_btn_check_margin_bottom"
android:layout_marginTop="@dimen/login_btn_check_margin_top"
android:gravity="center"
android:text="获取验证码"
android:textColor="@color/gray"
android:textSize="@dimen/font_normal"
app:defaultBackgroundResource="@drawable/btn_check_gray_shape"/>

android:id="@+id/line_check_num"
android:layout_
android:layout_
android:layout_below="@+id/rl_check_num"
android:layout_centerHorizOntal="true"
android:layout_marginLeft="25.3dp"
android:layout_marginRight="25.3dp"
android:background="@color/driver_color"/>

android:id="@+id/btn_phone_login"
android:layout_
android:layout_
android:layout_gravity="center_horizontal"
android:layout_marginTop="23dp"/>





清单文件中的配置

android:name=".activities.LoginActivity"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:theme="@style/AppTheme"
android:windowSoftInputMode="stateHidden|adjustResize">

后来又读者反映按照的方式键盘还是会将布局顶上去:

检查自己的主题和代码中是否设置了全屏模式(FullScreen),因为如果设置了全屏模式的话 adjustResize 将失效,参考 Android How to adjust layout in Full Screen Mode when softkeyboard is visible ;


推荐阅读
  • Java EE 平台集成了多种服务、API 和协议,旨在支持基于 Web 的多层应用程序开发。本文将详细介绍 Java EE 中的 13 种关键技术规范,帮助开发者更好地理解和应用这些技术。 ... [详细]
  • 阿里云 Aliplayer高级功能介绍(八):安全播放
    如何保障视频内容的安全,不被盗链、非法下载和传播,阿里云视频点播已经有一套完善的机 ... [详细]
  • WPF项目学习.一
    WPF项目搭建版权声明:本文为博主初学经验,未经博主允许不得转载。一、前言记录在学习与制作WPF过程中遇到的解决方案。使用MVVM的优点是数据和视图分离,双向绑定,低耦合,可重用行 ... [详细]
  • 本文详细介绍了 Java 网站开发的相关资源和步骤,包括常用网站、开发环境和框架选择。 ... [详细]
  • 本文介绍了 Oracle SQL 中的集合运算、子查询、数据处理、表的创建与管理等内容。包括查询部门号为10和20的员工信息、使用集合运算、子查询的注意事项、数据插入与删除、表的创建与修改等。 ... [详细]
  • SvpplyTable: 实现可扩展和可折叠的菜单动画
    SvpplyTable 是一个示例项目,旨在实现类似 Svpply 应用程序中的可扩展和可折叠的菜单动画效果。该项目托管在 GitHub 上,地址为 https://github.com/liuminqian/SvpplyTable。 ... [详细]
  • PBO(PixelBufferObject),将像素数据存储在显存中。优点:1、快速的像素数据传递,它采用了一种叫DMA(DirectM ... [详细]
  • 本文通过基准测试(Benchmark)对.NET Core环境下Thrift和HTTP客户端的微服务通信性能进行对比分析。基准测试是一种评估系统或组件性能的方法,通过运行一系列标准化的测试来衡量其表现。 ... [详细]
  • packagecom.panchan.tsmese.utils;importjava.lang.reflect.ParameterizedType;importjava.lang. ... [详细]
  • 本文介绍了Java编程语言的基础知识,包括其历史背景、主要特性以及如何安装和配置JDK。此外,还详细讲解了如何编写和运行第一个Java程序,并简要介绍了Eclipse集成开发环境的安装和使用。 ... [详细]
  • Cookie学习小结
    Cookie学习小结 ... [详细]
  • 华为捐赠欧拉操作系统,承诺不推商用版
    华为近日宣布将欧拉开源操作系统捐赠给开放原子开源基金会,并承诺不会推出欧拉的商用发行版。此举旨在推动欧拉和鸿蒙操作系统的全场景融合与生态发展。 ... [详细]
  • 2022年2月 微信小程序 app.json 配置详解:启用调试模式
    本文将详细介绍如何在微信小程序的 app.json 文件中启用调试模式(debug),并通过实际案例展示其配置方法和应用场景。 ... [详细]
  • 本文旨在解决 MySQL 无法连接到 localhost 的常见问题,并提供详细的步骤来确保 MySQL 服务正确启动和配置。 ... [详细]
  • 基于iSCSI的SQL Server 2012群集测试(一)SQL群集安装
    一、测试需求介绍与准备公司计划服务器迁移过程计划同时上线SQLServer2012,引入SQLServer2012群集提高高可用性,需要对SQLServ ... [详细]
author-avatar
我财我乐汽车869
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有