Android-->如何優雅的切換表情和鍵盤(原理)
阿新 • • 發佈:2019-01-04
網上有很多開源的專案, 但通常都封裝的很複雜, 並不能很友好的自定義, 甚至原理都看不清楚.
沒關係, 這篇文章就是講原理的. 讓你分分鐘都能自定義一個出來.
正常情況下, 當我們切換表情和鍵盤的時候, 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 歡迎您的加入.