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 表情面板和软键盘切换时跳闪问题的解决方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • Android判断软键盘弹出并隐藏的简单完美解决方法(推荐)

    最近项目中有一个编辑框,下面是个ListView.在触发编辑框弹出软键盘后,ListView还能滑动,并且ListView的item还能响应单击.这样的体验效果很不好.于是便想在滑动或单击item时判断键盘是否弹出,若弹出,则把它隐藏. 网上一搜,发现Android并没有直接提供软键盘的弹出与隐藏判断,一些解决方案诸如判断父控件的高度或者判断 if(getWindow().getAttributes().softInputMode==WindowManager.LayoutParams.SOFT

  • Android 软键盘弹出时把原来布局顶上去的解决方法

    键盘弹出时,会将布局底部的导航条顶上去. 解决办法: 在mainfest.xml中,在和导航栏相关的activity中加: <activity android:name=".filing.MainActivity" android:windowSoftInputMode="adjustResize|stateHidden" /> windowSoftInputMode 属性解释: 活动的主窗口如何与包含屏幕上的软键盘窗口交互.这个属性的设置将会影响两件事

  • Android判断软键盘的状态和隐藏软键盘的简单实例

    之前本人也遇到一个关于获取软键盘的状态的问题,在网上找了很多资料,基本上回答都是用getWindow().getAttributes().softInputMode==WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED来判断软键盘是否打开,若相等则为打开,然后你就可以根据这段代码进行后续操作了.但是我试了好久,不管是软键盘弹出还是关闭getWindow().getAttributes().softInputMode的值一直是0,至于为什

  • Android输入法与表情面板切换时的界面抖动问题解决方法

    昨天琢磨了下Android的输入法弹出模式,突然发现利用动态切换输入法的弹出模式可以解决输入法抖动的问题.具体是怎样的抖动呢?我们先看微博的反面教材. [具体表现为:表情面板与输入法面板高度不一致,从而导致弹出输入法(layout被挤压)时,同时又需要隐藏表情面板(layout被拉升),最终让界面产生了高度差抖动,所以在切换时明显会有不大好的抖动体验)] 使用了解决抖动的解决方案后,效果如下: [这样的方案明显比微博的切换更平滑] 老样子,先说思路.主要我们要用到两个输入法弹出模式,分别是:ad

  • Android 点击屏幕空白处收起输入法软键盘(手动打开)

    很多时候,我们在使用应用时,会出现输入法软键盘弹出的问题,通常情况下,我们默认会使用户点击返回键或者下一步对软键盘进行隐藏.为了更好的体验,我们可以实现当用户使用完毕软键盘时.点击屏幕空白区域即可实现收起输入法软键盘功能.下面给大家介绍下实现方法. 1.//隐藏软键盘   在Java文件: InputMethodManager m = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE); m .

  • Android开发软键盘遮挡登陆按钮的完美解决方案

    在应用登陆页面我们需要填写用户名和密码.当填写这些信息的时候,软键盘会遮挡登陆按钮,这使得用户体验较差,所以今天就来解决这个问题 1:登陆布局界面如下 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="

  • Android软键盘弹出时的界面控制方法

    本文实例讲述了Android软键盘弹出时的界面控制方法.分享给大家供大家参考,具体如下: 有时候androidactivity弹出软键盘后布局改变 下面有三种模式可以改变软键盘弹出以后的显示形式 模式一:压缩模式软键盘弹出以后,会压缩原先的大小 我们可以在AndroidManifet.xml中对Activity进行设置.如: android:windowSoftInputMode="stateUnchanged|adjustResize" 模式二:平移模式 软键盘弹出以后,不会压缩原先

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

    现在很多应用都会在让用户输入各种文本信息的时候同时多提供一个表情面板,这样就会出现一个问题,即表情面板的跳闪问题要输入文本信息,那固然是需要弹出软键盘,在软键盘显示的情况下,此时如果要切换显示出表情面板,由于表情面板不可能和用户的软键盘高度恰好一样,此外由于控件的上下移位,就会出现表情面板的跳闪现象 在点击切换按钮的时候,表情面板会先向上跳,然后再往下移,这样就会带来很差的用户体验,效果如下图所示: 这里提供一个解决方案,使软键盘和表情面板可以很自然地切换,效果如下图所示: 解决思路主要是这样:

  • 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 实现数字九宫格软键盘

    前言 一开始大概是这种 需求 组长说 要不搞一个自定义软键盘吧 数字搞大点 方便外卖员输入数字 我设置了输入EditText的输入格式为Number 还是不行 那就开搞吧 先来看下实现的效果图吧 实现效果GIF 实现代码 自定义View 一个NineNumericKeyboardView /** * Author by Lyu * Date on 2021/5/26-19:55 * Description:九宫格数字软键盘 */ public class NineNumericKeyboardV

  • Android中点击隐藏软键盘最佳方法

    实现功能:点击EditText,软键盘出现并且不会隐藏,点击或者触摸EditText以外的其他任何区域,软键盘被隐藏: 1.重写dispatchTouchEvent()方法,获取当前触摸事件为DOWN的时候隐藏软键盘 @Override public boolean dispatchTouchEvent(MotionEvent ev) { //Finger touch screen event if (ev.getAction() == MotionEvent.ACTION_DOWN) { //

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

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

  • Android开发实现按钮点击切换背景并修改文字颜色的方法

    本文实例讲述了Android开发实现按钮点击切换背景并修改文字颜色的方法.分享给大家供大家参考,具体如下: 其实原理很简单,用到的是selector,用来设置android:background和android:textcolor属性,selector可以用来设置默认时候.点击时候的背景图片和文字颜色的属性,过程如下: 这两个文件如下: 1.当点击按钮,改变文字的颜色: <?xml version="1.0" encoding="utf-8"?> <

  • Android Studio导入Eclipse项目时.so库文件的解决方法

    最近,将一个包含有百度地图SDK的Eclipse工程导入到Android Studio环境下时,运行进入App地图窗口出现了闪退,错误提示:java.lang.UnsatisfiedLinkError: No implementation found for long com.baidu.p--. 这是因为在Android Studio上导入so文件的方式和Eclipse不同. 解决方法有两种: 1.如果是直接在libs目录下创建子目录armeabi放置.so文件(针对Eclipse结构目录),

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

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

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

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

随机推荐