网上有很多开源的项目, 但通常都封装的很复杂, 并不能很友好的自定义, 甚至原理都看不清楚.
没关系, 这篇文章就是讲原理的. 让你分分钟都能自定义一个出来.
正常情况下, 当我们切换表情和键盘的时候, Layout会跳动, 体验极其差.
有几个前提需要满足:
"adjustResize" //这个是必须的
android:screenOrientation="portrait" //尽量固定为竖屏, 否则考虑的情况就多了.
/>
布局大概是这样的:
<SoftInputLayout>//这个是自定义的包裹层, 核心布局
<LinearLayout
android:layout_weight="1" > //注意这条属性, 关键哦
//这里用来放内容
LinearLayout>
<LinearLayout>
//这里用来放表情,默认情况下,表情布局是隐藏的;
LinearLayout>
SoftInputLayout>
分析
在不显示表情布局的情况下, 单纯的显示键盘,隐藏键盘. 一切都没有问题;很正常;
但是, 如果你要显示表情的时候, 问题就蹦出来了;#$%^&*各种问题; 我就不描述了;写过的你,应该懂;
解决的办法就是:
当你点击按钮,显示表情:此时需要把内容布局的高度固定(这个高度值, 就是需要计算的关键之一), 其次再显示表情布局.,,,没了…
其实就是一个高度的问题, 解决了这个高度, 文章也就结束了.
高度的获取
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh){
//首先需要在此,记录布局的最大高度
//然后当键盘弹出的时候, 布局高度会变小
//就可以计算出键盘的高度
//此时你已经知道了3个高度值: 最大的布局高度值, 当前键盘弹出后布局的高度值, 以及计算出来的键盘高度
}
@Override
protected 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 欢迎您的加入.