1. 程式人生 > >Android-->如何優雅的切換表情和鍵盤(原理)

Android-->如何優雅的切換表情和鍵盤(原理)

網上有很多開源的專案, 但通常都封裝的很複雜, 並不能很友好的自定義, 甚至原理都看不清楚.

沒關係, 這篇文章就是講原理的. 讓你分分鐘都能自定義一個出來.

正常情況下, 當我們切換表情和鍵盤的時候, Layout會跳動, 體驗極其差.

有幾個前提需要滿足:

<activity
    android:windowSoftInputMode="adjustResize" //這個是必須的
    android:screenOrientation="portrait"  //儘量固定為豎屏, 否則考慮的情況就多了.
/>

佈局大概是這樣的:

<SoftInputLayout
>
//這個是自定義的包裹層, 核心佈局 <LinearLayout android:layout_weight="1" > //注意這條屬性, 關鍵哦 //這裡用來放內容 </LinearLayout> <LinearLayout> //這裡用來放表情,預設情況下,表情佈局是隱藏的; </LinearLayout> </SoftInputLayout>

分析
在不顯示錶情佈局的情況下, 單純的顯示鍵盤,隱藏鍵盤. 一切都沒有問題;很正常;

但是, 如果你要顯示錶情的時候, 問題就蹦出來了;#$%^&*各種問題; 我就不描述了;寫過的你,應該懂;

解決的辦法就是:
當你點選按鈕,顯示錶情:此時需要把內容佈局的高度固定(這個高度值, 就是需要計算的關鍵之一), 其次再顯示錶情佈局.,,,沒了…

其實就是一個高度的問題, 解決了這個高度, 文章也就結束了.

高度的獲取

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh){
    //首先需要在此,記錄佈局的最大高度
    //然後當鍵盤彈出的時候, 佈局高度會變小
    //就可以計算出鍵盤的高度
    //此時你已經知道了3個高度值: 最大的佈局高度值, 當前鍵盤彈出後佈局的高度值, 以及計算出來的鍵盤高度
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    //拿到第一次的高度, 一般這個時候都是佈局的真是高度.之後resize會改變這個高度
    if (oldh == 0) {
        mRawLayoutHeight = h;
    }
    if (mRawLayoutHeight == h) {
        isSoftInputShow = false;
    } else {
        //鍵盤彈出的時候,高度會變化, 需要隱藏表情佈局
        if (mCurrentContentHeight != h) {
            fixContentLayoutHeight(mCurrentContentHeight, h);
        }
        mCurrentContentHeight = h;
        isSoftInputShow = true;
        hideEmojiLayout();
    }
    if (mOnSoftInputChangeListener != null) {
        mOnSoftInputChangeListener.onSoftInputChange(isSoftInputShow, mRawLayoutHeight, h);
    }
}

有了值之後,顯示錶情就簡單了:

顯示錶情佈局

/**
 * 強制內容和表情佈局的高度,這樣在鍵盤彈出的時候,就不會導致佈局跳動了
 */
public void showEmojiLayout() {
    hideSoftInput(getContext(), this);//不管鍵盤有沒有顯示, 先隱藏再說
    int keyboardHeight;
    if (mCurrentContentHeight == 0) {//首次進入佈局的時候,如果鍵盤之前沒有顯示過,則使用預設的高度
        keyboardHeight = getDefaultEmojiHeight();
        mCurrentContentHeight = mRawLayoutHeight - keyboardHeight;
    } else {
        keyboardHeight = mRawLayoutHeight - mCurrentContentHeight;
    }
    //主要是計算 鍵盤的高度和內容的高度, 用來固定佈局, 這樣resize 就不會跳動了;
    LayoutParams contentParams = (LayoutParams) mContentLayout.getLayoutParams();
    contentParams.height = mCurrentContentHeight;//固定內容佈局的高度
    contentParams.weight = 0;
    LayoutParams emojiParams = (LayoutParams) mEmojiLayout.getLayoutParams();
    emojiParams.height = keyboardHeight;//固定表情佈局的高度
    emojiParams.weight = 0;
    mEmojiLayout.setVisibility(VISIBLE);
    requestLayout();//重新整理一下
    isEmojiLayoutShow = true;
}

隱藏表情佈局

/**
 * 恢復成預設就行了, 這裡就簡單了許多;
 */
public void hideEmojiLayout() {
    LayoutParams params = (LayoutParams) mContentLayout.getLayoutParams();
    params.height = 0;
    params.weight = 1;//注意此處, 這裡千萬不能固定高度; 否則鍵盤彈出的時候,就看不到輸入框了...
    LayoutParams params2 = (LayoutParams) mEmojiLayout.getLayoutParams();
    params2.height = 0;
    params2.weight = 0;
    mEmojiLayout.setVisibility(GONE);
    isEmojiLayoutShow = false;
    requestLayout();
}
/**
 * 修改第一次開啟表情之前, 鍵盤沒有彈出之前的BUG.
 */
private void fixContentLayoutHeight(final int oldH, final int newH) {
    postDelayed(new Runnable() {
        @Override
        public void run() {
            LayoutParams params = (LayoutParams) mContentLayout.getLayoutParams();
            params.height = newH;
            params.weight = 0;
            requestLayout();
            unlockContentLayoutHeight();
        }
    }, 100);
}

/**
 * 此方法的作用就是在鍵盤彈出後,然後按下了鍵盤上的關閉鍵盤按鈕, 佈局能自適應.
 */
private void unlockContentLayoutHeight() {
    postDelayed(new Runnable() {
        @Override
        public void run() {
            LayoutParams params = (LayoutParams) mContentLayout.getLayoutParams();
            params.height = 0;
            params.weight = 1;
            requestLayout();
        }
    }, 300);
}

使用方法:

//當需要顯示錶情的時候呼叫:
showEmojiLayout()
//當需要隱藏表情的時候呼叫:
hideEmojiLayout()
//即可

至此: 文章就結束了,如有疑問: QQ群:274306954 歡迎您的加入.