簡體   English   中英

當軟鍵盤出現時,它使我的 EditText 字段失去焦點

[英]When the soft keyboard appears, it makes my EditText field lose focus

我在 ListView 中有一些 EditText 字段。 當我點擊 EditText 字段之一時,鍵盤會滑入視圖(應該如此),但我點擊的 EditText 字段失去焦點。 我嘗試使用各種 InputMethodManager 方法使鍵盤在視圖中啟動(為了解決問題而不是真正解決它),但這不起作用 - 當 Activity 出現時鍵盤不在視圖中。

EditText 的類型是number ,當鍵盤滑入時,它是一個數字鍵盤,但是當它完成滑動並且 EditText 失去焦點時,它變為字母鍵盤(這加強了 EditText 不再有焦點的想法) .

我的問題是這些:

1) 如何使我的 EditText 字段的選擇和軟鍵盤的后續滑入不會使我的 EditText 失去焦點?

……失敗了……

2) 我怎樣才能讓鍵盤從視野中開始,這樣它就不必滑入(從而避免我覺得如此令人反感的行為)?

我的清單確實包括android:windowSoftInputMode="stateAlwaysVisible" ,但在我點擊 EditText 之前鍵盤不會出現。 這種對 'stateAlwaysVisible' 屬性的忽略似乎只發生在模擬器中 - 在我配置的設備上,它很榮幸,所以上面的問題 2 確實適用於設備......但不適用於模擬器。

感謝您的任何幫助,您可以提供!

您需要在 AndroidManifest.xml 中進行更改

在持有列表視圖的活動中添加 android:windowSoftInputMode="adjustPan"。 這將解決您的問題。

    <activity android:name=".MyEditTextInListView"
              android:label="@string/app_name"
              android:windowSoftInputMode="adjustPan">

問候

這是我如何做到的。 當您觸摸EditText以在其中鍵入文本時, onFocusChangeListener()會被多次調用。 順序是:

  1. 如果焦點在不同的視圖上,則該視圖失去焦點
  2. 目標獲得焦點
  3. 彈出軟鍵盤。
  4. 這會導致目標失去焦點
  5. 代碼檢測到這種情況並調用 target.requestFocus()
  6. 由於 Android 廢話,最左邊、最上面的視圖獲得焦點
  7. 由於 requestFocus 被調用,最左邊的視圖失去焦點
  8. 目標終於獲得焦點

    ////////////////////////////////////////////////////////////////// private final int minDelta = 300; // threshold in ms private long focusTime = 0; // time of last touch private View focusTarget = null; View.OnFocusChangeListener onFocusChangeListener = new View.OnFocusChangeListener() { @Override public void onFocusChange(View view, boolean hasFocus) { long t = System.currentTimeMillis(); long delta = t - focusTime; if (hasFocus) { // gained focus if (delta > minDelta) { focusTime = t; focusTarget = view; } } else { // lost focus if (delta <= minDelta && view == focusTarget) { focusTarget.post(new Runnable() { // reset focus to target public void run() { focusTarget.requestFocus(); } }); } } } };

上面的代碼適用於鍵盤彈出窗口。 但是,它不會檢測到語音到文本的彈出窗口。

在我的情況下,發生這種情況是因為當 ListView 調整大小時,它會重新創建所有列表項(即它為每個可見列表項再次調用 getView())。

因為 EditText 位於我從 getView() 返回的布局內,這意味着它是 EditText 的一個不同實例,而不是以前具有焦點的實例。 第二個后果是當軟鍵盤出現或消失時,我發現我丟失了 EditText 的內容。

因為我希望我的視圖保持完全可訪問(即我希望它被調整大小而不是隱藏在鍵盤窗口后面,某些部分不可訪問),我不能使用弗蘭克的答案,否則這似乎是最好的方法。

我通過在 EditText 上使用 OnFocusChangeListener 記錄焦點丟失時的時間戳來解決這個問題,然后在重新創建列表項時在 getView() 中,如果當前時間在焦點丟失時的某個閾值內,請調用 requestFocus( ) 將其返回給有問題的 EditText。

您還可以在那時從 EditText 的前一個實例中獲取文本並將其傳輸到新實例。

private class MyAdapter<Type> extends ArrayAdapter<String>
    implements OnFocusChangeListener
{
    private EditText mText;
    private long mTextLostFocusTimestamp;
    private LayoutInflater mLayoutInflater;

    public MyAdapter(Context context, int resource, int textResourceId, ArrayList<String> data, LayoutInflater li) {
        super(context, resource, textResourceId, data);
        mLayoutInflater = li;
        mTextLostFocusTimestamp = -1;
    }

    private void reclaimFocus(View v, long timestamp) {
        if (timestamp == -1)
            return;
        if ((System.currentTimeMillis() - timestamp) < 250)
            v.requestFocus();
    }

    @Override public View getView (int position, View convertView, ViewGroup parent)
    {
        View v = mLayoutInflater.inflate(R.layout.mylayout, parent, false);

        EditText newText = (EditText) v.findViewById(R.id.email);
        if (mText != null)
            newText.setText(mText.getText());
        mText = newText;
        mText.setOnFocusChangeListener(this);
        reclaimFocus(mText, mTextLostFocusTimestamp);

        return v;
    }

    @Override public void onFocusChange(View v, boolean hasFocus) {
        if ((v == mText) && !hasFocus)
            mTextLostFocusTimestamp = System.currentTimeMillis();
    }
}

在 AndroidManifest.xml 中,在包含視圖的活動中使用 adjustNothing

<activity
            android:name=".ActivityName"
            android:windowSoftInputMode="adjustNothing">

如果 listView 中的 editText 只是確保使用這種方式在 getView 方法中膨脹 View 。


        if (convertView == null)
        convertView = LayoutInflater.from(context).inflate(R.layout.yourItemListLayout,
                parent, false);   

編輯:這項工作適用於某些手機,並非所有我都使用上面 Mr.Frank 的答案。

您應該在硬件鍵盤始終可見的設備上測試此代碼。 這種行為也可能發生在這里。

為避免這種情況,您可以讓鍵盤始終可見。

https://groups.google.com/forum/#!topic/android-developers/FyENeEdmYC0

從理論上講,您可能需要創建自己的 Android 鍵盤(盡管使用 Android 鍵盤作為基礎),如下所述: Android:如何使鍵盤始終可見?

在包含列表視圖或 EditText 的活動中添加 android:windowSoftInputMode="adjustResize"。 這將解決您的問題。

<activity android:name=".MainActivity"
        android:windowSoftInputMode="adjustResize">
</activity>

對於那些帶着 Xamarin 或 Xamarin.Forms 來到這里的人:

我也遇到了同樣的問題,但僅限於 Android 5.x - 包括 8.1 在內的所有較新版本都運行良好。

顯然,謝爾頓說得對:

在我的情況下,發生這種情況是因為當 ListView 調整大小時,它會重新創建所有列表項(即它為每個可見列表項再次調用 getView())。

我的列表視圖也在調整大小,不,弗蘭克設置windowSoftInputMode="adjustPan"的解決方案對我來說不是選擇,因為這意味着鍵盤將列表視圖部分移出屏幕。

經過數小時的焦點調試后,我所要做的就是設置 Xamarin Forms ListView 的單元格緩存策略:

CachingStrategy="RecycleElement"

CachingStrategy="RetainElement"

這將阻止重新創建單元格。 但是,這可能會導致巨大的列表性能不佳和內存消耗高。 意識到。

就我而言,當鍵盤出現時,我在我的根 ScrollView 上調用了root_scrollview.fullScroll(View.FOCUS_DOWN) 我用

login_scrollview.post(new Runnable() { 
    @Override
    public void run() {
        root_scrollview.scrollTo(0,root_container.bottom)
    }
});

其中 root_container 是 root_scrollview 的直接子級。 這為我解決了這個問題。

注意:直接調用root_scrollview.scrollTo(0,root_container.bottom)不起作用。

這家伙有同樣的問題,而且還有更多。 他通過使用 ScrollView 和 LinearLayout 而不是 ListView 解決了這個問題。

轉換為 RecyclerView

我相信失去對鍵盤顯示隱藏的關注不是預期的行為,並且應該是(或應該是)報告的 Android 問題。

但是現在已經晚了,10年后OP遇到了!

在我的情況下,開關的缺點SOFT_INPUT_ADJUST_RESIZESOFT_INPUT_ADJUST_PAN勝過不失去焦點的優勢。

為什么? ADJUST_RESIZE官方首選的方法,因為ADJUST_PAN阻止部分視圖並可能阻止滾動。

但是由於早先對這個問題的回答,我對ListView強烈的懷疑。

為了證明我的懷疑,我花了一天時間將一個復雜的基於ListView的編輯器轉換為RecyclerView

我可以確認軟鍵盤狀態更改不再影響EditText焦點,即使我正在使用ADJUST_RESIZE

我知道看起來很痛苦 - 但也許最終結果比子分類或棘手的解決方法更好?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM