本文将提及的是软键盘的使用技巧,包括一些初始进入的小细节还有一些常见的应用场景。
应用场景包括 1. 登陆注册界面时由于屏幕原因,弹出的软键盘会遮住登陆注册按钮
2.评论时输入文字框居于软件盘上的效果时
细节描述
1. 初次进入含有文本框的界面时,光标闪烁
2. 软键盘弹出,页面跳转,可能导致抖动
3. 软键盘将标题toolbar顶出去了
解决方式
让EditText的父亲布局抢占其焦点,可以有效解决进入界面输入框光标闪烁问题
.......
延迟退出软键盘抗拒可能会出现的抖动
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
// 隐藏软键盘 imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0);
// 延迟个0.1秒是因为 可能推出太快导致软键盘刚刚被回收,前面的界面出现断层
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
finish();
规避底部的文本框不太接近弹出框的方法:
看下下面的效果,是不是还挺赞的,也是拿出来给大家分享下,也是希望懂的大牛告知为啥这样就行,我也不知道原因。
具体实现过程:如下一共有3步,设置活动的 windowSoftInputMode属性,然后建立 Scroll布局+EditText焦点的布局[含文本的置于底部],最后是设置默认隐藏软键盘。大家可以试一下。
//主题
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
setContentView(R.layout.activity_session);
}
当然,我是觉得这里这种方式是更适合运用于聊天消息的设置,使得文本输入框且其父布局能够放置于软键盘之上。当然这里的局是文本框位于底部。
当布局中存在EditText时,又涉及到提交按钮特别是登录注册界面,由于手机屏幕高度不够使得按钮被遮挡的效果会出现。这样会带来比较不好的使用体验效果。下面将对这一问题进行解决
运行效果:
示意图:
解释: 如图所示,不做处理软件盘会遮盖button,而我们需要显示出,那么需要是内容区平滑按钮到软键盘顶部的距离,那么按钮就会显示出来了。所以问题的关键是测量当按钮位于软键盘顶部显示时的高度。
核心代码如下
/**
* 功能: 软键盘弹起时让特定页面置于软键盘之上
* @param rootGroup 外围布局
* @param bottomView 底部需要显示的view
*/
private void buttonBeyondKeyboardLayout(final View rootGroup,final View bottomView) {
mListener = new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
// 总的布局空间
View decorView = RegisterActivity.this.getWindow().getDecorView();
int normalHeight = decorView.getRootView().getHeight();
// 可视区域
Rect outRect = new Rect();
decorView.getWindowVisibleDisplayFrame(outRect);
// 软键盘弹起
if (normalHeight - outRect.height() > dpToPx(100)){
if (distanceY == -1){
int[] bottomArray = new int[2];
bottomView.getLocationInWindow(bottomArray);
// 底部view的bottom坐标
int viewBottomY = bottomArray[1]+bottomView.getHeight();
// 判断底部view是否被软键盘盖住
if (viewBottomY > outRect.bottom){
// 计算偏移的距离 并给出20dp的间隙
distanceY = viewBottomY - outRect.bottom + dpToPx(20);
}else {
distanceY = 0;
}
}
if (distanceY != 0){
// 滑动间距
//rootGroup.scrollTo(0,distanceY);
smoothScroll(0,distanceY,rootGroup);
}else {
unRegisterTree();
}
}else {
// 软键盘收起
// 还原...
if (distanceY != -1 && distanceY != 0){
// rootGroup.scrollTo(0,0); 瞬间移动
smoothScroll(distanceY,0,rootGroup); // 平滑移动
}
}
}
};
mTreeObserver = rootGroup.getViewTreeObserver();
mTreeObserver.addOnGlobalLayoutListener(mListener);
}
private void smoothScroll(int fromY, int toY, final View view){
mValueAnimator = ValueAnimator.ofInt(fromY,toY);
mValueAnimator.setInterpolator(new DecelerateInterpolator());
mValueAnimator.setDuration(200);
mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int animatedValue = (int) animation.getAnimatedValue();
view.scrollTo(0,animatedValue);
}
});
mValueAnimator.start();
}
private void unRegisterTree(){
if (mListener != null && mTreeObserver != null && mTreeObserver.isAlive()) {
mTreeObserver.removeOnGlobalLayoutListener(mListener);
}
}
private void releaseAnimator(){
if (mValueAnimator != null && mValueAnimator.isRunning()){
mValueAnimator.cancel();
}
}
@Override
protected void onDestroy() {
unRegisterTree();
releaseAnimator();
super.onDestroy();
}
小结:
咱们在做开发的时候,肯定会遇到很多困难,但要努力思考将之解决,即便解决不了也要有自己的思路。其实也是很常规,总结别人的思考自己的知识储备,提升自己的能力。
mListener = new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Rect rect = new Rect();
BasicSoftActivity.this.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
int screenHeight = BasicSoftActivity.this.getWindow().getDecorView().getRootView().getHeight();
if (screenHeight - rect.bottom > dp2Px(100)){
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
0);
params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
btnSubmit.setLayoutParams(params);
}else {
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
dp2Px(50));
params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
btnSubmit.setLayoutParams(params);
}
}
};
活用BottomSheetDialog 弹出评论的软键盘,并解决了布局被被键盘部分遮挡的问题。
效果展示:
如上图所示,当点击评论则会从底部弹出Dialog,该DIalog会手指移动而移动,且由于含文本框故而有必要弹出软键盘,且可以发现该软键盘将整个弹出框挤压了上去。好了,这就是我们的效果。
具体实现:
继承BottomSheetDialog,实现显示和隐藏的状态方法
public class BottomDialog extends BottomSheetDialog {
private BottomSheetBehavior behavior;
public BottomDialog(@NonNull Context context, int theme,boolean isTranslucentStatus) {
super(context, theme);
Window window = getWindow();
if (window != null) {
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE |
WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
if (isTranslucentStatus) {
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
}
@Override
public void setContentView(View view) {
super.setContentView(view);
initialize(view);
setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
if (behavior != null) {
behavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
}
});
}
@Override
public void show() {
super.show();
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
private void initialize(final View view) {
ViewGroup parent = (ViewGroup) view.getParent();
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) parent.getLayoutParams();
behavior = (BottomSheetBehavior) params.getBehavior();
if (behavior == null) {
return;
}
behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
dismiss();
behavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
});
}
}
在values文件夹下的style.xml 引入含底部编辑框的style,说明一下,假若你定义style,那么当你弹出软键盘或者点击EditText时,会被部分遮挡,这是很不好的效果。所以下面的设置记住咯。
像一些简单的布局和java代码我就不给出了,大家可以在文后的例子中进行查看的,ok了。
**提醒**
具体使用那种显示方式还是得具体分析应用场景,从我目前的开发经验来看:
询问类弹窗,单行输入,优先使用dialog
底部列表拉伸,优先使用bottomSheetDialog
其他一些显示效果 dialogFragment
带多行输入框,自定义假的dialog,即使用背景进行显示隐藏实现效果展示
Github项目地址:https://github.com/crazyzhangxl/KeyBoardDemo