Android-->如何优雅的切换表情和键盘(原理)

来源:互联网 发布:淘宝感谢卡内容简短 编辑:程序博客网 时间:2024/05/17 04:34

网上有很多开源的项目, 但通常都封装的很复杂, 并不能很友好的自定义, 甚至原理都看不清楚.

没关系, 这篇文章就是讲原理的. 让你分分钟都能自定义一个出来.


正常情况下, 当我们切换表情和键盘的时候, Layout会跳动, 体验极其差.

有几个前提需要满足:

<activity    android:windowSoftInputMode="adjustResize" //这个是必须的    android:screenOrientation="portrait"  //尽量固定为竖屏, 否则考虑的情况就多了./>

布局大概是这样的:

<SoftInputLayout>//这个是自定义的包裹层, 核心布局    <LinearLayout        android:layout_weight="1" > //注意这条属性, 关键哦        //这里用来放内容    </LinearLayout>    <LinearLayout>        //这里用来放表情,默认情况下,表情布局是隐藏的;    </LinearLayout></SoftInputLayout>

分析
在不显示表情布局的情况下, 单纯的显示键盘,隐藏键盘. 一切都没有问题;很正常;

但是, 如果你要显示表情的时候, 问题就蹦出来了;#$%^&*各种问题; 我就不描述了;写过的你,应该懂;

解决的办法就是:
当你点击按钮,显示表情:此时需要把内容布局的高度固定(这个高度值, 就是需要计算的关键之一), 其次再显示表情布局.,,,没了…

其实就是一个高度的问题, 解决了这个高度, 文章也就结束了.

高度的获取

@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh){    //首先需要在此,记录布局的最大高度    //然后当键盘弹出的时候, 布局高度会变小    //就可以计算出键盘的高度    //此时你已经知道了3个高度值: 最大的布局高度值, 当前键盘弹出后布局的高度值, 以及计算出来的键盘高度}
@Overrideprotected 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);}

项目源码:
https://github.com/Redbird/KeyboardDemo

核心文件:
https://github.com/Redbird/KeyboardDemo/blob/master/app/src/main/java/com/angcyo/keyboarddemo/SoftInputLayout.java

使用方法:

//当需要显示表情的时候调用:showEmojiLayout()//当需要隐藏表情的时候调用:hideEmojiLayout()//即可

至此: 文章就结束了,如有疑问: QQ群:274306954 欢迎您的加入.

0 0