热门标签 | 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 ;


推荐阅读
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • Linux服务器密码过期策略、登录次数限制、私钥登录等配置方法
    本文介绍了在Linux服务器上进行密码过期策略、登录次数限制、私钥登录等配置的方法。通过修改配置文件中的参数,可以设置密码的有效期、最小间隔时间、最小长度,并在密码过期前进行提示。同时还介绍了如何进行公钥登录和修改默认账户用户名的操作。详细步骤和注意事项可参考本文内容。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • 解决Cydia数据库错误:could not open file /var/lib/dpkg/status 的方法
    本文介绍了解决iOS系统中Cydia数据库错误的方法。通过使用苹果电脑上的Impactor工具和NewTerm软件,以及ifunbox工具和终端命令,可以解决该问题。具体步骤包括下载所需工具、连接手机到电脑、安装NewTerm、下载ifunbox并注册Dropbox账号、下载并解压lib.zip文件、将lib文件夹拖入Books文件夹中,并将lib文件夹拷贝到/var/目录下。以上方法适用于已经越狱且出现Cydia数据库错误的iPhone手机。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 从零学Java(10)之方法详解,喷打野你真的没我6!
    本文介绍了从零学Java系列中的第10篇文章,详解了Java中的方法。同时讨论了打野过程中喷打野的影响,以及金色打野刀对经济的增加和线上队友经济的影响。指出喷打野会导致线上经济的消减和影响队伍的团结。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
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社区 版权所有