Android默認(rèn)不彈出軟鍵盤(pán)-第二彈-較完整實(shí)踐君

關(guān)于輸入框肯定有很多困惑。個(gè)人就有困惑來(lái)著。。。

主要分幾種使用場(chǎng)景:

1. 進(jìn)入有EditText控件的頁(yè)面,默認(rèn)會(huì)彈出軟鍵盤(pán)?

2. 進(jìn)入帶輸入框的界面,默認(rèn)不彈出軟鍵盤(pán)

3. 點(diǎn)擊輸入框彈出后,點(diǎn)擊其他按鈕手動(dòng)軟鍵盤(pán)或者退出頁(yè)面時(shí)隱藏軟鍵盤(pán);

4. 多個(gè)輸入框焦點(diǎn)獲取如何顯示next按鍵,以便跳轉(zhuǎn)到下一個(gè)輸入框;

5. 其他的呢? 在想想看...先把上面驗(yàn)證下吧....

1. 先從xml著手這個(gè)鍵盤(pán)是否默認(rèn)彈窗來(lái)的問(wèn)題吧..focus?

1.1 Activity界面如果存在輸入框,默認(rèn)彈窗鍵盤(pá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>
image

1.1.1 當(dāng)進(jìn)入界面時(shí)你會(huì)發(fā)現(xiàn)鍵盤(pán)并沒(méi)有彈出來(lái)?? 我印象中,如果是HomeActvity,如果底部有搜索框是會(huì)默認(rèn)彈出來(lái)的。還會(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)整大小,以使屏幕上的軟鍵盤(pán)的余地。
"adjustPan"
該活動(dòng)的主窗口無(wú)法調(diào)整大小,使軟鍵盤(pán)的余地。
相反,窗口的內(nèi)容是自動(dòng)平移以便當(dāng)前焦點(diǎn)從來(lái)沒(méi)有遮擋鍵盤(pán),用戶始終可以看到他們正在鍵入。
這是比調(diào)整大小,一般是較不可取,因?yàn)橛脩艨赡苄枰P(guān)閉軟鍵盤(pán)在獲取和與模糊部分窗口的互動(dòng)。

就是說(shuō),如果你不喜歡窗口被調(diào)整,比如底部導(dǎo)航欄被強(qiáng)行頂上去,以便留出空間給鍵盤(pán)。那么就需要設(shè)置為adjustPan...同時(shí)你不喜歡進(jìn)入主頁(yè)就彈窗鍵盤(pán),那就stateHidden。

綜上我們就可以解決進(jìn)入帶搜索的主頁(yè)的問(wèn)題 --- 其他的屬性其實(shí)內(nèi)容還是不少。暫時(shí)我們放到下篇分析吧.....

1.1.2 現(xiàn)在我們是想讓頁(yè)面彈窗鍵盤(pán),那就簡(jiǎn)單了吧。。。

看圖說(shuō)話就行,不想用adjustresize就別用哈....

image

1.2 問(wèn)題來(lái)了,如果是一個(gè)Dialog呢?有沒(méi)有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();
image

1.2.1 此時(shí)并沒(méi)有彈出來(lái)鍵盤(pán)。我們看看代碼好伐? 不過(guò)需要注意的時(shí)候,有時(shí)候你在頁(yè)面初始化里面彈貌似會(huì)彈不出來(lái) - 由于界面還未被初始化,所以需要一個(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ì)給你帶來(lái)困擾,如果要強(qiáng)制隱藏,建議用別的方式;不要靠什么Boolean狀態(tài)來(lái)做..
                imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
            }
        });
        dlg.show();

這樣就可以彈出來(lái)了呀 - 后面還會(huì)說(shuō)明一些參數(shù)和更多的方式以及區(qū)別:

官方文檔鏈表: https://developer.android.google.cn/reference/android/view/inputmethod/InputMethodManager#InputMethods

右側(cè)有想法方法結(jié)束,后面我們一起去看看吧~~(它這個(gè)搜索不得勁,不能模糊搜索....差勁了有點(diǎn))

image

好吧。我們看一段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.

解釋:反正就是說(shuō)如果顯示了,那么再次調(diào)用會(huì)隱藏。反之,則會(huì)顯示。

再看哈里面的flag說(shuō)明:

 showFlags為顯示軟鍵盤(pán)時(shí)使用的標(biāo)記,只有當(dāng)前軟鍵盤(pán)處于隱藏狀態(tài)時(shí)才會(huì)使用。hideFlags是隱藏軟鍵盤(pán)時(shí)使用的標(biāo)記,只有當(dāng)前軟鍵盤(pán)處于顯示狀態(tài)時(shí)才會(huì)使用。
showFlags和hideFlags取值范圍,以及不同取值的影響和上文分析的一樣。
即showFlags和hideFlags都只影響軟鍵盤(pán)的隱藏,不影響軟鍵盤(pán)的顯示。
不同取值對(duì)軟鍵盤(pán)隱藏的影響參見(jiàn)上文中的表格。
當(dāng)顯示軟鍵盤(pán)時(shí),并不要求當(dāng)前界面布局中有一個(gè)已經(jīng)獲取焦點(diǎn)的EditText,
即使當(dāng)前布局是完全空白的,一個(gè)View也沒(méi)有(除了最外層的Layout),
toggleSoftInput也能夠顯示軟鍵盤(pán)。不過(guò)如果沒(méi)有一個(gè)已經(jīng)獲取焦點(diǎn)的EditText,那么軟鍵盤(pán)中的按鍵輸入都是無(wú)效的。

那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è)人理解就是說(shuō),如果你是用show_froced顯示的。那么你用這種方式顯示是不不能隱藏的了。 - 我們?cè)囋嚳窗?,好?

1.2.1.1 按照官方說(shuō)法采用SHOW_FORCED顯示之后,我們用toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS); 就沒(méi)有用了。無(wú)法隱藏的呀。。。啊哈。

而看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來(lái)強(qiáng)制顯示的喲。 而不是說(shuō)采用了imm.toggleSoftInput(0, InputMethodManager.SHOW_FORCED); 的不能隱藏。。。我們有時(shí)候需要關(guān)注參數(shù)的說(shuō)明和用法,再結(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ì)給你帶來(lái)困擾,如果要強(qiáng)制隱藏,建議用別的方式;不要靠什么Boolean狀態(tài)來(lá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ì)給你帶來(lái)困擾,如果要強(qiáng)制隱藏,建議用別的方式;不要靠什么Boolean狀態(tài)來(lái)做..
        imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
    }
image

1.2.2.2 說(shuō)明個(gè)人就大概先這樣理解。我想后續(xù)的屬性還是蠻多的。不過(guò)我們可以去分析,嘗試,然后總結(jié),然后糾錯(cuò),然后再分析,總會(huì)弄清楚一些事情的。有個(gè)思路就行。。。這篇我們先把實(shí)際用的來(lái)實(shí)踐下吧。。。別的后面慢慢來(lái)。不然一下子是總結(jié)不完了的....

2.既然說(shuō)到了顯示,我們簡(jiǎn)單的使用應(yīng)該是問(wèn)題不大。平時(shí)需求多半也就是進(jìn)入頁(yè)面是否彈不彈的問(wèn)題。其實(shí)比較麻煩的可能是隱藏了吧。。。

比如點(diǎn)擊登錄按鈕,需要先隱藏鍵盤(pán);頁(yè)面消失也需要隱藏鍵盤(pán);個(gè)人目前主要就是這兩種狀態(tài)。

2.1 隱藏方式之上面的toggleSoftInput方式:

  inputMethodManager.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);

這個(gè)有個(gè)邏輯問(wèn)題,你如果是點(diǎn)擊輸入框彈出了鍵盤(pán), 登錄事件里面你想調(diào)用隱藏,這個(gè)邏輯沒(méi)問(wèn)題。 但是如果你打開(kāi)鍵盤(pán)后,點(diǎn)擊鍵盤(pán)上的收回鍵。 然后當(dāng)你點(diǎn)擊登錄時(shí),會(huì)彈出來(lái)。這個(gè)不是我們要的效果? 此時(shí)你可能就需要判斷鍵盤(pán)狀態(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ì)給你帶來(lái)困擾,如果要強(qiáng)制隱藏,建議用別的方式;不要靠什么Boolean狀態(tài)來(lá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ì)給你帶來(lái)困擾,如果要強(qiáng)制隱藏,建議用別的方式;不要靠什么Boolean狀態(tài)來(lái)做..
        imm.hideSoftInputFromWindow(dlg.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }
image

效果沒(méi)問(wèn)題。隱藏了就隱藏了呀。。。。也不用像toggle那樣需要判斷狀態(tài),以免混亂...

那Activity呢?我們也試試...

image

Actv也沒(méi)問(wèn)題呀。。。我們封裝下吧:

  /*
     *@Description: 隱藏鍵盤(pán)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);
            }
        }
    }

貌似基本上我們的顯示隱藏基本就夠用了。 目前來(lái)看個(gè)人的幾個(gè)項(xiàng)目都基本夠用了額....

3.我們還是來(lái)看看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.

解釋: 意思就是說(shuō)這是一種不帶結(jié)果返回的隱藏軟鍵盤(pán)的方式,其中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è)置 - 咦? 也就是說(shuō)我們之前的第二個(gè)參數(shù)有問(wèn)題,雖然效果不影響,但是還是遵循官方建議給個(gè)0算了?。。?這個(gè)token是當(dāng)前顯示鍵盤(pán)的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都可以隱藏 --- 具體什么原理的。沒(méi)研究過(guò)。。。。飄過(guò)~~~

而第二個(gè)參數(shù)給0, 如果給 HIDE_IMPLICIT_ONLY,用這種方式隱藏的話,那么顯示時(shí)也就需要這種方式才能顯示。 有點(diǎn)像force的情況。 他們之間應(yīng)該是有相對(duì)關(guān)系的。。。。

這是目前從官方文檔和實(shí)踐來(lái)看,個(gè)人的一些總結(jié)吧。 我覺(jué)得后續(xù)有空還是應(yīng)該深入分析和實(shí)踐下這些個(gè)參數(shù)。。。其實(shí)個(gè)人不太明白google設(shè)計(jì)了這些個(gè)復(fù)雜的并且對(duì)外提供的方式? 為什么不提供簡(jiǎn)單的隱藏顯示。。?;蛘呖催^(guò)原理的人會(huì)比較明白...

對(duì)了后來(lái)看了一篇文章分析,將的還比較細(xì)。 比較值得參考....當(dāng)然筆者建議從官方文檔入手,印象更深....后面我們?cè)倮^續(xù)搞吧...要學(xué)習(xí)的東西還再很多....

https://www.cnblogs.com/ldq2016/p/6861128.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容