Android获取输入法高度——输入法与页面布局无缝切换
来源:互联网 发布:剑灵捏脸数据龙男 编辑:程序博客网 时间:2024/05/28 22:09
在QQ或者微信的聊天页面,当输入法和表情栏互相切换时,过度非常自然,而且表情栏高度刚好跟输入法一样。个人感觉这种用户体验特别的好,别看这个细节小,但代码实现处理起来还是有一定难度。今天我就带大家来实现这种效果,下面是效果图:
首先,我们需要知道输入法的高度,使表情栏的高度与之保持一致。但是Android是没有提供现成的接口给开发者监听输入法的状态,因此需要自定义的KeyboardLayout,监听布局的改变,通过变化前后布局高度差计算出输入法的高度。
public class KeyboardLayout extends FrameLayout { private KeyboardLayoutListener mListener; private boolean mIsKeyboardActive = false; // 输入法是否激活 private int mKeyboardHeight = 0; // 输入法高度 public KeyboardLayout(Context context) { this(context, null, 0); } public KeyboardLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public KeyboardLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); // 监听布局变化 getViewTreeObserver().addOnGlobalLayoutListener(new KeyboardOnGlobalChangeListener()); } private class KeyboardOnGlobalChangeListener implements ViewTreeObserver.OnGlobalLayoutListener { int mScreenHeight = 0; private int getScreenHeight() { if (mScreenHeight > 0) { return mScreenHeight; } mScreenHeight = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)) .getDefaultDisplay().getHeight(); return mScreenHeight; } @Override public void onGlobalLayout() { Rect rect = new Rect(); // 获取当前页面窗口的显示范围 ((Activity) getContext()).getWindow().getDecorView().getWindowVisibleDisplayFrame(rect); int screenHeight = getScreenHeight(); int keyboardHeight = screenHeight - rect.bottom; // 输入法的高度 boolean isActive = false; if (Math.abs(keyboardHeight) > screenHeight / 5) { isActive = true; // 超过屏幕五分之一则表示弹出了输入法 mKeyboardHeight = keyboardHeight; } mIsKeyboardActive = isActive; if (mListener != null) { mListener.onKeyboardStateChanged(isActive, keyboardHeight); } } } public void setKeyboardListener(KeyboardLayoutListener listener) { mListener = listener; } public KeyboardLayoutListener getKeyboardListener() { return mListener; } public boolean isKeyboardActive() { return mIsKeyboardActive; } /** * 获取输入法高度 * @return */ public int getKeyboardHeight() { return mKeyboardHeight; } public interface KeyboardLayoutListener { /** * @param isActive 输入法是否激活 * @param keyboardHeight 输入法面板高度 */ void onKeyboardStateChanged(boolean isActive, int keyboardHeight); }}
KeyboardLayout加入布局文件中即可,无其他使用限制。从代码中可知,当布局变化时并不需要知道KeyboardLayout的高度来计算输入法高度,KeyboardLayout只是充当一个布局监听器的作用。
输入法和表情栏切换时,如果只是简单的在切换到输入法时隐藏表情栏,或者切换到表情栏时隐藏输入法,这样过度过程造成布局闪烁一下,如下所示:
这样的效果简直会逼死像我这样有强迫症的人,因此我们需要解决它!造成这种问题的原因是,在显示表情栏时,输入法还没消失,因此表情栏会出现在输入法上面,当输入法消失时,表情栏的位置又被重新调整到底部,因此会造成布局闪烁,同理可以解释切换到输入法时造成闪烁的原因。解决问题的关键主要靠如下两句代码:
// 设置输入法弹起时自动调整布局,使之在输入法之上getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);// 设置输入法弹起时不调整当前布局getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
当从输入法切换到表情栏时,设置布局为不会重新调整SOFT_INPUT_ADJUST_NOTHING,同时隐藏输入法,显示表情栏,这样当再次切换输入法时,刚好输入法可以挡住表情栏,再把布局设为可自动调整SOFT_INPUT_ADJUST_RESIZE,代码如下:
public class KeyboardLayoutDemo extends Activity { private KeyboardLayout mKeyboardLayout; private View mEmojiView; private Button mEmojiBtn; private EditText mInput; int mKeyboardHeight = 400; // 输入法默认高度为400 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_keyboard_layout); // 起初的布局可自动调整大小 getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); mKeyboardLayout = (KeyboardLayout) findViewById(R.id.keyboard_layout); mEmojiView = findViewById(R.id.emoji); mEmojiBtn = (Button) findViewById(R.id.emoji_btn); mInput = (EditText) findViewById(R.id.input); // 点击输入框 mInput.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mKeyboardLayout.postDelayed(new Runnable() { @Override public void run() { // 输入法弹出之后,重新调整 mEmojiBtn.setSelected(false); mEmojiView.setVisibility(View.GONE); getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); } }, 250); // 延迟一段时间,等待输入法完全弹出 } }); mEmojiBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mEmojiBtn.setSelected(!mEmojiBtn.isSelected()); if (mKeyboardLayout.isKeyboardActive()) { // 输入法打开状态下 if (mEmojiBtn.isSelected()) { // 打开表情 getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING); // 不改变布局,隐藏键盘,emojiView弹出 InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(mInput.getApplicationWindowToken(), 0); mEmojiView.setVisibility(View.VISIBLE); } else { mEmojiView.setVisibility(View.GONE); InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(mInput.getApplicationWindowToken(), 0); getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); } } else { // 输入法关闭状态下 if (mEmojiBtn.isSelected()) { // 设置为不会调整大小,以便输入弹起时布局不会改变。若不设置此属性,输入法弹起时布局会闪一下 getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING); mEmojiView.setVisibility(View.VISIBLE); } else { getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); mEmojiView.setVisibility(View.GONE); } } } }); mKeyboardLayout.setKeyboardListener(new KeyboardLayout.KeyboardLayoutListener() { @Override public void onKeyboardStateChanged(boolean isActive, int keyboardHeight) { if (isActive) { // 输入法打开 if (mKeyboardHeight != keyboardHeight) { // 键盘发生改变时才设置emojiView的高度,因为会触发onGlobalLayoutChanged,导致onKeyboardStateChanged再次被调用 mKeyboardHeight = keyboardHeight; initEmojiView(); // 每次输入法弹起时,设置emojiView的高度为键盘的高度,以便下次emojiView弹出时刚好等于键盘高度 } if (mEmojiBtn.isSelected()) { // 表情打开状态下 mEmojiView.setVisibility(View.GONE); mEmojiBtn.setSelected(false); } } } }); } // 设置表情栏的高度 private void initEmojiView() { ViewGroup.LayoutParams layoutParams = mEmojiView.getLayoutParams(); layoutParams.height = mKeyboardHeight; mEmojiView.setLayoutParams(layoutParams); }}
实践中会不断的改进的代码,请大家关注最新完整的代码:https://github.com/1993hzw/Androids
3 0
- Android获取输入法高度——输入法与页面布局无缝切换
- Android 获取输入法高度
- Android获取输入法高度
- 微信表情与输入法无缝切换(原理篇)
- Android 切换输入法
- Android 切换输入法
- Android 输入法 控制 切换
- Android输入法之——如何在代码中强制切换输入法
- Android输入法之——如何在代码中强制切换输入法
- Android输入法之——在代码中强制切换和获得当前输入法
- 【Android开发杂技】输入法高度获取(可监听变化)
- Android 输入法布局改变的页面适配
- android模拟器如何切换输入法
- Android模拟器切换中文输入法
- android切换输入法工具类
- android系统动态切换输入法
- 切换输入法
- 输入法切换
- rsync 错误报告
- 蜂巢晶格_Honeycomb Lattice Triangular Lattice初始化邻居信息
- POJ 2352[树状数组]
- 【转】JSP/SERVLET入门教程--Servlet 使用入门
- thinkphp报错 找不到think/log
- Android获取输入法高度——输入法与页面布局无缝切换
- MongoDB小结32 - 聚合管道【$skip】
- apache bench(ab) 压测,模拟post请求
- solr 增量更新
- monkey简介
- HD--2544最短路
- 手机端网页:控制安卓手机返回键
- mysql 给表和字段加注释
- 快速排序的改进方法