您的位置:首页 > 移动开发 > Android开发

Android 软键盘 相关知识讲解

2014-05-22 19:19 363 查看

一:基本知识讲解

开发中使用到EditText控件时,经常会遇到诸如软键盘挡住输入框的情况,android为此提供了一系列的的配置参数供选择,你可以在androidmanufist.xml的对应Activity的windowSoftInputMode属性中选择如下4者之一进行配置(紫色字):

 

intSOFT_INPUT_ADJUST_NOTHINGAdjustment option for 
softInputMode
:

set to have a window not adjust for a shown input method.
intSOFT_INPUT_ADJUST_PANAdjustment option for 
softInputMode
:

set to have a window pan when an input method is shown, so it doesn't need to deal with resizing but just panned by

the framework to ensure the current input focus is visible.
intSOFT_INPUT_ADJUST_RESIZEAdjustment option for 
softInputMode
:

set to allow the window to be resized when an input method is shown, so that its contents are not covered by the input method.
intSOFT_INPUT_ADJUST_UNSPECIFIEDAdjustment option for 
softInputMode
:

nothing specified.
 

       <activity android:name=".LoginAc"

 

                  android:label="@string/app_name"
                  android:windowSoftInputMode="stateHidden|adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

 

四个参数意思如下:

SOFT_INPUT_ADJUST_NOTHING:         不调整(输入法完全直接覆盖住,未开放此参数)

SOFT_INPUT_ADJUST_PAN:                 把整个Layout顶上去露出获得焦点的EditText,不压缩多余空间,见图1

SOFT_INPUT_ADJUST_RESIZE:            整个Layout重新编排,重新分配多余空间,见图2

SOFT_INPUT_ADJUST_UNSPECIFIED:  系统自己根据内容自行选择上两种方式的一种执行(默认配置)

 

这里的多余空间指的是控件们通过weight分配机制得到的额外空间。



 

图1

 



 

图2

 



 

图3

 

代码实现方式为:

   

Java代码  



getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);  

 

但是,这样的配置方法一般都很难完全满足需要,有得应用会做得比较好,让顶上去的Layout能够通过scrollbar滚动。

这种解决方法网上有各种介绍,本人也是第一时间从网上找解决方法参考,但最终发现都并未把原理说清,

而且大多数有错误,或者有多余配置,于是,我从android系统中源码中找参考案例,在Email应用中,找到了我想要的。

效果如图4,5。

 



 

图4

 



 

图5

 

 

其对应的Activity是AccountSetupBasics.java,对应的xml文件为account_setup_basics.xml。

来学习下它的xml写法:

 

Java代码  



<?xml version="1.0" encoding="utf-8"?>  

Java代码  



<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"  

    android:layout_width="fill_parent"  

    android:layout_height="fill_parent"  

    android:fillViewport="true"  

    android:scrollbarStyle="outsideInset" >  

  

    <LinearLayout  

        android:layout_width="fill_parent"  

        android:layout_height="fill_parent"  

        android:orientation="vertical" >  

  

        <LinearLayout  

            android:layout_width="fill_parent"  

            android:layout_height="wrap_content"  

            android:layout_weight="1"  

            android:orientation="vertical" >  

            <TextView  

                android:id="@+id/instructions"  

                android:layout_width="fill_parent"  

                android:layout_height="wrap_content"  

                android:layout_marginTop="10dip"  

                android:textSize="20sp"  

                android:text="@string/accounts_welcome"  

                android:textColor="?android:attr/textColorPrimary" />  

            <View  

                android:layout_width="fill_parent"  

                android:layout_height="0dip"  

                android:layout_weight="1" />  

            <EditText  

                android:id="@+id/account_email"  

                android:hint="@string/account_setup_basics_email_hint"  

                android:inputType="textEmailAddress"  

                android:imeOptions="actionNext"  

                android:layout_height="wrap_content"  

                android:layout_width="fill_parent" />  

            <EditText  

                android:id="@+id/account_password"  

                android:hint="@string/account_setup_basics_password_hint"  

                android:inputType="textPassword"  

                android:imeOptions="actionDone"  

                android:layout_height="wrap_content"  

                android:layout_width="fill_parent"  

                android:nextFocusDown="@+id/next" />  

            <CheckBox  

                android:id="@+id/account_default"  

                android:layout_height="wrap_content"  

                android:layout_width="fill_parent"  

                android:text="@string/account_setup_basics_default_label"  

                android:visibility="gone" />  

            <View  

                android:layout_width="fill_parent"  

                android:layout_height="0dip"  

                android:layout_weight="1" />  

        </LinearLayout>  

  

        <RelativeLayout  

            android:layout_width="fill_parent"  

            android:layout_height="54dip"  

            android:background="@android:drawable/bottom_bar" >  

            <Button  

                android:id="@+id/manual_setup"  

                android:text="@string/account_setup_basics_manual_setup_action"  

                android:layout_height="wrap_content"  

                android:layout_width="wrap_content"  

                android:minWidth="@dimen/button_minWidth"  

                android:layout_alignParentLeft="true"  

                android:layout_centerVertical="true" />  

            <Button  

                android:id="@+id/next"  

                android:text="@string/next_action"  

                android:layout_height="wrap_content"  

                android:layout_width="wrap_content"  

                android:minWidth="@dimen/button_minWidth"  

                android:drawableRight="@drawable/button_indicator_next"  

                android:layout_alignParentRight="true"  

                android:layout_centerVertical="true" />  

        </RelativeLayout>  

    </LinearLayout>  

</ScrollView>  

 

 

 

1  它完全把ScrollView作为了一个根Layout,而不是网上好多文章写的在一个Linearlayout里面嵌入一个ScrollView

(貌似这种是行不通的)。然后把我们原来的根Layout搬入ScrollView(ScrollView只能有一个子控件),

我查了下androidmanifist.xml和代码,未做任何以上2种方法的配置。

2  它定义了2个0dip的View帮助分配空间(设置其weight吃掉剩余空间,保证输入框处于界面中心位置),

可以猜测出这里系统调用的是SOFT_INPUT_ADJUST_RESIZE参数,当所有有实际内容的控件空间总和超出特定范围时,

ScrollView开始发挥作用。

 

如此,完美的解决我们遇到的问题。

另外,网上有人说想用SOFT_INPUT_ADJUST_RESIZE ,但又不希望背景图片被压缩,只要按如上方法把Linearlayout的背景图片设置好即可。

二:知识升华

最近项目里有类似微信聊天界面需要我去写,要动态显示最新的数据,效果和微信基本一样。有个问题困扰我一晚上,每次进入Activity后,EditText自动获得焦点弹出软键盘,键盘遮挡listView,使得无法显示最后一条消息。我在edittext点击事件中也设定了,listView.setSelection,选中最后一条数据,可是每次需要点击两下才会显示最新消息,最后在windowSoftInputMode设置了N种组合还是不行。到中午修改Bug,莫名其妙的把acitivity设置成了全屏,这样每次进入acitivity,整个布局都将被上移,其中自定义的Title每次都被挤出屏幕,此奥,这样……我又一边边找错误,终于发现原来我把屏幕设置为了全屏,所以设置inputMode为adjustResize木有反应,Tittle依然被挤出。

  最后发现,ListView有一属性,android:transcriptMode="normal" 设置过后,再配合adjustResize这样每次进入界面后,效果和微信一模一样了,listView被压缩,tittle也不会移出屏幕,并且listView显示最新一条数据。哈哈,终于大功告成~~~~~另外android:stackFromBottom="true"时,如果是动态加载数据,listView每次回从最下面开始加载,这样listVIew上面一片空白,效果不好。(注意:当前activity如果设置了Fullscreen,就失去效果啦!) 

参考布局代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<RelativeLayout
android:id="@+id/top_pic"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:orientation="horizontal" >

<TextView
android:id="@+id/title_tv"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
android:text="自定义标题"
android:textColor="@color/white"
android:background="#3A3C3C" />

</RelativeLayout>

<ListView
android:id="@+id/iolist_lv"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="@+id/messageinput_rl"
android:layout_below="@+id/top_pic"
android:cacheColorHint="#00000000"
android:clickable="true"
android:fadeScrollbars="true"
android:fadingEdge="none"
android:fastScrollEnabled="true"
android:focusable="true"
android:transcriptMode="normal" />

<RelativeLayout
android:id="@+id/messageinput_rl"
android:layout_width="fill_parent"
android:layout_height="60.0dip"
android:layout_alignParentBottom="true" >

<EditText
android:id="@+id/messagecontent_et"
android:layout_width="fill_parent"
android:layout_height="40.0dip"
android:layout_centerVertical="true"
android:layout_marginLeft="10.0dip"
android:layout_marginRight="10.0dip"
android:layout_toLeftOf="@+id/send_bt"
android:paddingLeft="4.0dip"
android:paddingRight="4.0dip" >
</EditText>

<Button
android:id="@+id/send_bt"
android:layout_width="wrap_content"
android:layout_height="40.0dip"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:text="发送"
android:layout_marginRight="6.0dip" />
</RelativeLayout>

</RelativeLayout>


三:补充说明

搜集整理,也不完善,有网友说,恰当使用以下代码也能实现,但个人未能实现,大神路过,多多指教:

<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp">
</ScrollView>


附上:

显示或者隐藏软键盘:

public static void toggleSoftKeyBoard(Context context, View view, boolean isShowKeyboard) {
InputMethodManager imm = (InputMethodManager) context.getSystemService(Service.INPUT_METHOD_SERVICE);
if (isShowKeyboard) {
imm.showSoftInput(view, InputMethod.SHOW_FORCED);
}else{
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}


监听软键盘的显示或隐藏:

http://winuxxan.blog.51cto.com/2779763/522810


 

 

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: