在android中,常常会和输入法的软件键盘交互。在Manifest文件中,系统给activity的一个属性-windowSoftInputMode来控制输入法的显示方式。

该属性提供了Activity的window与软键盘的window交互的方式。这里的属性设置有双方面的影响:

1.软键盘的显示与隐藏。-当Activity界面成为用户的焦点时,或隐藏或显示。

2。

对Activty的主window窗体进行调整。或者将Activity的window窗体调小以便为软键盘腾出空间,或者当Activity的部分window被软件盖住时,移动Activity的内容以便用户可以看到当前的焦点。



你至少要从下列属性值选取一项对其设置,要么是”state...“,要么是”adjust...“。

你能够设置多个值。设置不同的属性值。要用|进行分开。

比方:

<activityandroid:windowSoftInputMode="stateVisible|adjustResize"
. . . >

以下是对属性的值的描写叙述。

描写叙述
”stateUnSpecified“ 不指定软件的状态(显示或隐藏)。系统会依据主题中的设置来选择对应的状态。 该属性软键盘的默认设置。
”stateUnchnaged“ 总是保持上次软键盘的状态。当Activity进入到最前端时,不论是它上次它是显示或隐藏。保持不变。
”stateHidden“ 当用户进入目标Activity时。软键盘保持隐藏状态。这里的Activity是用户是向前进入Activity,而不是因为退出其他Activity退回到目标Activity。
”stateVisible“ 仅仅有条件合适(当用户前进进入到Activity的主window),就会显示键盘
”stateAlawaysVisible“ 当用户选择进入目标Activity时。软键盘被设置为可见的。这里的Activity是用户向前进入的Activity,而不是因为退出其他Activity而回到目标Activity
"adjustUnspecified" 不指定是否去调整Activity的界面。或者调整Activity窗体的大小以便为软键盘腾出空间或者移动窗体的内容来屏幕上当前的焦点可见。系统会自己主动选择当中一种模式,这依赖于窗体是包括能够滑动其内容的view.如有这种视图,窗体的大小就会被调整。在这种假定的情况下,非常小的滑动就能够使用窗体的内容可见。

该属性是主windowr默认设置。

”adjustResize“ Activity的窗体总是被调整其大小以便为软键盘腾出空间。

”adjustPan“ Activity的主窗体不会被调整其大小以便为软键盘腾出空间。相反,窗体的内容会被自己主动移动以便当前的焦点不会被软键盘遮住,用户能够总是看到他输入的内容。

这个值一般用于用户非常少想调整窗体的大小的情况下。由于用户可能须要关闭软键盘来与窗体的其他部分进行交互。

从上面系统的描写叙述了解了系统在处理两个交互时都显示Activity和软键盘都是看作window窗体来处理的。

非常多的时候,我们都希望可以监听到软件键盘的显示与关闭状态。比方下图的情况,

你有一个登录界面是这样设计的

你希望登录时它是这种,

然后你去尝试给activity的windowSoftInputMode属性加上值,当你加上 adjustResize时。它是这种

你不甘心。你将adjustResize改动成adjustPan,结果是这种

没有办法。仅仅有靠我们自己来监听键盘的显示或隐藏来动态改变布局。如今的问题是怎么监听到键盘的动态改变呢。系统并没有提供对应的方法。我们能够通过两种方法来实现。

1.在adjustResize属性下。activity的窗体大小会发生改变,而窗体中的layout的大小也必定后会发生改变。

当view大小发生改变时,必定会引起onSizeChanged(int, int, int, int)的回调。所以可能自己定义一个Layout。来监測onSizeChanged()函数的回调。然后在当中的作对应的处理。

这种方法也是网上传的最多的方法。

2.借助ViewTreeOberserver类。ViewTreeOberserver能够用来注冊一个监听器。它能监听view树的全局变化。

这些变化包含但不限于,整个View的布局,绘制传递的源头,触摸模式的变化。



第一种方法的实现:

自己定义一个Layout。以RelativeLayout为例,

能够在onSizeChanged(int
w, int h,int
oldw,int oldh) 方法里监听界面大小的变化,然后在该方法里定义回调函数。当监听到键盘被调出时,将键盘向上推一段距离,这样将登录键显示出来。

package com.example.keyboardlistener;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.RelativeLayout; public class KeyboardLayout extends RelativeLayout { private onSizeChangedListener mChangedListener;
private static final String TAG ="KeyboardLayoutTAG";
private boolean mShowKeyboard = false; public KeyboardLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
} public KeyboardLayout(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
} public KeyboardLayout(Context context) {
super(context);
// TODO Auto-generated constructor stub
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Log.d(TAG, "onMeasure-----------");
} @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
super.onLayout(changed, l, t, r, b);
Log.d(TAG, "onLayout-------------------");
} @Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// TODO Auto-generated method stub
super.onSizeChanged(w, h, oldw, oldh);
Log.d(TAG, "--------------------------------------------------------------");
Log.d(TAG, "w----" + w + "\n" + "h-----" + h + "\n" + "oldW-----" + oldw + "\noldh----" + oldh);
if (null != mChangedListener && 0 != oldw && 0 != oldh) {
if (h < oldh) {
mShowKeyboard = true;
} else {
mShowKeyboard = false;
}
mChangedListener.onChanged(mShowKeyboard);
Log.d(TAG, "mShowKeyboard----- " + mShowKeyboard);
}
} public void setOnSizeChangedListener(onSizeChangedListener listener) {
mChangedListener = listener;
} interface onSizeChangedListener{ void onChanged(boolean showKeyboard);
} }

在主Activity里创建一个Handler。当监听到布局发生变化时,通过Handler更新UI。

package com.example.keyboardlistener;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.ViewTreeObserver.OnPreDrawListener;
import android.widget.Button; import com.example.keyboardlistener.KeyboardLayout.onSizeChangedListener; public class MainActivity extends Activity { private static final String TAG = "KeyboardLayoutTAG";
private KeyboardLayout mRoot;
private Button mLogin;
private int mLoginBottom;
private static final int KEYBOARD_SHOW = 0X10;
private static final int KEYBOARD_HIDE = 0X20;
private boolean mGetBottom = true; private Handler mHandler = new Handler() { @Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
switch (msg.what) {
case KEYBOARD_HIDE:
mRoot.setPadding(0, 0, 0, 0);
break; case KEYBOARD_SHOW:
int mRootBottom = mRoot.getBottom();
Log.d(TAG, "the mLoginBottom is " + mLoginBottom);
mRoot.setPadding(0, mRootBottom - mLoginBottom, 0, 0);
break; default:
break;
}
} }; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); getActionBar().hide();
mRoot = (KeyboardLayout) findViewById(R.id.root_view);
mLogin = (Button) findViewById(R.id.login);
mRoot.setOnSizeChangedListener(new onSizeChangedListener() { @Override
public void onChanged(boolean showKeyboard) {
// TODO Auto-generated method stub
if (showKeyboard) {
mHandler.sendMessage(mHandler.obtainMessage(KEYBOARD_SHOW));
Log.d(TAG, "show keyboard");
} else {
mHandler.sendMessage(mHandler.obtainMessage(KEYBOARD_HIDE));
}
}
}); mRoot.getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() { @Override
public boolean onPreDraw() {
// TODO Auto-generated method stub
if (mGetBottom) {
mLoginBottom = mLogin.getBottom();//获取登录button的位置信息。 }
mGetBottom = false;
return true;
}
}); } // @Override
// public boolean onCreateOptionsMenu(Menu menu) {
// // Inflate the menu; this adds items to the action bar if it is present.
// getMenuInflater().inflate(R.menu.main, menu);
// return true;
// } }

另外一种方法的实现:

借助ViewTreeObserver类对你想监听的view加入OnGlobalLayoutListener监听器。然后在onGlobalLayout()方法里窗体的变化情况来推断键盘是否被调出来了。以下是ViewTreeObserver监听的部分的代码:

mRoot.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

            @Override
public void onGlobalLayout() {
int offset = mRoot.getRootView().getHeight() - mRoot.getHeight();
//依据视图的偏移值来推断键盘是否显示
if (offset > 300) {
mHandler.sendMessage(mHandler.obtainMessage(KEYBOARD_SHOW));
} else {
mHandler.sendMessage(mHandler.obtainMessage(KEYBOARD_HIDE));
} }
});

当中Handler的详细实现同上述结构中的Handler一样。

參考文章:InputMethod

样例源代码下载地址

android 软键盘的显示与隐藏问题的研究的更多相关文章

  1. Android 软键盘的显示和隐藏,这样操作就对了

    一.前言 如果有需要用到输入的地方,通常会有需要自动弹出或者收起软键盘的需求.开篇明义,本文会讲讲弹出和收起软键盘的一些细节,最终还会从源码进行分析. 想要操作软键盘,需要使用到 InputMetho ...

  2. android软键盘的显示和隐藏

    显示: InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); imm.toggle ...

  3. EditText获取和失去焦点,软键盘的关闭,和软键盘的显示和隐藏的监听

    软键盘显示和隐藏的监听: 注: mReplayRelativeLayout是EditText的父布局 //监听软键盘是否显示或隐藏 mReplayRelativeLayout.getViewTreeO ...

  4. 日积月累:EditText软键盘的显示和隐藏

    在工作过程中,常常会遇见需要根据自己的需求,控制文本框的键盘显示和隐藏. 通过查阅Android文档,介绍可以通过在清单文件中<activity>元素中添加android:windowSo ...

  5. Android软键盘的隐藏显示、事件监听的代码

    把开发过程中重要的一些内容片段做个珍藏,如下资料是关于Android软键盘的隐藏显示.事件监听的内容,应该是对小伙伴们有所用途. public class ResizeLayout extends L ...

  6. Android之Android软键盘的隐藏显示研究

    转自:http://blog.csdn.net/lilu_leo/article/details/6587578 看了很多这类型的文章,这篇文章最有价值,解决了我的烦恼,必须转. Android是一个 ...

  7. Android手动控制软键盘的开启和关闭,判断软键盘是否显示;

    工具类,拿走就能用: import android.annotation.TargetApi; import android.app.Activity; import android.content. ...

  8. android软键盘弹出隐藏的监听

    通过网上搜索关于软键盘的隐藏弹出的监听,有几种方式,其中最有效的方式是在View的Onlayout()里面做文章 具体代码: 将布局视图自定义,重写onlayout()方法,然后在主Activity里 ...

  9. Android 软键盘弹出时把原来布局顶上去的解决方法

    键盘弹出时,会将布局底部的导航条顶上去. 解决办法: 在mainfest.xml中,在和导航栏相关的activity中加: <activity            android:name=& ...

随机推荐

  1. 【HNOI 2004】 L语言

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1212 [算法] 字典树 + dp [代码] #include<bits/std ...

  2. [Apple开发者帐户帮助]二、管理你的团队(1)邀请团队成员

    组织可以选择向其开发团队添加其他人员.如果您已加入Apple开发者计划,您将在App Store Connect中管理团队成员.有关详细信息,请转到在App Store Connect帮助中添加用户. ...

  3. SpringAOP使用注解实现5种通知类型

    spring aop的5种通知类型都有 Before前置通知 AfterReturning后置通知 Around环绕通知 AfterThrowing异常通知 After最终通知 首先创建接口和实现类 ...

  4. POJ 1523 Tarjan求割点

    SPF Description Consider the two networks shown below. Assuming that data moves around these network ...

  5. C - Lucky Numbers (easy)

    Problem description Petya loves lucky numbers. Everybody knows that positive integers are lucky if t ...

  6. Java上传视频

    页面: 上传文件时的关键词:enctype="multipart/form-data" <%@ page language="java" import=& ...

  7. retrofit post请求多文件,partMap用法

    1. APIService 定义注解 @Multipart @POST("cyxx/Feedback/add.do") Observable<ResponseBody> ...

  8. Android MediaRecorder自定义分辨率

    Android MediaRecorder自定义分辨率 工作这么久了,确实积累了不少东西,但都是以文档的形式存在U盘里的,为什么不写博客呢?因为懒啊!!!总感觉博客太难写了(大概是上学时候写作文恐惧症 ...

  9. Linux系统下通过命令行对mysql数据进行备份和还原

    一.备份 1.进入mysql目录 cd /var/lib/mysql (进入mysql目录,根据安装情况会有差别) 2.备份 mysqldump -u root -p密码 数据库名 数据表名 > ...

  10. 1、Scala安装与基础

    1.scala与java 2.安装 3.scala编译器 4.变量声明 5.数据类型 6.操作符 7.函数调用 8.apply函数 1.scala与java scala基于java虚拟机,所有scal ...