微信的效果是这样,点击+号时,键盘会收入和弹出,而下面的操作框感觉是一直在下面,而且刚好和键盘等高。要实现这个步骤重点在以下几步
1. 得到键盘高度,并把操作框设成键盘高度。
2. 能够监听到键盘的收回,键盘收回时把操作框隐藏掉
3. 动态设置键盘的弹出模式。
先上图
先来解决第一与第二个问题,官方并没给出相应api来得到键盘高度并监听键盘变化。但网上的大神给出了解决方案,这里封装了一个listener来达到这个目的,其原理就是根据键盘弹出时根布局的变化来算出键盘的高度。
代码如下
import android.app.Activity;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewTreeObserver;
public class SoftKeyBoardListener {
private View rootView;//activity的根视图
int rootViewVisibleHeight;//纪录根视图的显示高度
private OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener;
public SoftKeyBoardListener(Activity activity) {
//获取activity的根视图
rootView = activity.getWindow().getDecorView();
//监听视图树中全局布局发生改变或者视图树中的某个视图的可视状态发生改变
rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//获取当前根视图在屏幕上显示的大小
Rect r = new Rect();
rootView.getWindowVisibleDisplayFrame(r);
int visibleHeight = r.height();
if (rootViewVisibleHeight == 0) {
rootViewVisibleHeight = visibleHeight;
return;
}
//根视图显示高度没有变化,可以看作软键盘显示/隐藏状态没有改变
if (rootViewVisibleHeight == visibleHeight) {
return;
}
//根视图显示高度变小超过200,可以看作软键盘显示了
if (rootViewVisibleHeight - visibleHeight > 200) {
if (onSoftKeyBoardChangeListener != null) {
onSoftKeyBoardChangeListener.keyBoardShow(rootViewVisibleHeight - visibleHeight);
}
rootViewVisibleHeight = visibleHeight;
return;
}
//根视图显示高度变大超过200,可以看作软键盘隐藏了
if (visibleHeight - rootViewVisibleHeight > 200) {
if (onSoftKeyBoardChangeListener != null) {
onSoftKeyBoardChangeListener.keyBoardHide(visibleHeight - rootViewVisibleHeight);
}
rootViewVisibleHeight = visibleHeight;
return;
}
}
});
}
private void setOnSoftKeyBoardChangeListener(OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener) {
this.onSoftKeyBoardChangeListener = onSoftKeyBoardChangeListener;
}
public interface OnSoftKeyBoardChangeListener {
void keyBoardShow(int height);
void keyBoardHide(int height);
}
public static void setListener(Activity activity, OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener) {
SoftKeyBoardListener softKeyBoardListener = new SoftKeyBoardListener(activity);
softKeyBoardListener.setOnSoftKeyBoardChangeListener(onSoftKeyBoardChangeListener);
}
}
用起来很简单
SoftKeyBoardListener.setListener(MainActivity.this, new SoftKeyBoardListener.OnSoftKeyBoardChangeListener() {
@Override
public void keyBoardShow(int height) {
Toast.makeText(MainActivity.this, "键盘显示 高度" + height, Toast.LENGTH_SHORT).show();
}
@Override
public void keyBoardHide(int height) {
Toast.makeText(MainActivity.this, "键盘隐藏 高度" + height, Toast.LENGTH_SHORT).show();
}
});
}
当然得到键盘高度的操作最好在用户第一次使用应用是就来获取,并存起来。
下面是键盘与操作框切换的思路
1. 键盘默认弹出模式设为 SOFT_INPUT_ADJUST_RESIZE, 这种模式下键盘会把整个布局给挤一去。
2. 点击切换按钮时,键盘模式设为SOFT_INPUT_ADJUST_PAN, 这种模式下键盘会悬浮在布局之上,只会把输入框向上挤。然后显示出操作框,收回键盘。
3.再次点击切换按钮,弹出键盘即可。
4.点击键盘上的收回按钮时,要同时隐藏掉操作框,这里要在监听中去实现。
具体实现看代码,代码才是重点。
public class MainActivity extends AppCompatActivity {
private LinearLayout llBottom;
private EditText editText;
private ListView listView;
private InputMethodManager mInputManager;
private boolean keybordShow = false;
private int inputHeight;
private boolean isClick = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mInputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
llBottom = (LinearLayout) findViewById(R.id.llBottom);
editText = (EditText) findViewById(R.id.editText);
listView = (ListView) findViewById(R.id.listView);
listView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
hideSoftInput();
llBottom.setVisibility(View.GONE);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
}
return false;
}
});
SoftKeyBoardListener.setListener(MainActivity.this, new SoftKeyBoardListener.OnSoftKeyBoardChangeListener() {
@Override
public void keyBoardShow(int height) {
Toast.makeText(MainActivity.this, "键盘显示 高度" + height, Toast.LENGTH_SHORT).show();
LinearLayout.LayoutParams linearParams = (LinearLayout.LayoutParams) llBottom.getLayoutParams();
linearParams.height = height;
keybordShow = true;
isClick = false;
}
@Override
public void keyBoardHide(int height) {
Toast.makeText(MainActivity.this, "键盘隐藏 高度" + height, Toast.LENGTH_SHORT).show();
if (!isClick) {
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
llBottom.setVisibility(View.GONE);
}
keybordShow = false;
}
});
}
public void change(View v) {
isClick = true;
if (llBottom.getVisibility() == View.GONE) {
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
hideSoftInput();
llBottom.setVisibility(View.VISIBLE);
} else if (keybordShow){
//getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
hideSoftInput();
} else {
showSoftInput();
}
}
private void showSoftInput() {
mInputManager.showSoftInput(editText, 0);
}
private void hideSoftInput() {
mInputManager.hideSoftInputFromWindow(editText.getWindowToken(), 0);
}
}