zoukankan      html  css  js  c++  java
  • Android键盘面板冲突 布局闪动处理方案

    转:来自Android键盘面板冲突 布局闪动处理方案

    起源,之前在微信工作的时候,为了给用户带来更好的基础体验,做了很多尝试,踩了很多输入法的坑,特别是动态调整键盘高度,二级页面是透明背景,魅族早期的Smart bar等, 后来逐一完善了,考虑到拥抱开源,看业界还是有很多应用存在类似问题。就有了这个repo

    之前有写过一篇核心思想: Switching between the panel and the keyboard in Wechat

    Android键盘面板冲突 布局闪动处理方案Android键盘面板冲突 布局闪动处理方案 Android键盘面板冲突 布局闪动处理方案Android键盘面板冲突 布局闪动处理方案

    欢迎提交 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

    Android键盘面板冲突 布局闪动处理方案

    I. AndroidManifest

    可直接参照: AndroidManifest.xml

    对应的Activity,在AndroidManifest中配置android:windowSoftInputMode=adjustResize

    <manifest
      ...>
      <application
        ...>
    
        <activity
          android:name=".activity.ChattingActivity"
          android:windowSoftInputMode=adjustResize"/>
          ...
      </application>
      ...
    </manifest>
    

    II. 需要处理页面的layout xml

    可直接参照: activity_chatting_resolved.xml

    1. 需要用到 最上层布局 (KPSwitchRootFrameLayout/KPSwitchRootLinearLayout/KPSwitchRootRelativeLayout)
    2. 需要用到 面板布局(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:

    可直接参照: ChattingResolvedActivity.java

    1. 处理一些事件(KPSwitchConflictUtil)
    2. 键盘状态(高度与显示与否)监听(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

    Android键盘面板冲突 布局闪动处理方案

    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:

    可直接参照: ChattingResolvedFullScreenActivity.java

    1. 主要是处理一些事件(KPSwitchConflictUtil)
    2. 键盘状态(高度与显示与否)监听(KeyboardUtil#attach())
    3. 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);
    }

    基本原理

    项目描述: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
     

    分支代码更新时间:2017-03-09

    开发语言:Java

    下载ZIP
  • 相关阅读:
    SQL Server 2005高可用性之镜像功能
    Linux的常见问题解答和管理技巧
    安装sharepoint server 2007步骤
    CISCO 中对OSI的解释
    CISCO 2600 密码恢复
    三层交换机与路由器的比较
    PHP的注释
    php的变量、常量和数据类型
    操作符与控制结构
    【1】淘宝sdk装修入门引言
  • 原文地址:https://www.cnblogs.com/xinmengwuheng/p/6655095.html
Copyright © 2011-2022 走看看