Android中聊天界面鍵盤面板沖突、布局閃動處理、表情輸入與鍵盤輸入適配各種主題標題欄listview+edittext+button沖突完美解決


轉載自:http://blog.csdn.net/yanliabcd/article/details/78389131

github上項目地址:https://github.com/604982372/InputConflict.git

       即時通訊的聊天界面表情跟輸入法切換的功能困擾了我很久,在網上找各路大神的demo,無奈發現改了個主題或者設置下標題欄顏色,沖突還是出來了。最終決定自己研究一個能夠適配各種主題、無論設置標題欄顏色與否都能處理沖突的demo。先來看看效果圖(左邊的不設置標題欄顏色,右邊的圖設置標題欄顏色)。

        

1.去除是否設置狀態欄干擾因素:android:fitsSystemWindows="true"。

        fitsSystemWindows 是在 android 4.4 中引入的。 System windows 顧名思義就是系統窗口,系統在這里顯示系統一些屬性和操作區域,比如 最上方的狀態欄,以及沒有實體按鍵的最下方的虛擬導航欄。

    大部分的時候,你的應用都不會在狀態欄和導航欄下面顯示內容,如果你需要在他們下面顯示內容,則需要確保你應用的可交互控件(比如按鈕)不要顯示在系統窗口下面了。 android:fitsSystemWindows=“true” 默認行為就是通過在 View 上設置和系統窗口一樣高度的邊框(padding )來確保你的內容不會出現到系統窗口下面。使用 fitsSystemWindows 有如下幾點需要注意: 

·fitsSystemWindows 按照深度優先的方式其作用,所以使用該屬性的 View 的順序是有要求的,如果第一個 View   使用了 inset (系統窗口的尺寸)則會導致其他 View 尺寸不一樣。
·Inset 總是相對於全屏幕的,Inset 可能在 View layout 之前就已經應用了,所以在設置 View 的 padding 之前   View 並不知道其具體相對於系統窗口的位置。
·View 的其他 padding 值被重新改寫了,在使用 fitsSystemWindows 為 true 的View 上設置 padding 值(paddingLeft/paddingTop/ 等)是沒有效果的。
實際效果: 
當status bar為透明或半透明時(4.4以上),系統會設置view的paddingTop值為一個適合的值(status bar的高度)讓view的內容不被上拉到狀態欄,當在不占據status bar的情況下(4.4以下)會設置paddingTop值為0(因為沒有占據status bar所以不用留出空間)。

提示:如果android:fitsSystemWindows不設置或者設置為false,在4.4手機運行在設置狀態欄的情況下將會出現下圖有圖中的情況

  

2.將覆蓋在主題中設置的值,設置除"stateUnspecified"和"adjustUnspecified"以外的值。

各值的含義:
(1)stateUnspecified:軟鍵盤的狀態並沒有指定,系統將選擇一個合適的狀態或依賴於主題的設置
(2)stateUnchanged:當這個activity出現時,軟鍵盤將一直保持在上一個activity里的狀態,無論是隱藏還是顯示
(3)stateHidden:用戶選擇activity時,軟鍵盤總是被隱藏
(4)stateAlwaysHidden:當該Activity主窗口獲取焦點時,軟鍵盤也總是被隱藏的
(5)stateVisible:軟鍵盤通常是可見的
(6)stateAlwaysVisible:用戶選擇activity時,軟鍵盤總是顯示的狀態
(7)adjustUnspecified:默認設置,通常由系統自行決定是隱藏還是顯示
(8)adjustResize:該Activity總是調整屏幕的大小以便留出軟鍵盤的空間
(9)adjustPan:當前窗口的內容將自動移動以便當前焦點從不被鍵盤覆蓋和用戶能總是看到輸入內容的部分

3.通過監聽鍵盤打開或關閉來切換表情欄和輸入法

private class KeyboardOnGlobalChangeListener implements ViewTreeObserver.OnGlobalLayoutListener {  
        int mScreenHeight = 0;  
        Rect mRect = new Rect();  
  
        private int getScreenHeight() {  
            if (mScreenHeight > 0) {  
                return mScreenHeight;  
            }  
            mScreenHeight = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE))  
                    .getDefaultDisplay().getHeight();  
            return mScreenHeight;  
        }  
  
        @Override  
        public void onGlobalLayout() {  
            // 獲取當前頁面窗口的顯示范圍  
            getWindowVisibleDisplayFrame(mRect);  
            int screenHeight = getScreenHeight();  
            int keyboardHeight = screenHeight - mRect.bottom; // 輸入法的高度  
            boolean isActive = false;  
            if (Math.abs(keyboardHeight) > screenHeight / 5) {  
                isActive = true; // 超過屏幕五分之一則表示彈出了輸入法  
            }  
            mIsKeyboardActive = isActive;  
            onKeyboardStateChanged(mIsKeyboardActive, keyboardHeight);  
        }  
    }  
private void onKeyboardStateChanged(boolean isActive, int keyboardHeight) {  
        if (isActive) {  
            mSwitchBtn.setFocusable(false);  
            mSwitchBtn.setFocusableInTouchMode(false);  
            mEditText.requestFocus();  
            if (mSwitchBtn.isSelected()) { // 表情打開狀態下  
                mPanelView.setVisibility(View.GONE);  
                mSwitchBtn.setSelected(false);  
            }  
            SPUtils.saveInt(mContext,  COLUMN_NAME, keyboardHeight);  
            ViewGroup.LayoutParams params = mPanelView.getLayoutParams();  
            if (!(params.height == keyboardHeight)) {  
                params.height = keyboardHeight;  
                mPanelView.setLayoutParams(params);  
            }  
        } else {  
            if (mSwitchBtn.isSelected()) {  
                return;  
            }  
        }  
    }
}
 

4.通過設置輸入模式和延時隱藏控件來避免閃爍的情況

if (mSwitchBtn.isSelected()) {  
                               mSwitchBtn.setBackgroundResource(R.drawable.icon_key);  
                               // 設置為不會調整大小,以便輸入彈起時布局不會改變。若不設置此屬性,輸入法彈起時布局會閃一下  
                               ((Activity) mContext).getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);  
                               mPanelView.setVisibility(View.VISIBLE);  
                           } else {  
                               mSwitchBtn.setBackgroundResource(R.drawable.icon_more);  
                               imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, InputMethodManager.HIDE_IMPLICIT_ONLY);  
                               mSwitchBtn.postDelayed(new Runnable() {  
                                   @Override  
                                   public void run() { // 輸入法彈出之后,重新調整  
                                       mPanelView.setVisibility(View.GONE);  
                                       ((Activity) mContext).getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE  
                                               | WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);  
                                   }  
                               }, 250); // 延遲一段時間,等待輸入法完全彈出*/  
                           }

5.使用方式,在布局文件中使用即可:

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout  
    android:id="@+id/activity_chat_ll"  
    xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:app="http://schemas.android.com/apk/res-auto"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:clipToPadding="true"  
    android:fitsSystemWindows="true"  
    android:orientation="vertical">  
  
    <View  
        android:layout_width="match_parent"  
        android:layout_height="60dp"  
        android:background="@color/colorAccent"  
        android:visibility="gone"  
    />  
  
    <cn.xiwu.inputconflict.MyView.InputConflictView  
        android:id="@+id/keyboard_layout"  
        android:layout_width="wrap_content"  
        android:layout_height="match_parent"  
        android:orientation="vertical"  
        app:editText="@+id/chat_input_et"  
        app:listView="@+id/lv_chatting"  
        app:panelView="@+id/panel_view"  
        app:switchBtn="@+id/add_menu_btn">  
        <ListView  
            android:id="@+id/lv_chatting"  
            android:layout_width="match_parent"  
            android:layout_height="0dp"  
            android:layout_weight="1"  
            android:background="#eeeeee"  
            android:cacheColorHint="#00000000"  
            android:divider="@null"  
            android:dividerHeight="10px"  
            android:listSelector="#00000000"  
            android:scrollbarStyle="outsideOverlay"  
            android:transcriptMode="normal"/>  
  
        <LinearLayout  
            android:id="@+id/input_all_ll"  
            android:layout_width="match_parent"  
            android:layout_height="wrap_content"  
            android:background="@android:color/white"  
            android:minHeight="42dp"  
            android:orientation="horizontal"  
            android:paddingBottom="6dp"  
            android:paddingLeft="10dp"  
            android:paddingRight="10dp"  
            android:paddingTop="6dp"  
        >  
            <EditText  
                android:id="@+id/chat_input_et"  
                android:layout_width="0dp"  
                android:layout_height="wrap_content"  
                android:layout_gravity="bottom"  
                android:layout_marginLeft="3dp"  
                android:layout_marginRight="6dp"  
                android:layout_weight="1"  
                android:background="@drawable/bg_chat_input"  
                android:clickable="true"  
                android:hint="請輸入短信"  
                android:maxLines="3"  
                android:minHeight="34dp"  
                android:paddingBottom="7dp"  
                android:paddingLeft="10dp"  
                android:paddingRight="10dp"  
                android:paddingTop="7dp"  
                android:textColorHint="#cecaca"  
                android:textSize="16sp"/>  
            <FrameLayout  
                android:layout_width="wrap_content"  
                android:layout_height="match_parent">  
                <TextView  
                    android:id="@+id/send_msg_tv"  
                    android:layout_width="56dp"  
                    android:layout_height="34dp"  
                    android:layout_centerInParent="true"  
                    android:layout_gravity="bottom"  
                    android:background="@drawable/bg_chat_shape"  
                    android:clickable="true"  
                    android:gravity="center"  
                    android:text="發送"  
                    android:textColor="#fff"  
                    android:visibility="gone"/>  
                <ImageButton  
                    android:id="@+id/add_menu_btn"  
                    android:layout_width="wrap_content"  
                    android:layout_height="wrap_content"  
                    android:layout_gravity="center"  
                    android:layout_marginLeft="8dp"  
                    android:layout_marginRight="5dp"  
                    android:adjustViewBounds="true"  
                    android:background="@drawable/icon_more"  
                    android:gravity="center"/>  
            </FrameLayout>  
        </LinearLayout>  
        <include  
            android:id="@+id/panel_view"  
            layout="@layout/panel_view"  
            android:layout_width="match_parent"  
            android:layout_height="200dp"  
            android:visibility="gone"/>  
    </cn.xiwu.inputconflict.MyView.InputConflictView>  
</LinearLayout>  

github上項目地址:https://github.com/604982372/InputConflict.git


免責聲明!

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



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