Android 表情面板和软键盘切换时跳闪问题的解决方法

现在很多应用都会在让用户输入各种文本信息的时候同时多提供一个表情面板,这样就会出现一个问题,即表情面板的跳闪问题要输入文本信息,那固然是需要弹出软键盘,在软键盘显示的情况下,此时如果要切换显示出表情面板,由于表情面板不可能和用户的软键盘高度恰好一样,此外由于控件的上下移位,就会出现表情面板的跳闪现象

在点击切换按钮的时候,表情面板会先向上跳,然后再往下移,这样就会带来很差的用户体验,效果如下图所示:

这里提供一个解决方案,使软键盘和表情面板可以很自然地切换,效果如下图所示:

解决思路主要是这样:系统在弹出软键盘时,会将内容输入框View以及其之上的View都给顶上去,当切换到表情面板时,只有将表情面板的高度保持为和软键盘的高度一致,才能自然地切换。此外,还需要将内容输入框View以及其之上的View的位置固定住,这样才不会出现跳闪问题

主要的操作逻辑都在 EmojiKeyboard 类中

/** * 作者: chenZY * 时间: 2017/8/26 18:12 * 描述: */ public class EmojiKeyboard { private Activity activity; //文本输入框 private EditText editText; //表情面板 private View emojiPanelView; //内容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(); } /** * 如果之前没有保存过键盘高度值 * 则在进入Activity时自动打开键盘,并把高度值保存下来 */ private void init() { if (!sharedPreferences.contains(KEY_SOFT_KEYBOARD_HEIGHT)) { handler.postDelayed(new Runnable() { @Override public void run() { showSoftKeyboard(true); } }, 200); } } /** * 当点击返回键时需要先隐藏表情面板 */ public boolean interceptBackPress() { if (emojiPanelView.isShown()) { hideEmojiPanel(false); return true; } return false; } /** * 锁定内容View以防止跳闪 */ private void lockContentViewHeight() { LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) contentView.getLayoutParams(); layoutParams.height = contentView.getHeight(); layoutParams.weight = 0; } /** * 释放锁定的内容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); //屏幕当前可见高度,不包括状态栏 int displayHeight = rect.bottom - rect.top; //屏幕可用高度 int availableHeight = ScreenUtils.getAvailableScreenHeight(activity); //用于计算键盘高度 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) { // 因为考虑到用户可能会主动调整键盘高度,所以只能是每次获取到键盘高度时都将其存储起来 sharedPreferences.edit().putInt(KEY_SOFT_KEYBOARD_HEIGHT, softInputHeight).apply(); } return softInputHeight; } /** * 获取本地存储的键盘高度值或者是返回默认值 */ private int getSoftKeyboardHeightLocalValue() { return sharedPreferences.getInt(KEY_SOFT_KEYBOARD_HEIGHT, SOFT_KEYBOARD_HEIGHT_DEFAULT); } /** * 判断是否显示了键盘 */ private boolean isSoftKeyboardShown() { return getSoftKeyboardHeight() != 0; } /** * 令编辑框获取焦点并显示键盘 */ 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(); } } /** * 隐藏表情面板,同时指定是否随后开启键盘 */ 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 解决表情面板和软键盘切换时跳闪的问题

总结

以上所述是小编给大家介绍的Android 表情面板和软键盘切换时跳闪问题的解决方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

时间: 2024-09-13 21:02:00

Android 表情面板和软键盘切换时跳闪问题的解决方法的相关文章

android避免弹出软键盘遮盖listview的简单方法_Android

做开发的时候,我们常常把listview放中间,然后底部放置一个edittext控件,这样导致editext控件获得焦点的时候,输入法弹出,Edittext控件上移,挡住了listview的部分数据,这样不太美观.所以,我们需要让listview也跟着上移,所以需要: 方法一:在xml文件中,设置listview属性时候加上这句就ok了android:transcriptMode="normal": 方法二:在程序中加入语句: listView.setTranscriptMode(Li

android TextView 弹出软键盘

问题描述 android TextView 弹出软键盘 背景:我想在一个ViewGroup上添加一个TextView ,操作说明,点击ViewGroup中央,出现一个光标在那并弹出软键盘,在键盘上输入文字,对应的光标的位置会出现键盘上输入的文字,点击换行按钮随之换行继续输入,请问如何实现? 解决方案 android系统里, TextView得到焦点后会自动弹出软键盘 至于输入多行的问题,可以参考这个 Android TextView多行文本滚动实现 http://blog.csdn.net/zz

Android 显示和隐藏软键盘的方法(手动)_Android

在Android开发中,经常会有一个需求,做完某项操作后,隐藏键盘,也即让Android中的软键盘不显示.今天,和大家分享如何利用代码来实现对Android的软件盘的隐藏.显示的操作. 1.方法一(如果输入法在窗口上已经显示,则隐藏,反之则显示) InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.toggleSoftInput(0, InputMeth

Android 显示和隐藏软键盘的方法(手动)

在Android开发中,经常会有一个需求,做完某项操作后,隐藏键盘,也即让Android中的软键盘不显示.今天,和大家分享如何利用代码来实现对Android的软件盘的隐藏.显示的操作. 1.方法一(如果输入法在窗口上已经显示,则隐藏,反之则显示) InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.toggleSoftInput(0, InputMeth

android避免弹出软键盘遮盖listview的简单方法

做开发的时候,我们常常把listview放中间,然后底部放置一个edittext控件,这样导致editext控件获得焦点的时候,输入法弹出,Edittext控件上移,挡住了listview的部分数据,这样不太美观.所以,我们需要让listview也跟着上移,所以需要: 方法一:在xml文件中,设置listview属性时候加上这句就ok了android:transcriptMode="normal": 方法二:在程序中加入语句: listView.setTranscriptMode(Li

Android开发中Activity之间切换出现短暂黑屏的解决方法_Android

本文实例讲述了Android开发中Activity之间切换出现短暂黑屏的解决方法.分享给大家供大家参考,具体如下: 在默认情况下,Android应用程序启动时,会有一个黑屏的时期,原因是,首个activity会加载一些数据,比如初始化列表数据.向服务器发送请求获取数据等等.同样,使用startActivity(inte -- 在默认情况下,Android应用程序启动时,会有一个黑屏的时期,原因是,首个activity会加载一些数据,比如初 始化列表数据.向服务器发送请求获取数据等等.同样,使用s

Android开发中Activity之间切换出现短暂黑屏的解决方法

本文实例讲述了Android开发中Activity之间切换出现短暂黑屏的解决方法.分享给大家供大家参考,具体如下: 在默认情况下,Android应用程序启动时,会有一个黑屏的时期,原因是,首个activity会加载一些数据,比如初始化列表数据.向服务器发送请求获取数据等等.同样,使用startActivity(inte -- 在默认情况下,Android应用程序启动时,会有一个黑屏的时期,原因是,首个activity会加载一些数据,比如初 始化列表数据.向服务器发送请求获取数据等等.同样,使用s

php生成二维码时出现中文乱码的解决方法_php技巧

本文实例讲述了php生成二维码时出现中文乱码的解决方法.分享给大家供大家参考.具体分析如下: 最近做了个扫描二维码得到vcard的项目,遇到一个问题,有一部分生成完的二维码,用android系统手机扫描后得到的vcard中的中文姓名是乱码,经过比对发现,这部分vcard中ORG这个类型没有内容,随即判断没内容就加上一个固定的字符串,这样乱码的问题得以解决. php生成二维码的几种方式 1.google开放api,代码如下: 复制代码 代码如下: $urlToEncode="http://www.

Android Listview 滑动过程中提示图片重复错乱的原因及解决方法_Android

主要分析Android中Listview滚动过程造成的图片显示重复.错乱.闪烁的原因及解决方法,顺便跟进Listview的缓存机制. 1.原因分析 Listview item 缓存机制:为了使得性能更优,Listview会缓存行item(某行对应的view).listview通过adapter的getview函数获得每行的item.滑动过程中, a.如果某行item已经划出屏幕,若该item不在缓存内,则put进缓存,否则更新缓存: b.获取滑入屏幕的行item之前会先判断缓存中是否有可用的it