Android键盘面板冲突 布局闪动处理方案
JKeyboardPanelSwitch
起源,之前在微信工作的時(shí)候,為了給用戶(hù)帶來(lái)更好的基礎(chǔ)體驗(yàn),做了很多嘗試,踩了很多輸入法的坑,特別是動(dòng)態(tài)調(diào)整鍵盤(pán)高度,二級(jí)頁(yè)面是透明背景,魅族早期的Smart bar等, 后來(lái)逐一完善了,考慮到擁抱開(kāi)源,看業(yè)界還是有很多應(yīng)用存在類(lèi)似問(wèn)題。就有了這個(gè)repo
之前有寫(xiě)過(guò)一篇核心思想:Switching between the panel and the keyboard in Wechat
android軟鍵盤(pán)擋住輸入框問(wèn)題解決方法
1、EditText有焦點(diǎn)(focusable為true)阻止輸入法彈出
editText=(EditText)findViewById(R.id.txtBody);editText.setOnTouchListener(new OnTouchListener() {public boolean onTouch(View v, MotionEvent event) {editText.setInputType(InputType.TYPE_NULL); // 關(guān)閉軟鍵盤(pán) return false;}});2、當(dāng)EidtText無(wú)焦點(diǎn)(focusable=false)時(shí)阻止輸入法彈出
InputMethodManager imm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);3.調(diào)用顯示系統(tǒng)默認(rèn)的輸入法
方法一、
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.showSoftInput(m_receiverView(接受軟鍵盤(pán)輸入的視圖(View)),InputMethodManager.SHOW_FORCED(提供當(dāng)前操作的標(biāo)記,SHOW_FORCED表示強(qiáng)制顯示));方法二、
InputMethodManager m=(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); m.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS); (這個(gè)方法可以實(shí)現(xiàn)輸入法在窗口上切換顯示,如果輸入法在窗口上已經(jīng)顯示,則隱藏,如果隱藏,則顯示輸入法到窗口上)4.調(diào)用隱藏系統(tǒng)默認(rèn)的輸入法
((InputMethodManager)getSystemService(INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(WidgetSearchActivity.this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); (WidgetSearchActivity是當(dāng)前的Activity)5.獲取輸入法打開(kāi)的狀態(tài)
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); //isOpen若返回true,則表示輸入法打開(kāi) boolean isOpen=imm.isActive();| WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN | 軟鍵盤(pán)直接覆蓋Activity,通常這是默認(rèn)值 |
| WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | Activity高度會(huì)變化,讓出軟鍵盤(pán)的空間。和WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN 為2選1的值 |
| WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE | Activity一打開(kāi)就直接顯示軟鍵盤(pán)窗口,如果該窗口需要的話(huà)(即有EditText,或有ditable的控件) |
| WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN | Activity打開(kāi)后并不直接顯示軟鍵盤(pán)窗口,直到用戶(hù)自己touch文本框。 |
大家在布局時(shí)候,有時(shí)候會(huì)發(fā)現(xiàn)輸入框被擋住一部分,能完全顯示出來(lái),但是系統(tǒng)自帶短信界面
可以完全漂浮在軟鍵盤(pán)之上,看了一下短信源碼,修改一下輸入模式就可以了,源碼如下
代碼方式:
也可以簡(jiǎn)單點(diǎn):
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);xml方式:
<activity android:name=".Activity.FilterActivity" android:label="@string/app_name" android:windowSoftInputMode="stateHidden" android:screenOrientation="portrait" android:configChanges="keyboardHidden|orientation" />下面做個(gè)詳細(xì)的介紹:
軟輸入法模式選項(xiàng):
public int softInputMode;
以下選項(xiàng)與輸入法模式有關(guān):
軟輸入?yún)^(qū)域是否可見(jiàn)。
public static final int SOFT_INPUT_MASK_STATE = 0x0f;
未指定狀態(tài)。
public static final int SOFT_INPUT_STATE_UNSPECIFIED = 0;
不要修改軟輸入法區(qū)域的狀態(tài)。
public static final int SOFT_INPUT_STATE_UNCHANGED = 1;
隱藏輸入法區(qū)域(當(dāng)用戶(hù)進(jìn)入窗口時(shí))。
public static final int SOFT_INPUT_STATE_HIDDEN = 2;
當(dāng)窗口獲得焦點(diǎn)時(shí),隱藏輸入法區(qū)域。
public static final int SOFT_INPUT_STATE_ALWAYS_HIDDEN = 3;
顯示輸入法區(qū)域(當(dāng)用戶(hù)進(jìn)入窗口時(shí))。
public static final int SOFT_INPUT_STATE_VISIBLE = 4;
當(dāng)窗口獲得焦點(diǎn)時(shí),顯示輸入法區(qū)域。
public static final int SOFT_INPUT_STATE_ALWAYS_VISIBLE = 5;
窗口應(yīng)當(dāng)主動(dòng)調(diào)整,以適應(yīng)軟輸入窗口。
public static final int SOFT_INPUT_MASK_ADJUST = 0xf0;
未指定狀態(tài),系統(tǒng)將根據(jù)窗口內(nèi)容嘗試選擇一個(gè)輸入法樣式。
public static final int SOFT_INPUT_ADJUST_UNSPECIFIED = 0x00;
當(dāng)輸入法顯示時(shí),允許窗口重新計(jì)算尺寸,使內(nèi)容不被輸入法所覆蓋。
不可與SOFT_INPUT_ADJUSP_PAN混合使用;如果兩個(gè)都沒(méi)有設(shè)置,系統(tǒng)將根據(jù)窗口內(nèi)容自動(dòng)設(shè)置一個(gè)選項(xiàng)。
public static final int SOFT_INPUT_ADJUST_RESIZE = 0x10;
輸入法顯示時(shí)平移窗口。它不需要處理尺寸變化,框架能夠移動(dòng)窗口以確保輸入焦點(diǎn)可見(jiàn)。
不可與SOFT_INPUT_ADJUST_RESIZE混合使用;如果兩個(gè)都沒(méi)有設(shè)置,系統(tǒng)將根據(jù)窗口內(nèi)容自動(dòng)設(shè)置一個(gè)選項(xiàng)。
public static final int SOFT_INPUT_ADJUST_PAN = 0x20;
當(dāng)用戶(hù)轉(zhuǎn)至此窗口時(shí),由系統(tǒng)自動(dòng)設(shè)置,所以你不要設(shè)置它。
當(dāng)窗口顯示之后該標(biāo)志自動(dòng)清除。
public static final int SOFT_INPUT_IS_FORWARD_NAVIGATION = 0x100;
EditText導(dǎo)致的界面上移、擋住、擠壓等問(wèn)題
http://blog.csdn.net/biezhihua/article/details/51049689
布局中使用了EditText和RecyclerView,軟鍵盤(pán)彈出的時(shí)候會(huì)將界面也向上面擠
//輸入框處于中下的位置,這樣的話(huà),鍵盤(pán)可能擋住輸入框 android:windowSoftInputMode = "adjustResize" //調(diào)整屏幕的大小以便留出軟鍵盤(pán)的空間//輸入框處于偏上面,發(fā)生擠壓 android:windowSoftInputMode = "adjustPan" android:windowSoftInputMode = "stateHidden" android:fitsSystemWindows="true"使軟鍵盤(pán)不全屏顯示,只占用一部分屏幕同時(shí),這個(gè)屬性還能控件軟鍵盤(pán)右下角按鍵的顯示內(nèi)容,默認(rèn)情況下為回車(chē)鍵
android:imeOptions="flagNoExtractUi" setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);Android中軟鍵盤(pán)的使用是非常多的,下面為軟鍵盤(pán)常用的設(shè)置;
1、橫屏?xí)r,點(diǎn)擊輸入框出現(xiàn)全鍵盤(pán)解決方案: 在EditText、searchview等控件中加
android:imeOptions="flagNoExtractUi"2、豎屏?xí)r,安卓會(huì)出現(xiàn)半屏。
case1:你的輸入框處于中下的位置,這樣的話(huà),鍵盤(pán)可能擋住輸入框。 解決方法:在manifest中對(duì)activity設(shè)置
這樣activity的主窗口總會(huì)resize為鍵盤(pán)提供空間
case2:你的輸入框處于偏上面,一般情況下這樣就不會(huì)有什么問(wèn)題,但是如果你的界面縱向方面使用的是layout_weight即比重來(lái)分布頁(yè)面的話(huà),
軟件盤(pán)會(huì)壓縮整個(gè)window,導(dǎo)致輸入框部分被壓縮。 解決方法:在manifest中對(duì)activity設(shè)置
這樣鍵盤(pán)不會(huì)對(duì)壓縮原窗口,只會(huì)遮蓋下面一部分內(nèi)容。這樣輸入框不會(huì)被壓縮了。
3、剛進(jìn)入一個(gè)activity,會(huì)focus 輸入框,這時(shí)會(huì)主動(dòng)彈出軟鍵盤(pán),如果不希望自動(dòng)彈出,那么可先讓其他的不重要的控件獲取焦點(diǎn),然后一個(gè)定時(shí)器
再讓EditText獲取焦點(diǎn)即可!
4、判斷軟鍵盤(pán)當(dāng)前是否處于彈出狀態(tài)
if(getWindow().getAttributes().softInputMode==WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE)
5、手動(dòng)隱藏軟鍵盤(pán)
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
6、手動(dòng)彈出軟鍵盤(pán)
((InputMethodManager)getSystemService(INPUT_METHOD_SERVICE)).toggleSoftInput(0,InputMethodManager.HIDE_NOT_ALWAYS);
自動(dòng)彈出軟鍵盤(pán)
剛進(jìn)入activity的時(shí)候,如果布局組件有edittext的話(huà),往往edittext會(huì)獲取焦點(diǎn),自動(dòng)彈出軟鍵盤(pán),影響整個(gè)界面的視覺(jué)效果。解決方法如下:
可以在edittext的父布局結(jié)構(gòu)中(例如LinearLayout,RelativeLayout等)添加
android:focusable="true" android:focusableInTouchMode="true"或者
<activity android:name=".MainActivity"android:windowSoftInputMode="stateHidden" > </activity>Android中的windowSoftInputMode屬性詳解
這篇文章主要介紹了Android中的windowSoftInputMode屬性詳解,本文對(duì)windowSoftInputMode的9個(gè)屬性做了詳細(xì)總結(jié),需要的朋友可以參考下
在前面的一篇文章中,簡(jiǎn)單的介紹了一下如何實(shí)現(xiàn)軟鍵盤(pán)不自動(dòng)彈出,使用的方法是設(shè)置android:windowSoftInputMode屬性。那么,這個(gè)屬性到底是干什么的,他有什么作用呢?今天這篇文章,就是探索android:windowSoftInputMode屬性的作用的。
首先,我們從這個(gè)屬性的名稱(chēng)中,可以很直觀的看出它的作用,這個(gè)屬性就是來(lái)設(shè)置窗口軟鍵盤(pán)的交互模式的。
android:windowSoftInputMode屬性一共有9個(gè)取值,分別是:
- stateUnspecified
- stateUnchanged
- stateHidden
- stateAlwaysHidden
- stateVisible
- stateAlwaysVisible
- adjustUnspecified
- adjustResize
- adjustPan
我們?cè)O(shè)置屬性的時(shí)候,可以在這9個(gè)值里面選擇一個(gè),也可以用”state…|adjust”的形式進(jìn)行設(shè)置。那么,這些取值到底是怎么影響到軟鍵盤(pán)與窗口之間的交互的呢?下面,我們就一個(gè)個(gè)的測(cè)試這9個(gè)取值,到底是如何影響軟鍵盤(pán)的顯示的。
1.stateUnspecified
中文意思是未指定狀態(tài),當(dāng)我們沒(méi)有設(shè)置android:windowSoftInputMode屬性的時(shí)候,軟件默認(rèn)采用的就是這種交互方式,系統(tǒng)會(huì)根據(jù)界面采取相應(yīng)的軟鍵盤(pán)的顯示模式,比如,當(dāng)界面上只有文本和按鈕的時(shí)候,軟鍵盤(pán)就不會(huì)自動(dòng)彈出,因?yàn)闆](méi)有輸入的必要。那么,當(dāng)界面上出現(xiàn)了獲取了焦點(diǎn)的輸入框的時(shí)候,軟鍵盤(pán)會(huì)不會(huì)自動(dòng)的彈出呢?這個(gè)還真不一定!比如,在下面的這個(gè)界面布局中,軟鍵盤(pán)并不會(huì)自動(dòng)彈出。
就是說(shuō),默認(rèn)的,在這種界面情況下,系統(tǒng)并不確定用戶(hù)是否需要軟鍵盤(pán),因此不會(huì)自動(dòng)彈出。但是,為什么說(shuō)不一定呢?這是因?yàn)?#xff0c;如果我們?cè)谶@個(gè)布局的外面,包裹上一個(gè)ScrollView,軟鍵盤(pán)就會(huì)自動(dòng)的彈出來(lái)了!如下,在這種布局文件下,軟鍵盤(pán)會(huì)自動(dòng)的彈出
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><ScrollView android:layout_width="match_parent"android:layout_height="match_parent" ><LinearLayout android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical" ><Button android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="toOther"android:text="跳轉(zhuǎn)" /><EditText android:layout_width="match_parent"android:layout_height="wrap_content" /></LinearLayout></ScrollView></LinearLayout>這確實(shí)是一個(gè)很奇怪的判斷方式。因此,我們可以得出結(jié)論,當(dāng)設(shè)置屬性為stateUnspecified的時(shí)候,系統(tǒng)是默認(rèn)不彈出軟鍵盤(pán)的,但是當(dāng)有獲得焦點(diǎn)的輸入框的界面有滾動(dòng)的需求的時(shí)候,會(huì)自動(dòng)彈出軟鍵盤(pán)。至于為什么非要強(qiáng)調(diào)要獲取焦點(diǎn)的輸入框,這是因?yàn)?#xff0c;如果不是輸入框獲取焦點(diǎn),軟鍵盤(pán)也是不會(huì)自動(dòng)彈出的,讓界面不自動(dòng)彈出軟鍵盤(pán)的其中一個(gè)解決方案,就是在xml文件中,設(shè)置一個(gè)非輸入框控件獲取焦點(diǎn),從而阻止鍵盤(pán)彈出。
2. stateUnchanged
中文的意思就是狀態(tài)不改變的意思,我們應(yīng)該怎么理解這句話(huà)呢?其實(shí)很好理解,就是說(shuō),當(dāng)前界面的軟鍵盤(pán)狀態(tài),取決于上一個(gè)界面的軟鍵盤(pán)狀態(tài)。舉個(gè)例子,假如當(dāng)前界面鍵盤(pán)是隱藏的,那么跳轉(zhuǎn)之后的界面,軟鍵盤(pán)也是隱藏的;如果當(dāng)前界面是顯示的,那么跳轉(zhuǎn)之后的界面,軟鍵盤(pán)也是顯示狀態(tài)。
3. stateHidden
顧名思義,如果我們?cè)O(shè)置了這個(gè)屬性,那么鍵盤(pán)狀態(tài)一定是隱藏的,不管上個(gè)界面什么狀態(tài),也不管當(dāng)前界面有沒(méi)有輸入的需求,反正就是不顯示。因此,我們可以設(shè)置這個(gè)屬性,來(lái)控制軟鍵盤(pán)不自動(dòng)的彈出。
4. stateAlwaysHidden
這個(gè)屬性也可以讓軟鍵盤(pán)隱藏,但是我暫時(shí)還不知道和stateHidden屬性的區(qū)別,本來(lái)想去stackOverFlow上問(wèn)一下的,但是,Great Wall,呵呵呵…祝愿病魔早日戰(zhàn)勝方校長(zhǎng)
5.stateVisible
設(shè)置為這個(gè)屬性,可以將軟鍵盤(pán)召喚出來(lái),即使在界面上沒(méi)有輸入框的情況下也可以強(qiáng)制召喚出來(lái)。
6.stateAlwaysVisible
這個(gè)屬性也是可以將鍵盤(pán)召喚出來(lái),但是與stateVisible屬性有小小的不同之處。舉個(gè)例子,當(dāng)我們?cè)O(shè)置為stateVisible屬性,如果當(dāng)前的界面鍵盤(pán)是顯示的,當(dāng)我們點(diǎn)擊按鈕跳轉(zhuǎn)到下個(gè)界面的時(shí)候,軟鍵盤(pán)會(huì)因?yàn)檩斎肟蚴ソ裹c(diǎn)而隱藏起來(lái),當(dāng)我們?cè)俅位氐疆?dāng)前界面的時(shí)候,鍵盤(pán)這個(gè)時(shí)候是隱藏的。但是如果我們?cè)O(shè)置為stateAlwaysVisible,我們跳轉(zhuǎn)到下個(gè)界面,軟鍵盤(pán)還是隱藏的,但是當(dāng)我們?cè)俅位貋?lái)的時(shí)候,軟鍵盤(pán)是會(huì)顯示出來(lái)的。所以,這個(gè)Always就解釋了這個(gè)區(qū)別,不管什么情況到達(dá)當(dāng)前界面(正常跳轉(zhuǎn)或者是上一個(gè)界面被用戶(hù)返回),軟鍵盤(pán)都是顯示狀態(tài)。 說(shuō)到這里,我聯(lián)想到了上面的stateHidden和stateAlwaysHidden,我估計(jì)區(qū)別也是這樣的,就是說(shuō),stateAlwaysHidden無(wú)論如何都是隱藏的,但是如果在跳轉(zhuǎn)到下個(gè)界面的時(shí)候,軟鍵盤(pán)被召喚出來(lái)了,那么當(dāng)下個(gè)界面被用戶(hù)返回的時(shí)候,鍵盤(pán)應(yīng)該是不會(huì)被隱藏的,但是,我還沒(méi)有找到能夠跳轉(zhuǎn)到下個(gè)界面,還讓當(dāng)前界面軟鍵盤(pán)不消失的方法,所以暫時(shí)不能驗(yàn)證。7.adjustUnspecified
從這個(gè)屬性開(kāi)始,就不是設(shè)置軟鍵盤(pán)的顯示與隱藏模式了,而是設(shè)置軟鍵盤(pán)與軟件的顯示內(nèi)容之間的顯示關(guān)系。當(dāng)你跟我們沒(méi)有設(shè)置這個(gè)值的時(shí)候,這個(gè)選項(xiàng)也是默認(rèn)的設(shè)置模式。在這中情況下,系統(tǒng)會(huì)根據(jù)界面選擇不同的模式。如果界面里面有可以滾動(dòng)的控件,比如ScrowView,系統(tǒng)會(huì)減小可以滾動(dòng)的界面的大小,從而保證即使軟鍵盤(pán)顯示出來(lái)了,也能夠看到所有的內(nèi)容。如果布局里面沒(méi)有滾動(dòng)的控件,那么軟鍵盤(pán)可能就會(huì)蓋住一些內(nèi)容,我們從下面的圖中可以看出差別。沒(méi)有滾動(dòng)控件,軟鍵盤(pán)下面的布局都被遮擋住了,若想修改,只能隱藏軟鍵盤(pán),然后選擇。而且,重點(diǎn)注意一下上面的布局,當(dāng)我們選擇的輸入框偏下的時(shí)候,上面的標(biāo)題欄和布局被軟鍵盤(pán)頂上去了。記住這個(gè)特征,因?yàn)楹竺嬗袀€(gè)屬性和這個(gè)的效果不一樣。
布局里面有滑動(dòng)控件,系統(tǒng)會(huì)自動(dòng)的縮小整個(gè)界面的大小,因此,我們可以軟鍵盤(pán)上面的小區(qū)域中顯示所有的輸入框。
這就是兩中顯示模式之間的差別。
8. adjustResize
這個(gè)屬性表示Activity的主窗口總是會(huì)被調(diào)整大小,從而保證軟鍵盤(pán)顯示空間。
我們先看顯示效果。
注意觀察這個(gè)上面的標(biāo)題欄和按鈕,設(shè)置為adjustResize屬性之后,對(duì)于沒(méi)有滑動(dòng)控件的布局,雖然還是不能選擇所有的輸入框,但是,窗口的顯示方式發(fā)生了變化,默認(rèn)屬性時(shí),整個(gè)布局是被頂上去了,但是設(shè)置為adjustResize屬性,布局的位置并沒(méi)有發(fā)生什么變化,這就是最大的區(qū)別。
而對(duì)于有滑動(dòng)控件的布局來(lái)說(shuō),顯示效果和默認(rèn)是一樣的。
9. adjustPan
如果設(shè)置為這個(gè)屬性,那么Activity的屏幕大小并不會(huì)調(diào)整來(lái)保證軟鍵盤(pán)的空間,而是采取了另外一種策略,系統(tǒng)會(huì)通過(guò)布局的移動(dòng),來(lái)保證用戶(hù)要進(jìn)行輸入的輸入框肯定在用戶(hù)的失業(yè)范圍里面,從而讓用戶(hù)可以看到自己輸入的內(nèi)容。對(duì)于沒(méi)有滾動(dòng)控件的布局來(lái)說(shuō),這個(gè)其實(shí)就是默認(rèn)的設(shè)置,如果我們選擇的位置偏下,上面的標(biāo)題欄和部分控件會(huì)被頂上去。但是對(duì)于有滾動(dòng)控件的布局來(lái)說(shuō),則不太一樣,我們看下面的效果圖。
首先,這是軟鍵盤(pán)沒(méi)有彈出的時(shí)候,有滾動(dòng)控件的顯示范圍,最下面顯示的是9.
當(dāng)我們點(diǎn)擊5這個(gè)輸入框,我們會(huì)發(fā)現(xiàn)下面的現(xiàn)象。
最上面只能夠顯示到按鈕,標(biāo)題欄已經(jīng)不能看到了。
而最下面也只能滑動(dòng)到8,下面的內(nèi)容也不能夠滑動(dòng)了。
因此,我們就能夠理解這個(gè)屬性的作用了。
通過(guò)以上的實(shí)驗(yàn),我們可以得出結(jié)論,如果我們不設(shè)置”adjust…”的屬性,對(duì)于沒(méi)有滾動(dòng)控件的布局來(lái)說(shuō),采用的是adjustPan方式,而對(duì)于有滾動(dòng)控件的布局,則是采用的adjustResize方式。
了解了上面的這些知識(shí)之后,我們就可以根據(jù)自己的需求設(shè)置不同的方式了。而且,關(guān)于如何使得界面加載的時(shí)候不顯示軟鍵盤(pán),我們也有了一個(gè)很清楚的認(rèn)識(shí)。
總結(jié)
以上是生活随笔為你收集整理的Android键盘面板冲突 布局闪动处理方案的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Android Cursor自动更新的实
- 下一篇: Android 开源之StickyHea