121

私はこれまで約6時間費やしてきましたが、障害になっているだけです。一般的な前提は、ウィジェットとListViewを含む行が(アダプターによって生成されたか、ヘッダー・ビューとして追加されたかにかかわらず)あることです。私がやりたいのは、ジョグボール/矢印を使用して、セレクターを通常のように個々のアイテムにナビゲートできるようにすることですが、特定の行に到達すると、行を明示的に識別しなければならない場合でも、フォーカス可能な子供、セレクターで位置を示すのではなく、その子供に焦点を合わせてもらいたい。EditTextButton

私は多くの可能性を試しましたが、これまでのところ運がありませんでした。

レイアウト:

<ListView
    android:id="@android:id/list" 
    android:layout_height="fill_parent" 
    android:layout_width="fill_parent"
    />

ヘッダービュー:

EditText view = new EditText(this);
listView.addHeaderView(view, null, true);

アダプタに他の項目があると仮定すると、矢印キーを使用すると、期待どおりにリスト内で選択範囲が上下に移動します。ただし、ヘッダー行に到達すると、セレクターにも表示されEditText、ジョグボールの使用に集中する方法はありません。注:をタップするEditText 、その時点でフォーカスが移動しますが、タッチスクリーンに依存しているため、必須ではありません。

ListViewこの点に関して、明らかに2つのモードがあります
。1 setItemsCanFocus(true)。:セレクターは表示されませんがEditText、矢印を使用するとフォーカスを取得できます。フォーカス検索アルゴリズムは予測が難しく、どの項目が選択されているかについて視覚的なフィードバック(どの行でも:フォーカス可能な子があるかどうか)がないため、どちらもユーザーに予期しないエクスペリエンスを与える可能性があります。
2 setItemsCanFocus(false).:セレクターは常に非タッチモードで描画され、EditTextタップしてもフォーカスを取得できません。

さらに悪いことに、呼び出しeditTextView.requestFocus()はtrueを返しますが、実際にはEditTextにフォーカスを与えません。

私が想定しているのは、基本的に1と2のハイブリッドです。ここでは、すべてのアイテムがフォーカス可能かどうかのリスト設定ではなく、リスト内の1つのアイテムのフォーカス可能性を設定して、セレクターが選択からシームレスに移行するようにします。フォーカスできないアイテムの場合は行全体、フォーカス可能な子を含むアイテムの場合はフォーカスツリーをトラバースします。

テイカーはいますか?

4

13 に答える 13

102

これは私を助けました。
マニフェスト:

<activity android:name= ".yourActivity" android:windowSoftInputMode="adjustPan"/>
于 2011-02-04T18:39:25.447 に答える
101

申し訳ありませんが、私自身の質問に答えました。これは、最も正確または最も洗練されたソリューションではないかもしれませんが、私にとっては機能し、かなり堅実なユーザーエクスペリエンスを提供します。ListViewのコードを調べて、2つの動作が非常に異なる理由を確認し、ListView.javaからこれに遭遇しました。

    public void setItemsCanFocus(boolean itemsCanFocus) {
        mItemsCanFocus = itemsCanFocus;
        if (!itemsCanFocus) {
            setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
        }
    }

したがって、を呼び出すときはsetItemsCanFocus(false)、子がフォーカスを取得できないように子孫のフォーカス可能性も設定します。mItemsCanFocusこれは、ListViewのOnItemSelectedListenerを切り替えることができなかった理由を説明しています。これは、ListViewがすべての子へのフォーカスをブロックしていたためです。

私が今持っているもの:

<ListView
    android:id="@android:id/list" 
    android:layout_height="match_parent" 
    android:layout_width="match_parent"
    android:descendantFocusability="beforeDescendants"
    />

beforeDescendantsListView自体(子ではない)にフォーカスがある場合にのみセレクターが描画されるため、これを使用します。デフォルトの動作では、ListViewが最初にフォーカスを取得し、セレクターを描画する必要があります。

次に、OnItemSelectedListenerで、セレクターをオーバーライドするヘッダービューがわかっているので(特定の位置にフォーカス可能なビューが含まれているかどうかを動的に判断するには、より多くの作業が必要になります)、子孫のフォーカス可能性を変更し、EditTextにフォーカスを設定できます。そして、そのヘッダーから移動したら、もう一度元に戻します。

public void onItemSelected(AdapterView<?> listView, View view, int position, long id)
{
    if (position == 1)
    {
        // listView.setItemsCanFocus(true);

        // Use afterDescendants, because I don't want the ListView to steal focus
        listView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
        myEditText.requestFocus();
    }
    else
    {
        if (!listView.isFocused())
        {
            // listView.setItemsCanFocus(false);

            // Use beforeDescendants so that the EditText doesn't re-take focus
            listView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
            listView.requestFocus();
        }
    }
}

public void onNothingSelected(AdapterView<?> listView)
{
    // This happens when you start scrolling, so we need to prevent it from staying
    // in the afterDescendants mode if the EditText was focused 
    listView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
}

コメントアウトされたsetItemsCanFocus呼び出しに注意してください。これらの呼び出しで、正しい動作が得られましたがsetItemsCanFocus(false)、フォーカスがEditTextからListViewの外部の別のウィジェットにジャンプし、ListViewに戻って、次に選択されたアイテムにセレクターが表示され、そのジャンプフォーカスは気が散りました。ItemsCanFocusの変更を削除し、子孫のフォーカス可能性を切り替えるだけで、目的の動作が得られました。すべてのアイテムは通常どおりセレクターを描画しますが、EditTextを使用して行に到達すると、代わりにテキストフィールドにフォーカスされます。次に、そのEditTextを続行すると、セレクターの描画が再開されました。

于 2010-04-21T03:17:35.663 に答える
18

私の仕事はListView、クリックすると展開するものを実装することでした。追加のスペースはEditText、テキストを入力できる場所を示しています。アプリは2.2以降で機能する必要があります(これを書いている時点では4.2.2まで)

私はこの投稿や見つけた他の投稿から多くの解決策を試しました。2.2から4.2.2までのデバイスでそれらをテストしました。2.2以降のすべてのデバイスで満足のいくソリューションはありませんでした。各ソリューションにはさまざまな問題がありました。

私は私の最終的な解決策を共有したかった:

  1. リストビューをに設定android:descendantFocusability="afterDescendants"
  2. リストビューをに設定setItemsCanFocus(true);
  3. android:windowSoftInputMode="adjustResize" 多くの人が提案するようにあなたの活動を設定しますadjustPanadjustResize、はるかに優れたux imhoを提供します、あなたのケースでこれをテストしてください。たとえば、adjustPan一番下のリストアイテムが隠されます。ドキュメントは次のように示唆しています(「これは一般的にサイズ変更よりも望ましくありません」)。また、4.0.4では、ユーザーがソフトキーボードで入力を開始した後、画面が上にパンします。
  4. 4.2.2ではadjustResize、EditTextフォーカスにいくつかの問題があります。解決策は、このスレッドからrjrjrソリューションを適用することです。怖そうに見えますが、そうではありません。そしてそれは動作します。やってみなよ。

追加EditText5.HoneyCombより前のバージョンにフォーカスが移っ たときにアダプターが更新されたため(ビューのサイズ変更のため)、ビューが反転する問題が見つかりました。4.0.3で動作します

一部のアニメーションを実行している場合は、adjustPanハニカム以前のバージョンの動作を変更して、サイズ変更が実行されず、アダプターがビューを更新しないようにすることができます。このようなものを追加する必要があります

if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB)
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);

これにより、2.2〜4.2.2デバイスで許容可能なUXが得られます。この結論に達するまでに少なくとも数時間かかったので、人々が時間を節約できることを願っています。

于 2013-04-04T18:42:16.583 に答える
10

これは私の命を救った--->

  1. この行を設定します

    ListView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);

  2. 次に、アクティビティタグのマニフェストに次のように入力します->

    <activity android:windowSoftInputMode="adjustPan">

あなたのいつもの意図

于 2015-10-18T16:45:22.760 に答える
7

ビューのリサイクルを行わない短いリストでこれを試しています。ここまでは順調ですね。

XML:

<RitalinLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
  <ListView
      android:id="@+id/cart_list"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:scrollbarStyle="outsideOverlay"
      />
</RitalinLayout>

Java:

/**
 * It helps you keep focused.
 *
 * For use as a parent of {@link android.widget.ListView}s that need to use EditText
 * children for inline editing.
 */
public class RitalinLayout extends FrameLayout {
  View sticky;

  public RitalinLayout(Context context, AttributeSet attrs) {
    super(context, attrs);

    ViewTreeObserver vto = getViewTreeObserver();

    vto.addOnGlobalFocusChangeListener(new ViewTreeObserver.OnGlobalFocusChangeListener() {
      @Override public void onGlobalFocusChanged(View oldFocus, View newFocus) {
        if (newFocus == null) return;

        View baby = getChildAt(0);

        if (newFocus != baby) {
          ViewParent parent = newFocus.getParent();
          while (parent != null && parent != parent.getParent()) {
            if (parent == baby) {
              sticky = newFocus;
              break;
            }
            parent = parent.getParent();
          }
        }
      }
    });

    vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
      @Override public void onGlobalLayout() {
        if (sticky != null) {
          sticky.requestFocus();
        }
      }
    });
  }
}
于 2013-03-25T17:29:13.977 に答える
4

この投稿は私のキーワードと完全に一致していました。検索EditTextと検索ボタンを含むListViewヘッダーがあります。

最初のフォーカスを失った後にEditTextにフォーカスを与えるために、私が見つけた唯一のハックは次のとおりです。

    searchText.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View arg0) {
            // LOTS OF HACKS TO MAKE THIS WORK.. UFF...
            searchButton.requestFocusFromTouch();
            searchText.requestFocus();
        }
    });

多くの時間を失いました、そしてそれは本当の修正ではありません。それが誰かがタフになるのを助けることを願っています。

于 2010-10-21T09:13:09.583 に答える
2

リストが動的で、フォーカス可能なウィジェットが含まれている場合、適切なオプションは、ListViewIMOの代わりにRecyclerViewを使用することです。

フォーカスされた位置を設定、、adjustPanまたはFOCUS_AFTER_DESCENDANTS手動で記憶する回避策は、実際には単なる回避策です。コーナーケースがあります(スクロール+ソフトキーボードの問題、EditTextでの位置の変更に注意してください)。ListViewがの間にビューをまとめて作成/破棄するという事実は変わりませんnotifyDataSetChanged

RecyclerViewを使用すると、個々の挿入、更新、および削除について通知します。フォーカスされたビューは再作成されていないため、フォームコントロールがフォーカスを失う問題はありません。追加のボーナスとして、RecyclerViewはリストアイテムの挿入と削除をアニメーション化します。

開始方法に関する公式ドキュメントの例を次に示しRecyclerViewます。開発者ガイド-RecyclerViewを使用してリストを作成する

于 2016-02-03T14:09:33.680 に答える
1

マニフェストアクティビティまたはxmlで使用するandroid:windowSoftInputMode="stateAlwaysHidden"と、キーボードフォーカスが失われることがあります。したがって、最初にxmlとマニフェストでそのプロパティを確認し、存在する場合は削除します。これらのオプションをサイドアクティビティのマニフェストファイルにandroid:windowSoftInputMode="adjustPan"追加し、このプロパティをxmlのlistviewに追加した後android:descendantFocusability="beforeDescendants"

于 2015-11-25T05:57:40.813 に答える
0

もう1つの簡単な解決策は、ListAdapterのgetView(..)メソッドでonClickListenerを定義することです。

public View getView(final int position, View convertView, ViewGroup parent){
    //initialise your view
    ...
    View row = context.getLayoutInflater().inflate(R.layout.list_item, null);
    ...

    //define your listener on inner items

    //define your global listener
    row.setOnClickListener(new OnClickListener(){
        public void onClick(View v) {
            doSomethingWithViewAndPosition(v,position);
        }
    });

    return row;

そうすれば、行をクリック可能になり、内部ビューもクリック可能になります:)

于 2011-10-04T09:15:29.030 に答える
0

最も重要な部分は、リストセルでフォーカスを機能させることです。特にGoogleTVのリストの場合、これは不可欠です。

リストビューのsetItemsCanFocusメソッドは、次のトリックを実行します。

...
mPuzzleList = (ListView) mGameprogressView.findViewById(R.id.gameprogress_puzzlelist);
mPuzzleList.setItemsCanFocus(true);
mPuzzleList.setAdapter(new PuzzleListAdapter(ctx,PuzzleGenerator.getPuzzles(ctx, getResources(), version_lite)));
...

私のリストセルxmlは次のように始まります:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             android:id="@+id/puzzleDetailFrame"
             android:focusable="true"
             android:nextFocusLeft="@+id/gameprogress_lessDetails"
             android:nextFocusRight="@+id/gameprogress_reset"
...

nextFocusLeft / Rightは、十字キーのナビゲーションでも重要です。

詳細については、他のすばらしい回答を確認してください。

于 2012-12-04T20:11:06.663 に答える
0

私はちょうど別の解決策を見つけました。私はそれが解決策というよりはハックだと信じていますが、それはアンドロイド2.3.7とアンドロイド4.3で動作します(私はその古き良き十字キーをテストしました)

通常どおりWebビューを初期化し、これを追加します:( Michael Biermanに感謝)

listView.setItemsCanFocus(true);

getView呼び出し中:

editText.setOnFocusChangeListener(
    new OnFocusChangeListener(View view,boolean hasFocus){
        view.post(new Runnable() {
            @Override
            public void run() {
                view.requestFocus();
                view.requestFocusFromTouch();
            }
     });
于 2013-11-22T17:08:58.017 に答える
0

これを試してみてください

android:windowSoftInputMode="adjustNothing"

の中に

アクティビティ

マニフェストのセクション。はい、何も調整しません。つまり、editTextはIMEを開いているときの位置に留まります。しかし、それでも焦点を失うという問題を完全に解決するのは少し不便です。

于 2016-02-20T14:46:22.440 に答える
0

私の場合、リストビューには14の入力編集テキストがあります。私が直面していた問題は、キーボードを開いたときにテキストフォーカスが失われたことを編集し、レイアウトをスクロールし、フォーカスされたビューがユーザーのキーボードから見えなくなるとすぐに下に移動しました。ユーザーエクスペリエンスには良くありませんでした。windowSoftInputMethod="adjustPan"を使用できません。そのため、多くの検索を行った後、LinearLayoutとscrollViewを使用して、カスタムレイアウトを拡張し、データをアダプターとしてビューに設定するリンクを見つけました。私の場合はうまく機能します。

于 2020-10-12T10:46:25.173 に答える