Android 表情面板和軟鍵盤切換時(shí)跳閃問題的解決方法
現(xiàn)在很多應(yīng)用都會(huì)在讓用戶輸入各種文本信息的時(shí)候同時(shí)多提供一個(gè)表情面板,這樣就會(huì)出現(xiàn)一個(gè)問題,即表情面板的跳閃問題要輸入文本信息,那固然是需要彈出軟鍵盤,在軟鍵盤顯示的情況下,此時(shí)如果要切換顯示出表情面板,由于表情面板不可能和用戶的軟鍵盤高度恰好一樣,此外由于控件的上下移位,就會(huì)出現(xiàn)表情面板的跳閃現(xiàn)象
在點(diǎn)擊切換按鈕的時(shí)候,表情面板會(huì)先向上跳,然后再往下移,這樣就會(huì)帶來很差的用戶體驗(yàn),效果如下圖所示:

這里提供一個(gè)解決方案,使軟鍵盤和表情面板可以很自然地切換,效果如下圖所示:

解決思路主要是這樣:系統(tǒng)在彈出軟鍵盤時(shí),會(huì)將內(nèi)容輸入框View以及其之上的View都給頂上去,當(dāng)切換到表情面板時(shí),只有將表情面板的高度保持為和軟鍵盤的高度一致,才能自然地切換。此外,還需要將內(nèi)容輸入框View以及其之上的View的位置固定住,這樣才不會(huì)出現(xiàn)跳閃問題
主要的操作邏輯都在 EmojiKeyboard 類中
/**
* 作者: chenZY
* 時(shí)間: 2017/8/26 18:12
* 描述:
*/
public class EmojiKeyboard {
private Activity activity;
//文本輸入框
private EditText editText;
//表情面板
private View emojiPanelView;
//內(nèi)容View,即除了表情布局和輸入框布局以外的布局
//用于固定輸入框一行的高度以防止跳閃
private View contentView;
private InputMethodManager inputMethodManager;
private SharedPreferences sharedPreferences;
private static final String EMOJI_KEYBOARD = "EmojiKeyboard";
private static final String KEY_SOFT_KEYBOARD_HEIGHT = "SoftKeyboardHeight";
private static final int SOFT_KEYBOARD_HEIGHT_DEFAULT = 654;
private Handler handler;
public EmojiKeyboard(Activity activity, EditText editText, View emojiPanelView, View emojiPanelSwitchView, View contentView) {
init(activity, editText, emojiPanelView, emojiPanelSwitchView, contentView);
}
private void init(Activity activity, EditText editText, View emojiPanelView, View emojiPanelSwitchView, View contentView) {
this.activity = activity;
this.editText = editText;
this.emojiPanelView = emojiPanelView;
this.contentView = contentView;
this.editText.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(final View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP && EmojiKeyboard.this.emojiPanelView.isShown()) {
lockContentViewHeight();
hideEmojiPanel(true);
unlockContentViewHeight();
}
return false;
}
});
this.contentView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
if (EmojiKeyboard.this.emojiPanelView.isShown()) {
hideEmojiPanel(false);
} else if (isSoftKeyboardShown()) {
hideSoftKeyboard();
}
}
return false;
}
});
//用于彈出表情面板的View
emojiPanelSwitchView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (EmojiKeyboard.this.emojiPanelView.isShown()) {
lockContentViewHeight();
hideEmojiPanel(true);
unlockContentViewHeight();
} else {
if (isSoftKeyboardShown()) {
lockContentViewHeight();
showEmojiPanel();
unlockContentViewHeight();
} else {
showEmojiPanel();
}
}
}
});
this.inputMethodManager = (InputMethodManager) this.activity.getSystemService(Context.INPUT_METHOD_SERVICE);
this.sharedPreferences = this.activity.getSharedPreferences(EMOJI_KEYBOARD, Context.MODE_PRIVATE);
this.activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
this.handler = new Handler();
init();
}
/**
* 如果之前沒有保存過鍵盤高度值
* 則在進(jìn)入Activity時(shí)自動(dòng)打開鍵盤,并把高度值保存下來
*/
private void init() {
if (!sharedPreferences.contains(KEY_SOFT_KEYBOARD_HEIGHT)) {
handler.postDelayed(new Runnable() {
@Override
public void run() {
showSoftKeyboard(true);
}
}, 200);
}
}
/**
* 當(dāng)點(diǎn)擊返回鍵時(shí)需要先隱藏表情面板
*/
public boolean interceptBackPress() {
if (emojiPanelView.isShown()) {
hideEmojiPanel(false);
return true;
}
return false;
}
/**
* 鎖定內(nèi)容View以防止跳閃
*/
private void lockContentViewHeight() {
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) contentView.getLayoutParams();
layoutParams.height = contentView.getHeight();
layoutParams.weight = 0;
}
/**
* 釋放鎖定的內(nèi)容View
*/
private void unlockContentViewHeight() {
handler.postDelayed(new Runnable() {
@Override
public void run() {
((LinearLayout.LayoutParams) contentView.getLayoutParams()).weight = 1;
}
}, 200);
}
/**
* 獲取鍵盤的高度
*/
private int getSoftKeyboardHeight() {
Rect rect = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
//屏幕當(dāng)前可見高度,不包括狀態(tài)欄
int displayHeight = rect.bottom - rect.top;
//屏幕可用高度
int availableHeight = ScreenUtils.getAvailableScreenHeight(activity);
//用于計(jì)算鍵盤高度
int softInputHeight = availableHeight - displayHeight - ScreenUtils.getStatusBarHeight(activity);
Log.e("TAG-di", displayHeight + "");
Log.e("TAG-av", availableHeight + "");
Log.e("TAG-so", softInputHeight + "");
if (softInputHeight != 0) {
// 因?yàn)榭紤]到用戶可能會(huì)主動(dòng)調(diào)整鍵盤高度,所以只能是每次獲取到鍵盤高度時(shí)都將其存儲(chǔ)起來
sharedPreferences.edit().putInt(KEY_SOFT_KEYBOARD_HEIGHT, softInputHeight).apply();
}
return softInputHeight;
}
/**
* 獲取本地存儲(chǔ)的鍵盤高度值或者是返回默認(rèn)值
*/
private int getSoftKeyboardHeightLocalValue() {
return sharedPreferences.getInt(KEY_SOFT_KEYBOARD_HEIGHT, SOFT_KEYBOARD_HEIGHT_DEFAULT);
}
/**
* 判斷是否顯示了鍵盤
*/
private boolean isSoftKeyboardShown() {
return getSoftKeyboardHeight() != 0;
}
/**
* 令編輯框獲取焦點(diǎn)并顯示鍵盤
*/
private void showSoftKeyboard(boolean saveSoftKeyboardHeight) {
editText.requestFocus();
inputMethodManager.showSoftInput(editText, 0);
if (saveSoftKeyboardHeight) {
handler.postDelayed(new Runnable() {
@Override
public void run() {
getSoftKeyboardHeight();
}
}, 200);
}
}
/**
* 隱藏鍵盤
*/
private void hideSoftKeyboard() {
inputMethodManager.hideSoftInputFromWindow(editText.getWindowToken(), 0);
}
/**
* 顯示表情面板
*/
private void showEmojiPanel() {
int softKeyboardHeight = getSoftKeyboardHeight();
if (softKeyboardHeight == 0) {
softKeyboardHeight = getSoftKeyboardHeightLocalValue();
} else {
hideSoftKeyboard();
}
emojiPanelView.getLayoutParams().height = softKeyboardHeight;
emojiPanelView.setVisibility(View.VISIBLE);
if (emojiPanelVisibilityChangeListener != null) {
emojiPanelVisibilityChangeListener.onShowEmojiPanel();
}
}
/**
* 隱藏表情面板,同時(shí)指定是否隨后開啟鍵盤
*/
private void hideEmojiPanel(boolean showSoftKeyboard) {
if (emojiPanelView.isShown()) {
emojiPanelView.setVisibility(View.GONE);
if (showSoftKeyboard) {
showSoftKeyboard(false);
}
if (emojiPanelVisibilityChangeListener != null) {
emojiPanelVisibilityChangeListener.onHideEmojiPanel();
}
}
}
public interface OnEmojiPanelVisibilityChangeListener {
void onShowEmojiPanel();
void onHideEmojiPanel();
}
private OnEmojiPanelVisibilityChangeListener emojiPanelVisibilityChangeListener;
public void setEmoticonPanelVisibilityChangeListener(OnEmojiPanelVisibilityChangeListener emojiPanelVisibilityChangeListener) {
this.emojiPanelVisibilityChangeListener = emojiPanelVisibilityChangeListener;
}
}
這里也提供代碼下載:Android 解決表情面板和軟鍵盤切換時(shí)跳閃的問題
總結(jié)
以上所述是小編給大家介紹的Android 表情面板和軟鍵盤切換時(shí)跳閃問題的解決方法,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
實(shí)時(shí)獲取股票數(shù)據(jù)的android app應(yīng)用程序源碼分享
本文我們分享一個(gè)實(shí)時(shí)獲取股票數(shù)據(jù)的android app應(yīng)用程序源碼分享,可以作為學(xué)習(xí)使用,本文貼出部分重要代碼,需要的朋友可以參考下本文2015-09-09
淺談Android onTouchEvent 與 onInterceptTouchEvent的區(qū)別詳解
本篇文章小編為大家介紹,Android onTouchEvent 與 onInterceptTouchEvent的區(qū)別詳解。需要的朋友參考下2013-04-04
Android基于Toolbar實(shí)現(xiàn)頂部標(biāo)題欄及后退鍵
這篇文章主要介紹了Android基于Toolbar實(shí)現(xiàn)頂部標(biāo)題欄及后退鍵,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09
Android截取視頻幀并轉(zhuǎn)化為Bitmap示例
利用MediaMetadataRetriever按照時(shí)間截取視頻并轉(zhuǎn)換為Bitmap存放于SDCard,具體實(shí)現(xiàn)如下,感興趣的朋友可以參考下哈2013-06-06
Android切換至SurfaceView時(shí)閃屏(黑屏閃一下)以及黑屏移動(dòng)問題的解決方法
本文主要介紹了Android切換至SurfaceView時(shí)閃屏(黑屏閃一下)以及黑屏移動(dòng)問題的解決方法。具有一定的參考作用,下面跟著小編一起來看下吧2017-01-01
輕松實(shí)現(xiàn)Android語音識(shí)別功能
這篇文章主要為初學(xué)者介紹了輕松實(shí)現(xiàn)Android語音識(shí)別功能的代碼,感興趣的小伙伴們可以參考一下2016-07-07
使用Android studio創(chuàng)建的AIDL編譯時(shí)找不到自定義類的解決辦法
這篇文章主要介紹了使用Android studio創(chuàng)建的AIDL編譯時(shí)找不到自定義類的解決辦法的相關(guān)資料,需要的朋友可以參考下2016-02-02
如何調(diào)用百度地圖API實(shí)現(xiàn)手機(jī)自動(dòng)定位
api手機(jī)自動(dòng)定位,通過聲明地址解析器,獲取當(dāng)前坐標(biāo),如何調(diào)用百度地圖api實(shí)現(xiàn)手機(jī)自動(dòng)定位呢?接下來,一起跟小編來學(xué)習(xí)吧。2015-09-09

