web-dev-qa-db-ja.com

ScrollViewはフォーカス移動を無効にします

簡単な入力フォームがあります。これは、ScrollView内にEditTextsがある垂直のLinearLayoutです。

<ScrollView Android:layout_width="fill_parent"
    Android:layout_height="wrap_content">
    <LinearLayout Android:layout_width="fill_parent"
            Android:layout_height="fill_parent"
            Android:orientation="vertical">
            <LinearLayout Android:layout_width="fill_parent"
                  Android:layout_height="wrap_content"
                  Android:padding="10dip"
                  Android:gravity="center_vertical"
                  Android:orientation="horizontal">
                  <TextView style="@style/Text"
                         Android:text="Name"/>
                  <EditText style="@style/EditBox"/>
            </LinearLayout>
            <View style="@style/Divider"/>
            <LinearLayout Android:layout_width="fill_parent"
                  Android:layout_height="wrap_content"
                  Android:padding="10dip"
                  Android:gravity="center_vertical"
                  Android:orientation="horizontal">
                  <TextView style="@style/Text"
                         Android:text="Password"/>
                  <EditText style="@style/EditBox"/>
            </LinearLayout>               
            ... 
     </LinearLayout>
</ScrollView>

ユーザーがフォームをスクロールすると、自動的にフォーカスが表示されているEditTextに移動します。そのような動作を無効にして、常に現在タッチで選択されているEditTextにフォーカスを維持することは可能ですか?

これは機能である可能性があることを理解していますが、無効にする必要があります。

ありがとう!

23
AlexKorovyansky

これに対する私の解決策を共有したいと思っただけです。他の回答のコメントの一部には、この動作をオーバーライドできないと記載されていますが、これは正しくありません。この動作は、onRequestFocusInDescendants()メソッドをオーバーライドするとすぐに停止します。したがって、これを行うには、ScrollView拡張機能を作成するだけです。

public class NonFocusingScrollView extends ScrollView {

  public NonFocusingScrollView(Context context) {
    super(context);
  }

  public NonFocusingScrollView(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  public NonFocusingScrollView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
  }

  @Override
  protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
    return true;
  }

}

これで完了です。 ScrollViewは、あなたのフォーカスを混乱させることはもうありません。

47
dmon

私もそのような問題を抱えていました。私を助けた唯一の方法は、スクロールビューを拡張して、隣人をオーバーライドすることです

_@Override
public ArrayList<View> getFocusables(int direction) {
    return new ArrayList<View>();
}
_

または

_@Override
protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
    return true;
}
_

ただし、次のようにViewGroup.requestChildFocus(View child, View focused)メソッドをオーバーライドします。

_    @Override
    public void requestChildFocus(View child, View focused) {
        // avoid scrolling to focused view
        // super.requestChildFocus(child, focused);
    }
_
15
rus1f1kat0R

私にとってうまくいったのは、@ dmonの回答と@wajの回答を組み合わせることでした。

ScrollView内でEditTextsのみを処理している場合は、onRequestFocusInDescendants()のオーバーライドのみが適切に機能しましたが、複数のビュータイプを追加し始めたときは、うまく機能しませんでした。

getFocusables()のオーバーライドのみではまったく機能しませんでした。

onRequestFocusInDescendants() AND getFocusables()の両方をオーバーライドすると、すべてのシナリオで美しく機能するようです。

public class FixedFocusScrollView extends ScrollView {

  public FixedFocusScrollView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
  }

  public FixedFocusScrollView(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  public FixedFocusScrollView(Context context) {
    super(context);
  }

  @Override
  public ArrayList<View> getFocusables(int direction) {
      return new ArrayList<View>();
  }

  @Override
  protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
    return true;
  }

}
9
Hunter S

私はここに投稿されたすべての解決策を試しましたが、特定のAndroid=バージョンで機能しないか、タッチモードと非タッチモードを切り替えるとき(ボタンをクリックするか、トラックパッド)。

私はついにメソッドgetFocusablesをオーバーライドすることがトリックをすることを発見しました:

public class FixedFocusScrollView extends ScrollView {

  public FixedFocusScrollView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
  }

  public FixedFocusScrollView(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  public FixedFocusScrollView(Context context) {
    super(context);
  }

  @Override
  public ArrayList<View> getFocusables(int direction) {
    return new ArrayList<View>();
  }

}
7
waj

ソースから問題を切り取ってみてください(edit:つまり、XMLファイルに移動します)。

まず、そのためにはフォーカス可能な要素が必要です。そのスクロールに含まれるすべてのフォーカス可能な要素を非フォーカス可能な要素にします。ビューがインフレートされて表示された後、フォーカス可能にします。

Android:focusable="false"
Android:focusableInTouchMode="false"
3
valera

私の問題に役立つ別の簡単な解決策を見つけました。

私はScrollViewを取得しました。上部にEditTextがあり、その後にTextViews、RatingBars、Buttonsの大きなリストがあります。ボタンはAlertDialogを起動し、ポップアップすると、ScrollViewが一番上に移動し、フォーカスがあるEditTextに移動します。

それを解決するために、ActivityのonClickメソッドでrequestFocusFromTouch()をクリックしたビュー(この場合はボタン)に設定します。

public void onClick(View v) {
    v.requestFocusFromTouch();
    ...
}

Buttonをクリックすると、ScrollViewが移動し、そのButtonが画面の中央に配置されます。

お役に立てば幸いです。

1
Hugo Matilla

今日私に起こったのは、基本的に私はいくつかの既存のビューの間にプログラムでビューを追加し、Scrollが自動的に移動してそのビューに焦点を合わせていたことです。私がやったことは、次のとおりです。

container.setFocusable( false );
0
Reinherd

このような動作には、nextFocusUpおよびnextFocusDownを使用します。

<EditText
    Android:id="@+id/my_edit_text"
    Android:nextFocusDown="@id/my_edit_text"
    Android:nextFocusUp="@id/my_edit_text"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content">
</EditText>
0
pawelzieba