關(guān)于輸入框肯定有很多困惑饰剥。個(gè)人就有困惑來著忠荞。蒋歌。。
主要分幾種使用場(chǎng)景:
1. 進(jìn)入有EditText控件的頁面委煤,默認(rèn)會(huì)彈出軟鍵盤堂油?
2. 進(jìn)入帶輸入框的界面,默認(rèn)不彈出軟鍵盤
3. 點(diǎn)擊輸入框彈出后碧绞,點(diǎn)擊其他按鈕手動(dòng)軟鍵盤或者退出頁面時(shí)隱藏軟鍵盤府框;
4. 多個(gè)輸入框焦點(diǎn)獲取如何顯示next按鍵,以便跳轉(zhuǎn)到下一個(gè)輸入框讥邻;
5. 其他的呢迫靖? 在想想看...先把上面驗(yàn)證下吧....
1. 先從xml著手這個(gè)鍵盤是否默認(rèn)彈窗來的問題吧..focus?
1.1 Activity界面如果存在輸入框,默認(rèn)彈窗鍵盤
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".SoftkeyActivity">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/app_name"
android:textSize="20sp"
android:textColor="@color/colorAccent"/>
<TextView
android:onClick="fucnSbs"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="彈個(gè)球窗(帶輸入框)"/>
</android.support.constraint.ConstraintLayout>
1.1.1 當(dāng)進(jìn)入界面時(shí)你會(huì)發(fā)現(xiàn)鍵盤并沒有彈出來兴使?系宜? 我印象中,如果是HomeActvity鲫惶,如果底部有搜索框是會(huì)默認(rèn)彈出來的蜈首。還會(huì)把底部的導(dǎo)航欄頂上去....這個(gè)解決辦法是:
<activity
android:name=".app.HomeActivity"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:theme="@style/MineActivityAppTheme"
android:windowSoftInputMode="adjustPan|stateHidden" />
看區(qū)別
"adjustResize"
該活動(dòng)的主窗口始終調(diào)整大小实抡,以使屏幕上的軟鍵盤的余地欠母。
"adjustPan"
該活動(dòng)的主窗口無法調(diào)整大小欢策,使軟鍵盤的余地。
相反赏淌,窗口的內(nèi)容是自動(dòng)平移以便當(dāng)前焦點(diǎn)從來沒有遮擋鍵盤踩寇,用戶始終可以看到他們正在鍵入。
這是比調(diào)整大小六水,一般是較不可取俺孙,因?yàn)橛脩艨赡苄枰P(guān)閉軟鍵盤在獲取和與模糊部分窗口的互動(dòng)。
就是說掷贾,如果你不喜歡窗口被調(diào)整睛榄,比如底部導(dǎo)航欄被強(qiáng)行頂上去,以便留出空間給鍵盤想帅。那么就需要設(shè)置為adjustPan...同時(shí)你不喜歡進(jìn)入主頁就彈窗鍵盤场靴,那就stateHidden。
綜上我們就可以解決進(jìn)入帶搜索的主頁的問題 --- 其他的屬性其實(shí)內(nèi)容還是不少港准。暫時(shí)我們放到下篇分析吧.....
1.1.2 現(xiàn)在我們是想讓頁面彈窗鍵盤旨剥,那就簡(jiǎn)單了吧。浅缸。轨帜。
看圖說話就行,不想用adjustresize就別用哈....
1.2 問題來了衩椒,如果是一個(gè)Dialog呢蚌父?有沒有xml可以給你去配置dialog屬性呀! 你基本上找相關(guān)資料毛萌,基本都是用代碼梢什。。那我們也用代碼吧朝聋。干嘛非得xml妮嗡午!
1.2.1 隨便創(chuàng)建個(gè)dialog
package com.example.lieyun_android.myapplication;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.View;
public class CustomSoftDialog extends Dialog {
private Context mContext;
public CustomSoftDialog(@NonNull Context context) {
super(context);
mContext = context;
}
public CustomSoftDialog(@NonNull Context context, int themeResId) {
super(context, themeResId);
}
protected CustomSoftDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) {
super(context, cancelable, cancelListener);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View view = View.inflate(mContext, R.layout.dialog_layout,null);
setContentView(view);
}
}
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SoftkeyActivity">
<EditText
android:id="@+id/ddddd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/app_name"
android:textColor="@color/colorAccent"
android:textSize="20sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="fucnSbs"
android:text="彈個(gè)球窗(帶輸入框)"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/ddddd" />
</android.support.constraint.ConstraintLayout>
然后彈一彈:
new CustomSoftDialog(this).show();
1.2.1 此時(shí)并沒有彈出來鍵盤。我們看看代碼好伐冀痕? 不過需要注意的時(shí)候荔睹,有時(shí)候你在頁面初始化里面彈貌似會(huì)彈不出來 - 由于界面還未被初始化,所以需要一個(gè)彈窗顯示完的事件里面或者延遲彈等方式言蛇!
Let's do it:
Dialog dlg;
dlg = new CustomSoftDialog(this);
dlg.setOnShowListener(new DialogInterface.OnShowListener() {
public void onShow(DialogInterface dialog) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
///< 隱藏就顯示僻他,顯示就隱藏 - 這種有時(shí)候再邏輯上會(huì)給你帶來困擾,如果要強(qiáng)制隱藏腊尚,建議用別的方式吨拗;不要靠什么Boolean狀態(tài)來做..
imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
}
});
dlg.show();
這樣就可以彈出來了呀 - 后面還會(huì)說明一些參數(shù)和更多的方式以及區(qū)別:
右側(cè)有想法方法結(jié)束,后面我們一起去看看吧~~(它這個(gè)搜索不得勁,不能模糊搜索....差勁了有點(diǎn))
好吧劝篷。我們看一段toggleSoftInput的介紹吧....
toggleSoftInput
added in API level 3
public void toggleSoftInput (int showFlags,
int hideFlags)
This method toggles the input method window display. If the input window is already displayed, it gets hidden. If not the input window will be displayed.
Parameters
showFlags int: Provides additional operating flags. May be 0 or have the SHOW_IMPLICIT, SHOW_FORCED bit set.
hideFlags int: Provides additional operating flags. May be 0 or have the HIDE_IMPLICIT_ONLY, HIDE_NOT_ALWAYS bit set.
解釋:反正就是說如果顯示了哨鸭,那么再次調(diào)用會(huì)隱藏。反之娇妓,則會(huì)顯示像鸡。
再看哈里面的flag說明:
showFlags為顯示軟鍵盤時(shí)使用的標(biāo)記,只有當(dāng)前軟鍵盤處于隱藏狀態(tài)時(shí)才會(huì)使用哈恰。hideFlags是隱藏軟鍵盤時(shí)使用的標(biāo)記只估,只有當(dāng)前軟鍵盤處于顯示狀態(tài)時(shí)才會(huì)使用。
showFlags和hideFlags取值范圍着绷,以及不同取值的影響和上文分析的一樣蛔钙。
即showFlags和hideFlags都只影響軟鍵盤的隱藏,不影響軟鍵盤的顯示荠医。
不同取值對(duì)軟鍵盤隱藏的影響參見上文中的表格夸楣。
當(dāng)顯示軟鍵盤時(shí),并不要求當(dāng)前界面布局中有一個(gè)已經(jīng)獲取焦點(diǎn)的EditText子漩,
即使當(dāng)前布局是完全空白的豫喧,一個(gè)View也沒有(除了最外層的Layout),
toggleSoftInput也能夠顯示軟鍵盤幢泼。不過如果沒有一個(gè)已經(jīng)獲取焦點(diǎn)的EditText紧显,那么軟鍵盤中的按鍵輸入都是無效的。
那HIDE_NOT_ALWAYS呢缕棵?
HIDE_NOT_ALWAYS
added in API level 3
public static final int HIDE_NOT_ALWAYS
Flag for hideSoftInputFromWindow(IBinder, int) and InputMethodService.requestShowSelf(int) to indicate that the soft input window should normally be hidden, unless it was originally shown with SHOW_FORCED.
Constant Value: 2 (0x00000002)
解釋: 它表明了soft input widows正常情況都應(yīng)該隱藏孵班,除非之前采用[SHOW_FORCED](https://link.zhihu.com/?target=https%3A//developer.android.google.cn/reference/android/view/inputmethod/InputMethodManager.html%23SHOW_FORCED)
的方式顯示。 個(gè)人理解就是說招驴,如果你是用show_froced顯示的篙程。那么你用這種方式顯示是不不能隱藏的了。 - 我們?cè)囋嚳窗杀鹄澹梅?
1.2.1.1 按照官方說法采用SHOW_FORCED顯示之后虱饿,我們用toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS); 就沒有用了。無法隱藏的呀触趴。氮发。。啊哈冗懦。
而看force:
SHOW_FORCED
added in API level 3
public static final int SHOW_FORCED
Flag for showSoftInput(View, int) to indicate that the user has forced the input method open (such as by long-pressing menu) so it should not be closed until they explicitly do so.
Constant Value: 2 (0x00000002)
所以我們需要采用showSoftInput來強(qiáng)制顯示的喲爽冕。 而不是說采用了imm.toggleSoftInput(0, InputMethodManager.SHOW_FORCED); 的不能隱藏。披蕉。颈畸。我們有時(shí)候需要關(guān)注參數(shù)的說明和用法乌奇,再結(jié)合整體,不然容易迷霧...對(duì)眯娱,迷霧...
看顯示 - View view1 = dlg.findViewById(R.id.ddddd);這個(gè)放到里面喲礁苗,不然找不到控件了就麻煩了....:
final Dialog dlg;
dlg = new CustomSoftDialog(this);
dlg.setOnShowListener(new DialogInterface.OnShowListener() {
public void onShow(DialogInterface dialog) {
View view1 = dlg.findViewById(R.id.ddddd);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
///< 隱藏就顯示,顯示就隱藏 - 這種有時(shí)候再邏輯上會(huì)給你帶來困擾困乒,如果要強(qiáng)制隱藏寂屏,建議用別的方式贰谣;不要靠什么Boolean狀態(tài)來做..
imm.showSoftInput(view1, InputMethodManager.SHOW_FORCED);
}
});
dlg.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
}
});
dlg.setCanceledOnTouchOutside(false);
dlg.show();
再看下點(diǎn)擊dialog里面的文本的點(diǎn)擊事件隱藏的代碼:
public void fucnSbsddd(View view) {
Toast.makeText(this, "fuck娜搂,不能被隱藏了呀", Toast.LENGTH_SHORT).show();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
///< 隱藏就顯示,顯示就隱藏 - 這種有時(shí)候再邏輯上會(huì)給你帶來困擾吱抚,如果要強(qiáng)制隱藏百宇,建議用別的方式;不要靠什么Boolean狀態(tài)來做..
imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
}
1.2.2.2 說明個(gè)人就大概先這樣理解秘豹。我想后續(xù)的屬性還是蠻多的携御。不過我們可以去分析,嘗試既绕,然后總結(jié)啄刹,然后糾錯(cuò),然后再分析凄贩,總會(huì)弄清楚一些事情的誓军。有個(gè)思路就行。疲扎。昵时。這篇我們先把實(shí)際用的來實(shí)踐下吧。椒丧。壹甥。別的后面慢慢來。不然一下子是總結(jié)不完了的....
2.既然說到了顯示壶熏,我們簡(jiǎn)單的使用應(yīng)該是問題不大句柠。平時(shí)需求多半也就是進(jìn)入頁面是否彈不彈的問題。其實(shí)比較麻煩的可能是隱藏了吧棒假。俄占。。
比如點(diǎn)擊登錄按鈕淆衷,需要先隱藏鍵盤缸榄;頁面消失也需要隱藏鍵盤;個(gè)人目前主要就是這兩種狀態(tài)祝拯。
2.1 隱藏方式之上面的toggleSoftInput方式:
inputMethodManager.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
這個(gè)有個(gè)邏輯問題甚带,你如果是點(diǎn)擊輸入框彈出了鍵盤她肯, 登錄事件里面你想調(diào)用隱藏,這個(gè)邏輯沒問題鹰贵。 但是如果你打開鍵盤后晴氨,點(diǎn)擊鍵盤上的收回鍵。 然后當(dāng)你點(diǎn)擊登錄時(shí)碉输,會(huì)彈出來籽前。這個(gè)不是我們要的效果? 此時(shí)你可能就需要判斷鍵盤狀態(tài)敷钾,如果是隱藏不可用枝哄,則點(diǎn)擊登錄的時(shí)候不能調(diào)用這種隱藏方法了。 稍微顯得有點(diǎn)麻煩....
2.2 隱藏方式之showSoftInput阻荒?挠锥??別鬧了侨赡,好伐蓖租,這明明是顯示方法嗎...哈哈哈。羊壹。蓖宦。。
2.3 隱藏方式之hideSoftInputFromWindow的方法
顯示:
Dialog dlg;
public void fucnSbs(View view) {
dlg = new CustomSoftDialog(this);
dlg.setOnShowListener(new DialogInterface.OnShowListener() {
public void onShow(DialogInterface dialog) {
View view1 = dlg.findViewById(R.id.ddddd);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
///< 隱藏就顯示油猫,顯示就隱藏 - 這種有時(shí)候再邏輯上會(huì)給你帶來困擾稠茂,如果要強(qiáng)制隱藏,建議用別的方式眨攘;不要靠什么Boolean狀態(tài)來做..
//imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
imm.showSoftInput(view1, InputMethodManager.SHOW_IMPLICIT);
}
});
dlg.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
}
});
dlg.setCanceledOnTouchOutside(false);
dlg.show();
}
隱藏走一走:
public void fucnSbsddd(View view) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
///< 隱藏就顯示主慰,顯示就隱藏 - 這種有時(shí)候再邏輯上會(huì)給你帶來困擾,如果要強(qiáng)制隱藏鲫售,建議用別的方式共螺;不要靠什么Boolean狀態(tài)來做..
imm.hideSoftInputFromWindow(dlg.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
效果沒問題。隱藏了就隱藏了呀情竹。藐不。。秦效。也不用像toggle那樣需要判斷狀態(tài)雏蛮,以免混亂...
那Activity呢?我們也試試...
Actv也沒問題呀阱州。挑秉。。我們封裝下吧:
/*
*@Description: 隱藏鍵盤2
*@Author: hl
*@Time: 2018/8/21 11:57
*/
public static void hideKeyBord(Activity context) {
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm.isActive() && context.getCurrentFocus() != null) {
if (context.getCurrentFocus().getWindowToken() != null) {
imm.hideSoftInputFromWindow(context.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
}
}
貌似基本上我們的顯示隱藏基本就夠用了苔货。 目前來看個(gè)人的幾個(gè)項(xiàng)目都基本夠用了額....
3.我們還是來看看hideSoftInputFromWindow吧犀概。立哑。
hideSoftInputFromWindow
added in API level 3
public boolean hideSoftInputFromWindow (IBinder windowToken,
int flags)
Synonym for hideSoftInputFromWindow(IBinder, int, ResultReceiver) without a result: request to hide the soft input window from the context of the window that is currently accepting input.
Parameters
windowToken IBinder: The token of the window that is making the request, as returned by View.getWindowToken().
flags int: Provides additional operating flags. Currently may be 0 or have the HIDE_IMPLICIT_ONLY bit set.
解釋: 意思就是說這是一種不帶結(jié)果返回的隱藏軟鍵盤的方式,其中flag可以是0或者[HIDE_IMPLICIT_ONLY](https://link.zhihu.com/?target=https%3A//developer.android.google.cn/reference/android/view/inputmethod/InputMethodManager.html%23HIDE_IMPLICIT_ONLY)
設(shè)置 - 咦姻灶? 也就是說我們之前的第二個(gè)參數(shù)有問題铛绰,雖然效果不影響,但是還是遵循官方建議給個(gè)0算了2怼N骊! 這個(gè)token是當(dāng)前顯示鍵盤的view的.[getWindowToken()](https://link.zhihu.com/?target=https%3A//developer.android.google.cn/reference/android/view/View.html%23getWindowToken%28%29)
即可獲取....實(shí)際上曾沈,只要是當(dāng)前界面的view獲取的token都可以隱藏 --- 具體什么原理的这嚣。沒研究過。晦譬。疤苹。互广。飄過~~~
而第二個(gè)參數(shù)給0敛腌, 如果給 HIDE_IMPLICIT_ONLY,用這種方式隱藏的話惫皱,那么顯示時(shí)也就需要這種方式才能顯示像樊。 有點(diǎn)像force的情況。 他們之間應(yīng)該是有相對(duì)關(guān)系的旅敷。生棍。。媳谁。
這是目前從官方文檔和實(shí)踐來看涂滴,個(gè)人的一些總結(jié)吧。 我覺得后續(xù)有空還是應(yīng)該深入分析和實(shí)踐下這些個(gè)參數(shù)晴音。柔纵。。其實(shí)個(gè)人不太明白google設(shè)計(jì)了這些個(gè)復(fù)雜的并且對(duì)外提供的方式? 為什么不提供簡(jiǎn)單的隱藏顯示锤躁。搁料。∠敌撸或者看過原理的人會(huì)比較明白...
對(duì)了后來看了一篇文章分析郭计,將的還比較細(xì)。 比較值得參考....當(dāng)然筆者建議從官方文檔入手椒振,印象更深....后面我們?cè)倮^續(xù)搞吧...要學(xué)習(xí)的東西還再很多....