Android键盘面板冲突 布局闪动处理方案
起源,之前在微信工作的时候,为了给用户带来更好的基础体验,做了很多尝试,踩了很多输入法的坑,特别是动态调整键盘高度,二级页面是透明背景,魅族早期的Smart bar等, 后来逐一完善了,考虑到拥抱开源,看业界还是有很多应用存在类似问题。就有了这个repo
之前有写过一篇核心思想: Switching between the panel and the keyboard in Wechat。



欢迎提交 Pull requests
- 尽量多的英文注解。
- 每个提交尽量的细而精准。
- Commit message 遵循: AngularJS's commit message convention。
- 尽可能的遵循IDE的代码检查建议(如 Android Studio 的 'Inspect Code')。
如何使用
在build.gradle中引入:
compile 'cn.dreamtobe.kpswitch:library:1.4.4'
使用引导
非全屏主题情况下使用引导
所谓非全屏主题,就是
(activity.getWindow().getAttributes().flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0

I. AndroidManifest
可直接参照: AndroidManifest.xml
对应的Activity,在
AndroidManifest中配置android:windowSoftInputMode=adjustResize
<manifest
...>
<application
...>
<activity
android:name=".activity.ChattingActivity"
android:windowSoftInputMode=adjustResize"/>
...
</application>
...
</manifest>
II. 需要处理页面的layout xml
- 需要用到 最上层布局 (KPSwitchRootFrameLayout/KPSwitchRootLinearLayout/KPSwitchRootRelativeLayout)
- 需要用到 面板布局(KPSwitchPanelFrameLayout/KPSwitchPanelLinearLayout/KPSwitchPanelRelativeLayout)。
简单案例:
<?xml version="1.0" encoding="utf-8"?>
<!-- 可选用 KPSwitchRootLinearLayout、KPSwitchRootRelativeLayout、KPSwitchRootFrameLayout -->
<cn.dreamtobe.kpswitch.widget.KPSwitchRootLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- 布局内容 -->
...
<!-- 可选用 KPSwitchPanelLinearLayout、KPSwitchPanelRelativeLayout、KPSwitchPanelFrameLayout -->
<cn.dreamtobe.kpswitch.widget.KPSwitchPanelLinearLayout
android:id="@+id/panel_root"
android:layout_width="fill_parent"
android:layout_height="@dimen/panel_height"
android:visibility="gone">
<!-- 面板内容 -->
...
</cn.dreamtobe.kpswitch.widget.KPSwitchPanelLinearLayout>
</cn.dreamtobe.kpswitch.widget.KPSwitchRootLinearLayout>
III. 需要处理页面的Activity:
- 处理一些事件(KPSwitchConflictUtil)
- 键盘状态(高度与显示与否)监听(KeyboardUtil#attach())
简单案例:
...
// 面板View
private KPSwitchPanelLinearLayout mPanelLayout;
// 键盘焦点View,用于输入内容
private EditText mSendEdt;
// 用于切换键盘与面板的按钮View
private ImageView mPlusIv;
@Override
public void onCreate(Bundle saveInstanceState){
...
mPanelLayout = (KPSwitchPanelLinearLayout)findViewById(R.id.panel_root);
mSendEdt = (EditText) findViewById(R.id.send_edt);
mPlusIv = (ImageView) findViewById(R.id.plus_iv);
/**
* 这个Util主要是监控键盘的状态: 显示与否 以及 键盘的高度
* 这里也有提供给外界监听 键盘显示/隐藏 的监听器,具体参看
* 这个接口 {@Link KeyboardUtil#attach(Activity, IPanelHeightTarget, OnKeyboardShowingListener)}
*/
KeyboardUtil.attach(this, mPanelLayout);
/**
* 这个Util主要是协助处理一些面板与键盘相关的事件。
* 这个方法主要是对一些相关事件进行注册,如切换面板与键盘等,具体参看源码,比较简单。
* 里面还提供了一些已经处理了冲突的工具方法: 显示面板;显示键盘;键盘面板切换;隐藏键盘与面板;
*
* @param panelRoot 面板的布局。
* @param switchPanelKeyboardBtn 用于触发切换面板与键盘的按钮。
* @param focusView 键盘弹起时会给这个View focus,收回时这个View会失去focus,通常是发送的EditText。
*/
KPSwitchConflictUtil.attach(mPanelLayout, mPlusIv, mSendEdt);
}
...
...
// 如果需要处理返回收起面板的话
@Override
public boolean dispatchKeyEvent(KeyEvent event){
if (event.getAction() == KeyEvent.ACTION_UP &&
event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
if (mPanelLayout.getVisibility() == View.VISIBLE) {
KPSwitchConflictUtil.hidePanelAndKeyboard(mPanelLayout);
return true;
}
}
return super.dispatchKeyEvent(event);
}
全屏主题情况下使用引导
所谓全屏主题,就是
(activity.getWindow().getAttributes().flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0

I. AndroidManifest
可直接参照: AndroidManifest.xml
对应的Activity,在
AndroidManifest中配置android:windowSoftInputMode=adjustUnspecified,或者不配置,默认就是这个模式。
II. 需要处理页面的layout xml
可直接参照: activity_chatting_fullscreen_resolved.xml
这边只需要用到一个 面板布局(KPSwitchFSPanelFrameLayout/KPSwitchFSPanelLinearLayout/KPSwitchFSPanelRelativeLayout)
<?xml version="1.0" encoding="utf-8"?>
...
...
<!-- 可选用 KPSwitchFSPanelFrameLayout、KPSwitchFSPanelLinearLayout、KPSwitchFSPanelRelativeLayout -->
<cn.dreamtobe.kpswitch.widget.KPSwitchFSPanelFrameLayout
android:id="@+id/panel_root"
style="@style/Panel"
android:visibility="gone">
...
</cn.dreamtobe.kpswitch.widget.KPSwitchFSPanelFrameLayout>
...
III. 需要处理页面的Activity:
- 主要是处理一些事件(KPSwitchConflictUtil)
- 键盘状态(高度与显示与否)监听(KeyboardUtil#attach())
- 在
onPause时,记录键盘状态用于从后台回到当前布局,恢复键盘状态不至于冲突(IFSPanelConflictLayout#recordKeyboardStatus())
如下使用案例:
...
// 面板View
private KPSwitchFSPanelLinearLayout mPanelLayout;
// 键盘焦点View,用于输入内容
private EditText mSendEdt;
// 用于切换键盘与面板的按钮View
private ImageView mPlusIv;
@Override
public void onCreate(Bundle saveInstanceState){
...
mPanelLayout = (KPSwitchFSPanelLinearLayout)findViewById(R.id.panel_root);
mSendEdt = (EditText) findViewById(R.id.send_edt);
mPlusIv = (ImageView) findViewById(R.id.plus_iv);
/**
* 这个Util主要是监控键盘的状态: 显示与否 以及 键盘的高度
* 这里也有提供给外界监听 键盘显示/隐藏 的监听器,具体参看
* 这个接口 {@Link KeyboardUtil#attach(Activity, IPanelHeightTarget, OnKeyboardShowingListener)}
*/
KeyboardUtil.attach(this, mPanelLayout);
/**
* 这个Util主要是协助处理一些面板与键盘相关的事件。
* 这个方法主要是对一些相关事件进行注册,如切换面板与键盘等,具体参看源码,比较简单。
* 里面还提供了一些已经处理了冲突的工具方法: 显示面板;显示键盘;键盘面板切换;隐藏键盘与面板;
*
* @param panelRoot 面板的布局。
* @param switchPanelKeyboardBtn 用于触发切换面板与键盘的按钮。
* @param focusView 键盘弹起时会给这个View focus,收回时这个View会失去focus,通常是发送的EditText。
*/
KPSwitchConflictUtil.attach(mPanelLayout, mPlusIv, mSendEdt);
}
@Override
protected void onPause() {
super.onPause();
// 用于记录当前的键盘状态,在从后台回到当前页面的时候,键盘状态能够正确的恢复并且不会导致布局冲突。
mPanelLayout.recordKeyboardStatus(getWindow());
}
...
// 如果需要处理返回收起面板的话
@Override
public boolean dispatchKeyEvent(KeyEvent event){
if (event.getAction() == KeyEvent.ACTION_UP &&
event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
if (mPanelLayout.getVisibility() == View.VISIBLE) {
KPSwitchConflictUtil.hidePanelAndKeyboard(mPanelLayout);
return true;
}
}
return super.dispatchKeyEvent(event);
}
基本原理
- 键盘高度计算,以及键盘是否显示的计算,参看:KeyboardUtil.KeyboardStatusListener#calculateKeyboardHeight、KeyboardUtil.KeyboardStatusListener#calculateKeyboardShowing。
- 处理闪动问题,参看: KPSwitchRootLayoutHandler,以及如果是非全屏主题用到的面板布局:KPSwitchPanelLayoutHandler;如果是全屏主题用到的面板布局: KPSwitchFSPanelLayoutHandler。
项目描述:For resolve the layout conflict when keybord & panel are switching (Android键盘面板冲突 布局闪动处理方案) — 查看更多内容...
| 问题列表: | ||
| #43 | Adapt the case of DialogFragment | 由 anjiao 2017-03-27 |
| #55 | focusView.setOnTouchListener在up的时候。panelLayout.setVisibility(View.INVISIBLE); | 由 lyqaiym 2017-01-24 |
| #54 | 希望能适配下panel是用fragment填充的情况 | 由 mansoul1994 2017-01-05 |
| #52 | Demo中 锁屏会出现问题 | 由 fanss 2016-12-30 |
| #53 | 建议在onGlobalLayout中判断下 activity 是否有焦点 | 由 RubinChen 2016-12-29 |
Android键盘面板冲突 布局闪动处理方案的更多相关文章
- android 类似QQ底部输入框弹出键盘和面板冲突 布局闪动处理方案(转)
先看下效果 差不多就是解决这种冲突,布局闪动的 作者的githup :https://github.com/Jacksgong/JKeyboardPanelSwitch Android键盘面板冲突 布 ...
- 个人经验 - Android的RelativeLayout布局的layout_height属性设置为wrap_content时的坑
Android的RelativeLayout布局的layout_height属性设置为wrap_content时的坑: 此坑出现的条件: 1.RelativeLayout布局的layout_heigh ...
- 关于Android滑动冲突的解决方法(二)
之前的一遍学习笔记主要就Android滑动冲突中,在不同方向的滑动所造成冲突进行了了解,这样的冲突非常easy理解,当然也非常easy解决.今天,就同方向的滑动所造成的冲突进行一下了解,这里就先以垂直 ...
- (转载)Android滑动冲突的完美解决
Android滑动冲突的完美解决 作者:softwindy_brother 字体:[增加 减小] 类型:转载 时间:2017-01-24我要评论 这篇文章主要为大家详细介绍了Android滑动冲突的完 ...
- Android菜鸟成长记7 -- Android的五大布局
Android五大布局,相信android的都了解过,今天我根据自己的学习整理一下五大布局,主要介绍的是线性布局(LiearLayout),因为,其他的布局使用率不是很高. Android的五大布局 ...
- 无废话Android之常见adb指令、电话拨号器、点击事件的4种写法、短信发送器、Android 中各种布局(1)
1.Android是什么 手机设备的软件栈,包括一个完整的操作系统.中间件.关键的应用程序,底层是linux内核,安全管理.内存管理.进程管理.电源管理.硬件驱动 2.Dalvik VM 和 JVM ...
- 14.Android之Layout布局学习
Android布局主要有5种,接下来学习总结下. 1) 最常见的线性布局 LinearLayout 线性布局是Android布局中最简单的布局,也是最常用,最实用的布局. android:orient ...
- Android中的布局优化方法
http://blog.csdn.net/rwecho/article/details/8951009 Android开发中的布局很重要吗?那是当然.一切的显示样式都是由这个布局决定的,你说能不重要吗 ...
- [置顶] Android系统五大布局详解Layout
我们知道Android系统应用程序一般是由多个Activity组成,而这些Activity以视图的形式展现在我们面前,视图都是由一个一个的组件构成的.组件就是我们常见的Button.TextEdit等 ...
随机推荐
- PAT (Basic Level) Practice 1004 成绩排名
个人练习 读入n名学生的姓名.学号.成绩,分别输出成绩最高和成绩最低学生的姓名和学号. 输入格式:每个测试输入包含1个测试用例,格式为\ 第1行:正整数n 第2行:第1个学生的姓名 学号 成绩 第3行 ...
- 第一章 UNIX 基础知识
1.1 Unix体系结构 OS定义为一种软件,它控制计算机硬件资源,提供程序运行环境,一般称其为内核(kernel),它体积小,位于环境中心. 内核的接口为系统调用(system call),共用函数 ...
- 4、spring boot 配置文件之profile
Profile 1.多Profile文件 我们在主配置文件编写的时候,文件名可以是 application-{profile}.properties/yml 默认使用application.prop ...
- Spring---加载配置文件的几种方法(org.springframework.beans.factory.BeanDefinitionStoreException)
Spring中的几种容器都支持使用xml装配bean,包括:XmlBeanFactory ,ClassPathXmlApplicationContext ,FileSystemXmlApplicati ...
- Qsys配置生成nios系统模块
1. 本次使用的是别人写好的例程,主要研究学习,使用quartus 11打开工程 2. bdf文件是块编辑器的,相当于原理图,以前只在用NIOS的时候会用到这种方式.接下来新建一个工程,添加原理图元件 ...
- Postman-进阶(2)
Postman-进阶(2) Postman-简单使用 Postman-进阶使用 Postman-CI集成Jenkins 管理请求 保存请求-添加“打开百度首页请求” 设置请求方式为Get,地址为www ...
- 《1024伐木累》-小白篇之丽jie(结束篇)-总章节六
往期回顾: 机缘巧合,月侠发现了老王和他心仪女孩儿的秘密,这让他倍感愤怒,一年以后,丽姐又在去往老王家的路上,这让月侠感到历史即将重新上演,他想拦住丽姐,可恰巧丽姐手机没电,失去了联系. 小序 有人 ...
- React + webpack 快速搭建开发环境
因网上大多React + webpack快速搭建的运行不起来,便自行写了一个.在搭建开发环境的前需安装nodejs,npm. 新建一个工作目录,比如叫reactdome,在reactdome目录中运行 ...
- python学习笔记五:模块和包
一.模块用import导入 cal.py: #!/usr/bin/python def add(x,y): return x+y if __name__ == '__main__': print ad ...
- ZOJ 3606 Lazy Salesgirl ( 线段树 + 思路 )
卖切糕的小女孩 http://www.cnblogs.com/wuyiqi/archive/2012/04/28/2474672.html #include <cstdio> #inclu ...