Android 模仿QQ登录界面解决软键盘遮挡问题

ClearEditText(账号输入框EditText中删除按钮的添加及功能实现,账号图标的添加,密码图标的添加) ClearEditText(账号输入框中删除按钮的添加,前置图标的添加,泛用性强),通过setCompoundDrawables(左,上,右,下)添加图片 阅读详情

Android 软件盘弹出可能会遮挡住界面上的某些控件。当 windowSoftInputMode 为 adjustPan 时,一般不会挡住 EditText,但是假如 EditText 下面是一个登录按钮,那么这个按钮就可能被挡住,但有时我们希望用户输完密码可以直接点击登录按钮,而不用把软键盘收起来。这时就需要用到 adjustResize,这种模式能够获取到软键盘的高度,这样我们就能够精确的对界面进行控制。

在阅读本章之前,你应该了解 windowSoftInputMode 的一些属性,特别是 adjustResize,如果还不熟悉,建议先阅读Android 软键盘之 windowSoftInputMode 分析再回过头来继续往下看。

QQ 登录界面很好的解决了软键盘遮挡问题,当然在大屏手机上软键盘并不会挡住登录按钮。今天我们也来模仿一个 QQ 登录界面,最终效果如下:
QQ登录界面

监听软键盘弹出及收起事件

step1. 指定 windowSoftInputMode=”adjustResize”

在 AndroidManifest.xml 中相应的 Activity 设置 android:windowSoftInputMode=”adjustResize”,也可以在 java 代码中设置。

step2. 监听 contentView 宽高(layout) 变化

获取 ViewTreeObserver 并监听 OnGlobalLayoutListener, 当viewTree的布局发生变化时onGlobalLayout将会回调。我们新建一个KeyboardHelper辅助类。

KeyboardHelper.java

public class KeyboardHelper {
    private Activity activity;
    private OnKeyboardStatusChangeListener onKeyboardStatusChangeListener;
    private int windowBottom = -1;
    private int keyboardHeight = 0;

    public KeyboardHelper(Activity activity) {
        this.activity = activity;
        activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        if (activity.getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        }
    }

    public void onCreate() {
        View content = activity.findViewById(android.R.id.content);
        // content.addOnLayoutChangeListener(listener); 这个方法有时会出现一些问题
        content.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
    }

    public void onDestroy() {
        View content = activity.findViewById(android.R.id.content);
        ViewUtils.removeOnGlobalLayoutListener(content, onGlobalLayoutListener);
    }

    private OnGlobalLayoutListener onGlobalLayoutListener = new OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            Rect rect = new Rect();
            activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
            Log.d("KeyboardHelper", "onGlobalLayout: " + rect + ", " + windowBottom);
            int newBottom = rect.bottom;
            if (windowBottom != -1 && windowBottom != newBottom) {
                if (newBottom < windowBottom) {
                    // keyboard pop
                    keyboardHeight = windowBottom - newBottom;
                    if (onKeyboardStatusChangeListener != null) {
                        onKeyboardStatusChangeListener.onKeyboardPop(keyboardHeight);
                    }
                } else {
                    // keyboard close
                    if (onKeyboardStatusChangeListener != null) {
                        onKeyboardStatusChangeListener.onKeyboardClose(keyboardHeight);
                    }
                }
            }
            windowBottom = newBottom;
        }
    };

    public void setOnKeyboardStatusChangeListener(
            OnKeyboardStatusChangeListener onKeyboardStatusChangeListener) {
        this.onKeyboardStatusChangeListener = onKeyboardStatusChangeListener;
    }

    public interface OnKeyboardStatusChangeListener {

        void onKeyboardPop(int keyboardHeight);

        void onKeyboardClose(int keyboardHeight);
    }
}

ViewUtils.java


public class ViewUtils {

    public static void removeOnGlobalLayoutListener(View view, ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener) {
        if (Build.VERSION.SDK_INT < 16) {
            view.getViewTreeObserver().removeGlobalOnLayoutListener(onGlobalLayoutListener);
        } else {
            view.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener);
        }
    }

}

代码比较简单,无非是获取window的可视坐标,通过比较bottom的值来判断软键盘是弹出还是收起。

实现 QQ 登录界面

有了这个 KeyBoardHelper,那么要实现和 QQ 登录界面一样的效果就不难了。我们甚至不需要任何自定义控件。思路是在软键盘弹出时,把登录按钮以上的布局往上移,只要为其设置一个负值的 topMargin 即可。

如图所示:
QQ登录界面示意图

MainActivity 代码如下:


public class MainActivity extends Activity {

    private int bottomHeight;
    private KeyboardHelper keyboardHelper;
    private View layoutBottom;
    private View layoutContent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_qq_login);

        layoutContent = findViewById(R.id.layout_content);
        layoutBottom = findViewById(R.id.layout_bottom);
        keyboardHelper = new KeyboardHelper(this);
        keyboardHelper.onCreate();
        keyboardHelper.setOnKeyboardStatusChangeListener(onKeyBoardStatusChangeListener);
        layoutBottom.post(new Runnable() {
            @Override
            public void run() {
                bottomHeight = layoutBottom.getHeight();
            }
        });
    }

    private OnKeyboardStatusChangeListener onKeyBoardStatusChangeListener = new OnKeyboardStatusChangeListener() {

        @Override
        public void onKeyboardPop(int keyboardHeight) {

            final int height = keyboardHeight;
            if (bottomHeight > height) {
                layoutBottom.setVisibility(View.GONE);
            } else {
                int offset = bottomHeight - height;
                final ViewGroup.MarginLayoutParams lp = (MarginLayoutParams) layoutContent
                        .getLayoutParams();
                lp.topMargin = offset;
                layoutContent.setLayoutParams(lp);
            }

        }

        @Override
        public void onKeyboardClose(int keyboardHeight) {
            if (View.VISIBLE != layoutBottom.getVisibility()) {
                layoutBottom.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        layoutBottom.setVisibility(View.VISIBLE);
                    }
                }, 300);
            }
            final ViewGroup.MarginLayoutParams lp = (MarginLayoutParams) layoutContent
                    .getLayoutParams();
            if (lp.topMargin != 0) {
                lp.topMargin = 0;
                layoutContent.setLayoutParams(lp);
            }

        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        keyboardHelper.onDestroy();
    }
}

布局文件:activity_qq_login.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/layout_root"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/layout_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:paddingTop="50dp">

        <ImageView
            android:id="@+id/imageView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="18dp"
            android:contentDescription="marginTop68dp"
            android:scaleType="centerInside"
            android:src="@drawable/qq_ava"
            android:visibility="visible" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="18dp"
            android:background="#f3f0f0"
            android:paddingBottom="100dp"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:paddingTop="100dp"
            android:text="这里为了演示增加一个TextView使登陆按钮在键盘底部"
            android:textColor="#333333"
            android:textSize="13sp" />

        <LinearLayout
            android:id="@+id/layout_ed"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#ffffff"
            android:divider="@drawable/divider"
            android:orientation="vertical"
            android:showDividers="middle">

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@null"
                android:hint="QQ号/手机号/邮箱"
                android:padding="10dp"
                android:textColor="#000000"
                android:textColorHint="#d2d2d2"
                android:textCursorDrawable="@null" />

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@null"
                android:hint="密码"
                android:padding="10dp"
                android:textColor="#000000"
                android:textColorHint="#d2d2d2"
                android:textCursorDrawable="@null" />
        </LinearLayout>

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="14dp"
            android:layout_marginRight="14dp"
            android:layout_marginTop="14dp"
            android:background="@drawable/btn_login"
            android:text="登陆"
            android:textSize="17sp" />

        <RelativeLayout
            android:id="@+id/layout_bottom"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <TextView
                android:id="@+id/tv_cannot_login"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:layout_margin="14dp"
                android:text="无法登陆?"
                android:textColor="@color/action_bar_bg"
                android:textSize="14sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:layout_alignParentRight="true"
                android:layout_margin="14dp"
                android:text="新用户"
                android:textColor="@color/action_bar_bg"
                android:textSize="14sp" />
        </RelativeLayout>
    </LinearLayout>

    <include
        android:id="@+id/appbar"
        layout="@layout/appbar"
        android:layout_width="match_parent"
        android:layout_height="50dp" />

</FrameLayout>

点我下载源码

Android全屏状态下弹出输入法adjustResize无效的修复方案及踩坑指南 Android全屏状态下弹出输入法ajustResize无效的修复方案及踩坑指南 输入框被输入法遮挡的问题相信很多人都遇见过,这次记录的是Activity在全屏FullScreen状态下windowSoftInputMode的ajustResize不生效问题。 下面是WindowManager类关于SOFT_INPUT_ADJUST_RESIZE的官方注释,在FullScreen状态下adjust... 阅读详情

相关推荐

微电网模型Matlab Simulink,风光储微电网,永磁风机并网仿真,光伏并网仿真,蓄电池仿真

通过探究风光储微电网、永磁风机并网仿真、光伏并网仿真、蓄电池仿真、柴油发电机以及光储微电网和风储微电网等方面的技术,我们可以更好地理解微电网的工作原理和优化方法,从而为微电网的发展做出更大的贡献。微电网模型Matlab Simulink,风光储微电网,永磁风机并网仿真,光伏并网仿真,蓄电池仿真,柴油发电机,光储微电网 风储微电网 Matlab仿真平台搭建的风光储微电网模型,风光柴储微电网,pwm控制,风力发电,光伏发电,微电网并网离网切换,并网孤岛切换,功能强大。永磁风机的并网仿真是一个非常重要的环节。

sjbextz的博客 399

Android实现系统下拉栏的消息提示——Notification

(img-W6G8gZQq-1712829832706)](img-iA4R5AFT-1712829832706)](img-UwURjII0-1712829832706)]视频,并且后续会持续更新**

2301_76348189的博客 1791

以GD32F103C8T6为例的核心板原理图PCB绘制学习笔记简单总结

重点在supplier part是立创商城的编号,可以搜到。

2301_80397661的博客 3261

Android自定义输入框

自定义输入框联动

QhappyfishQ的博客 2134

iOS自动化之打包-xcodebuild命令行打包.app并安装到ios模拟器

xcode xcodebuild xcrun ios模拟器 iOS UI自动化测试 ios自动打包安装到ios模拟器

z12347891的博客 5074

Vue3+uniapp开发必备:5分钟搞定unplugin-auto-import自动导入配置(附常见报错解决)

本文详细介绍了在Vue3+uniapp项目中配置unplugin-auto-import插件实现自动导入的方法。通过该配置,开发者无需手动导入ref、onLoad等常用API,可显著提升编码效率和团队协作规范性。文章提供了从安装、TypeScript集成到高级用法的完整指南,并附带了常见报错的解决方案。

weixin_29008805的博客 959

14. 【Android教程】文本输入框 EditText

android:hint="请输入密码"android:hint="请输入密码"用来提示用户,本输入框的功能是输入密码,当你点击EditText往里面输入字符之后,提示就会消失。设置当前输入的类为密码,那么当用户输入文本后,系统会用“*”或者“·”替代。设置当前的输入框最多使能容纳3行内人,如果多余 3 行,则会采用滚动条的形式上下滑动。

这是一个web全栈开发的博客,取其精华去其糟粕,争取让大家一看就懂,一学就会,一用就成~ 2092

一步步指导:在Chrome中安装Vue插件vue-devtools

Vue.js是现代Web开发中最流行的前端框架之一,它以其轻量级、高性能和易于理解的设计理念受到开发者的喜爱。为了更高效地开发和调试Vue应用,Vue.js官方提供了一个强大的开发工具——vue-devtools。

小透明的博客 5618

Android 软键盘的那些坑,原理篇来了!

分析了软键盘弹出、关闭、获取软键盘高度、常用属性展示等。这部分也是网上涉及软键盘文章的重点,但是几乎没人将原理剖析过,导致对常用属性的理解止于Demo,对一些问题的了解似是而非。因此,本篇...

Android技术之家 2670

SOMEIP协议--第三节[SOMEIP/SD](SD格式)

Entry和Option是SD报文中最重要的内容,是服务发现功能的承载。7.Minor Version是指当前服务的小版本号,可以配置,用于给用户区分当前服务的版本用的。注意:stop offer,stop subscribe,Subscribe Nack 这三条的TTL一定设为0,唯一和offer,subscribe,Subscribe的区别。Option用来辅助Entry实现其功能,是Entry携带的附加信息,作用上一般是用来告诉对端自己业务的ip和port信息,方便对端通过ip和port发送报文。

qq_41816308的博客 1338

基于pytorch cnn ResNets卷积网络的模糊图像检测 完整代码数据直接运行

基于pytorch cnn ResNets卷积网络的模糊图像检测 完整代码数据直接运行

730

仿QQ空间登录,解决键盘挡住输入框的问题

http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2013/0411/1151.html

340

第二节_PySide6项目创建流程介绍、手把手教学打包EXE可执行文件

本文详细介绍了如何使用PySide6创建一个带UI界面的Python程序,并将其打包成exe可执行文件。首先,通过Pycharm创建项目,并使用PySide6-Designer工具设计UI界面,将生成的ui文件转换为Python代码。接着,编写主程序,加载UI界面并实现功能,如加载图片、设置图标等。最后,通过资源文件管理图片资源,并确保UI界面的更新能同步到主程序中。整个过程涵盖了项目创建、UI设计、代码编写及资源管理,适合初学者学习如何将Python程序打包为可执行文件。

su桥木的博客 2555

Android UI设计初体验(模仿微信登录界面)

虽然说软件分工的目的在于各司其职更有效地完成开发任务,但在我写代码的过程中总是忍不住搞搞美工的事。(估计骨子里是个搞美工的) 因为软件的好坏,有时候不是从功能上评价的,而是从外观上。而美工这活,绿色与浅绿色的区别,没准就造成美丑之分。 这两天完成了功能代码的编写,心血来潮搞起UI,通过模仿微信(配色、布局、操作方式)来完善我的app(虽然是一个完全不需要外观的app = =)。 经过

Kw学编程 1万+

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

长沙红胖子Qt·西安(长沙创微智科)博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中...

长沙红胖子 Qt・西安,本人拥有省级科研团队从业背景,研发团队产出所有项目、产品方案和研发无分包、无外包、无AI代笔,长期深耕双一流体系高精尖技术配套研发。博客主动剥离复杂底层工况机理,专注沉淀高端、特种行业领域Qt工程化落地实战经验。所有内容均为个人梳理总结的通用性工程方法论,只输出可公开的普适技术思路。

长沙红胖子 Qt・西安|省级科研团队从业背景,深耕双一流体系高精尖技术配套研发|剥离高精尖机理,沉淀高端特种行业领域 Qt 工程化落地经验|博文仅分享通用技术总结,输出公开普适工程思路。 164万+

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Android开发之自定义控件-模仿QQ输入框

效果图:

liu537192的专栏 2365

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

安卓开发:模仿微信,QQ评论输入框,使用PopupWindow完美实现(新版)

首先说一下实现的效果,点击外部消失,有个缺点,键盘弹出时,点击back不会消失,第二次点击back或者点外部才可以消失; 我的直播项目里用的,有“弹幕”按钮(已隐藏),上效果 布局左边是有弹幕按钮的,隐藏了,有需要打开就可以了 上布局代码:<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http:/

ximen_qing的博客 1461

Android—简单的仿QQ聊天界面

最近仿照QQ聊天做了一个类似界面,先看下界面组成(画面不太美凑合凑合呗,,,,): 其中聊天背景可以是一个LinearLayout或者RelativeLayout里面存放的是ListView(将ListView的分割线设置成透明:android:divider="#0000"否则聊天界面会显示出分割线,,,想想都屌,,,) 于是,我要上主界面的xml布局文件了: &lt...

weixin_30765475的博客 374

android仿qq评论功能,仿微信、QQ评论功能,输入框保持在内容下面。

类似于QQ控件和微信朋友圈的的评论效果,点击回复,会保持输入框在当前回复的内容下面,一,效果图。GIF.gif二,实现思路。当点击item的时候,获取当前item距离屏幕顶部的距离。然后在输入法弹出来后,得到输入法距离顶部的距离。这两个距离差就是 recycleView要滑动的距离。三,具体实现/*** //滑动recycleview 当前回复的item保持在输入法上面* @param posit...

weixin_35997054的博客 437

Android开发之浅仿QQ聊天UI和键盘控制

话不多说,献上UI效果图 这里面设计到的知识点不多,先来了解系统输入法弹出方式.当输入内容时输入框被系统键盘遮挡了,影响了用户操作体验,这就是开发中非常常见的软键盘遮挡的问题,该如何解决?getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);这个方法适用于一般的滚动视图,会把视图往上

AnalyzeSystem的博客 5022

SOFT_INPUT_ADJUST_RESIZE

嵌一个webview 然后在输入框调出 android 软键盘时 一直 被覆盖。 各种调整参数设置了没用。。。 1、有把android:windowSoftInputMode="stateHidden|adjustResize“ 2、在webview 外嵌套 一个scroll 3、在webview外嵌套 Linearlayout 种种办法都尝试过,

田田的菜坛子 7016

Android SoftInputMode为SOFT_INPUT_ADJUST_RESIZE(adjustResize)时没有resize动画的问题

Android SoftInputMode为SOFT_INPUT_ADJUST_RESIZE(adjustResize)时没有resize动画的问题用过android:windowSoftInputMode=”adjustResize”的应该都知道,在该模式下弹出软键盘时,编辑框变位置时会有一个alpha动画。昨天突然发现一个界面里在弹出软键盘时没有了这个alpha动画,resize就显得很生硬。于

yellowcath的专栏 7149

输入法遮挡EditText输入框的问题

一:在清单文件中对应的Activity便签下添加如下配置android:windowSoftInputMode="stateVisible|adjustResize" 二:在对应的Activity代码中添加如下代码getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); 代码添加在setCont...

李建国的博客 1734

软键盘显示/交互问题

软键盘交互问题

QG 1410

【Android】WMS(二)Window的添加

window的添加

每天不是在写bug就是在写bug的路上 1836
上一篇: Android 软键盘之 windowSoftInputMode 分析
下一篇: Android 网络框架 Volley 源码解析
leandom
博客等级 码龄12年 3粉丝 11原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值