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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM