一、问题概述
在编辑框输入内容时会弹出软键盘,而手机屏幕区域有限往往会遮住输入界面
输入密码时输入框被系统键盘遮挡了,大大降低了用户操作体验,这就是开发中非常常见的软键盘遮挡的问题,该如何解决?
二、简单解决方案
方法一
在你的activity中的oncreate中setContentView之前写上这个代码
1
|
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
|
方法二
在 项目的AndroidManifest.xml文件中界面对应的<activity>里加入
1
|
android:windowSoftInputMode=
"adjustPan"
|
这样会让屏幕整体上移。如果加上的 是 android:windowSoftInputMode="adjustPan"这样键盘就不会覆盖屏幕。
关于android:windowSoftInputMode
activity主窗口与软键盘的交互模式,可以用来避免输入法面板遮挡问题,Android1.5后的一个新特性。
这个属性能影响两件事情:
【一】当有焦点产生时,软键盘是隐藏还是显示
【二】是否减少活动主窗口大小以便腾出空间放软键盘
它的设置必须是下面列表中的一个值,或一个”state…”值加一个”adjust…”值的组合。在任一组设置多个值——多个”state…”values,例如&mdash有未定义的结果。各个值之间用|分开。
例如:
1
|
<activity android:windowSoftInputMode=
"stateVisible|adjustResize"
. . . >
|
在这设置的值(除"stateUnspecified"和"adjustUnspecified"以外)将覆盖在主题中设置的值
各值的含义:
【A】stateUnspecified:软键盘的状态并没有指定,系统将选择一个合适的状态或依赖于主题的设置
【B】stateUnchanged:当这个activity出现时,软键盘将一直保持在上一个activity里的状态,无论是隐藏还是显示
【C】stateHidden:用户选择activity时,软键盘总是被隐藏
【D】stateAlwaysHidden:当该Activity主窗口获取焦点时,软键盘也总是被隐藏的
【E】stateVisible:软键盘通常是可见的
【F】stateAlwaysVisible:用户选择activity时,软键盘总是显示的状态
【G】adjustUnspecified:默认设置,通常由系统自行决定是隐藏还是显示
【H】adjustResize:该Activity总是调整屏幕的大小以便留出软键盘的空间
【I】adjustPan:当前窗口的内容将自动移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分
方法三
把顶级的layout替换成ScrollView,或者说在顶级的Layout上面再加一层ScrollView。这样就会把软键盘和输入框一起滚动了,软键盘会一直处于底部。
1
2
3
4
5
6
|
<ScrollView xmlns:android=
"http://schemas.android.com/apk/res/android"
android:layout_width=
"fill_parent"
android:layout_height=
"fill_parent"
>
<LinearLayout android:layout_width=
"fill_parent"
android:layout_height=
"fill_parent"
android:orientation=
"vertical"
>
</LinearLayout>
</ScrollView>
|
但这些方法虽然比较简单,但往往都有一定的局限性不是很灵活,有时达不到预期效果,大家可以试试或许也能解决你的问题,下面就教大家一种具有代码可控性的一种方法:
三、代码可控性方法
1.主界面布局文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
<com.jereh.overidelinearlayout.LinearLayoutView xmlns:android=
"http://schemas.android.com/apk/res/android"
android:layout_width=
"match_parent"
android:id=
"@+id/login_root_layout"
android:layout_height=
"match_parent"
android:orientation=
"vertical"
>
<!—这里模仿一个登录界面-->
<LinearLayout
android:id=
"@+id/login_layout_logo"
android:layout_width=
"match_parent"
android:layout_height=
"0dp"
android:layout_weight=
"10"
android:background=
"#ff0000"
android:orientation=
"vertical"
>
<ImageView
android:id=
"@+id/textView1"
android:layout_width=
"fill_parent"
android:layout_height=
"fill_parent"
android:src=
"@drawable/login_logo"
android:scaleType=
"fitXY"
/>
</LinearLayout>
<!—输入框和密码框-->
<LinearLayout
android:layout_width=
"match_parent"
android:layout_height=
"0dp"
android:layout_marginTop=
"20dp"
android:layout_weight=
"3"
android:orientation=
"vertical"
>
<EditText
android:id=
"@+id/editText1"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_alignLeft=
"@+id/textView1"
android:layout_alignParentBottom=
"true"
android:layout_gravity=
"center_vertical"
android:hint=
"用户名"
android:ems=
"10"
>
<requestFocus />
</EditText>
<EditText
android:id=
"@+id/editText1"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_alignLeft=
"@+id/textView1"
android:layout_alignParentBottom=
"true"
android:layout_gravity=
"center_vertical"
android:hint=
"密码"
android:ems=
"10"
>
<requestFocus />
</EditText>
</LinearLayout>
</com.jereh.overidelinearlayout.LinearLayoutView>
|
可以看出关键地方在于LinearLayoutView这个自定义组件
2.自定义LinearLayoutView
该组件可实现根据软键盘的弹出/关闭而隐藏和显示某些区域,这是问题解决最关键部分,主要有两点:
① 重写onSizeChanged方法
该方法是View生命周期的方法,当View尺寸发生变化时调用,如竖屏横屏切换、软键盘弹出。这里当软键盘弹出造成View尺寸改变,就会调用onSizeChanged方法,在该方法实现代码的核心思想是根据尺寸变化,当变大(软键盘弹出),将某些区域隐藏以给编辑界面预留出足够显示空间;当恢复(软键盘关闭),再将隐藏的区域显示出来
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
protected
void
onSizeChanged(
int
w,
final
int
h,
int
oldw,
final
int
oldh) {
super
.onSizeChanged(w, h, oldw, oldh);
uiHandler.post(
new
Runnable() {
public
void
run() {
if
(oldh - h > SOFTKEYPAD_MIN_HEIGHT){
// 软键盘关闭
keyBordStateListener.stateChange(KEYBORAD_SHOW);
//回调方法显示部分区域
}
else
{
// 软键盘弹出
if
(keyBordStateListener !=
null
){
keyBordStateListener.stateChange(KEYBORAD_HIDE);
// 回调方法隐藏部分区域
}
}
}
});
}
|
②提供KeyBordStateListener 接口采用回调机制调用接口的实现方法。
代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
public
interface
KeyBordStateListener{
public
void
stateChange(
int
state);}
//定义接口
private
KeyBordStateListener keyBordStateListener;
public
void
setKeyBordStateListener(KeyBordStateListener keyBordStateListener) {
this
.keyBordStateListener = keyBordStateListener;
}
LinearLayoutView组件的完整代码:
public
class
LinearLayoutView
extends
LinearLayout{
public
static
final
int
KEYBORAD_HIDE =
0
;
public
static
final
int
KEYBORAD_SHOW =
1
;
private
static
final
int
SOFTKEYPAD_MIN_HEIGHT =
50
;
private
Handler uiHandler =
new
Handler();
public
LinearLayoutView(Context context) {
super
(context);
}
public
LinearLayoutView(Context context, AttributeSet attrs) {
super
(context, attrs);
}
@Override
protected
void
onSizeChanged(
int
w,
final
int
h,
int
oldw,
final
int
oldh) {
// TODO Auto-generated method stub
super
.onSizeChanged(w, h, oldw, oldh);
uiHandler.post(
new
Runnable() {
@Override
public
void
run() {
if
(oldh - h > SOFTKEYPAD_MIN_HEIGHT){
keyBordStateListener.stateChange(KEYBORAD_SHOW);
}
else
{
if
(keyBordStateListener !=
null
){
keyBordStateListener.stateChange(KEYBORAD_HIDE);}
}
}
});
}
private
KeyBordStateListener keyBordStateListener;
public
void
、setKeyBordStateListener(KeyBordStateListener keyBordStateListener) {
this
.keyBordStateListener = keyBordStateListener;
}
public
interface
KeyBordStateListener{
public
void
stateChange(
int
state);
}
|
3.主界面MainActivity
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
public
class
MainActivity
extends
Activity
implements
KeyBordStateListener {
private
LinearLayoutView resizeLayout;
private
LinearLayout logoLayout;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获得可根据软键盘的弹出/关闭而隐藏和显示某些区域的LinearLayoutView组件
resizeLayout = (LinearLayoutView) findViewById(R.id.login_root_layout);
//获得要控制隐藏和显示的区域
logoLayout = (LinearLayout) findViewById(R.id.login_layout_logo);
resizeLayout.setKeyBordStateListener(
this
);
//设置回调方法
}
//实现接口中的方法,该方法在resizeLayout的onSizeChanged方法中调用
@Override
public
void
stateChange(
int
state) {
// TODO Auto-generated method stub
switch
(state) {
case
LinearLayoutView.KEYBORAD_HIDE:
logoLayout.setVisibility(View.VISIBLE);
break
;
case
LinearLayoutView.KEYBORAD_SHOW:
logoLayout.setVisibility(View.GONE);
break
;
}
}
|
原文链接:http://www.cnblogs.com/jerehedu/p/4194125.html