web-dev-qa-db-ja.com

NestedScrollView内にあるとき、RecycleViewはフォーカスを盗みます

ネストされたスクロールビュー内にRecyclerViewを配置すると、画面は常にページの上部ではなく、RecyclerViewの上部にジャンプします。以下に簡単な例を示します。

レイアウトxml:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.Android.com/tools"
    xmlns:Android="http://schemas.Android.com/apk/res/Android">
<Android.support.v4.widget.NestedScrollView
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">
    <LinearLayout
        Android:orientation="vertical"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content">
        <RelativeLayout
            Android:layout_width="match_parent"
            Android:layout_height="350dp"
            Android:background="@Android:color/holo_blue_dark"/>
        <Android.support.v7.widget.RecyclerView
            Android:id="@+id/recycleView"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content" />
    </LinearLayout>
</Android.support.v4.widget.NestedScrollView>
</layout>

ダミーアダプタを使用したアクティビティ:

public class RecycleViewTestActivity extends AppCompatActivity {

public static class ExampleAdapter extends RecyclerView.Adapter<ExampleViewHolder> {

    private Context context;

    public ExampleAdapter(Context context) {
        this.context = context;
    }

    @Override
    public ExampleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        TextView view = new TextView(context);
        view.setText("Test");
        return new ExampleViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ExampleViewHolder holder, int position) {

    }

    @Override
    public int getItemCount() {
        return 100;
    }
}

public static class ExampleViewHolder extends RecyclerView.ViewHolder {

    public ExampleViewHolder(View itemView) {
        super(itemView);
    }
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_rectest);
    RecyclerView view = (RecyclerView) findViewById(R.id.recycleView);
    view.setNestedScrollingEnabled(false);
    view.setLayoutManager(new LinearLayoutManager(this));
    ExampleAdapter adapter = new ExampleAdapter(this);
    view.setAdapter(adapter);
}

}

この例では、recycleviewに350dpの空のビューがあります。これを表示するには、RecycleViewにコンテンツが必要であるためです。 RecycleView自体には、100のダミーテキストビューが含まれています。

アクティビティを開始すると、スクロールはページの上部ではなくRecycleViewの上部にあります。 LinearLayoutManager内にある必要がありますが、実際にはまだ見えていません。

これを解決する方法はありますか?

42
breakline

トップビューをフォーカス可能にします。 「RecyclerViewのtrueに設定された「focusableOnTouchMode」は、レイアウト中の子のフォーカス変更を処理します。」関連 問題の議論

例:

<Android.support.v4.widget.NestedScrollView
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"">

    <LinearLayout
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:focusableInTouchMode="true"
        Android:orientation="vertical">

        <View
            Android:id="@+id/someView"
            Android:layout_width="wrap_content"
            Android:layout_height="350dp"/>

        <Android.support.v7.widget.RecyclerView
            Android:id="@+id/recyclerView"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"/>

    </LinearLayout>
</Android.support.v4.widget.NestedScrollView>
132
Amagi82

私にとって受け入れられた答えはうまくいきませんでした。これを解決するには、親にこの属性を追加します。

Android:descendantFocusability="blocksDescendants"

26
dr-to-str

ありがとう@ Amagi82。あなたの答えは私を助けたが、それは十分ではなかった。さらに2つの属性を追加しました。それは私のために働いた:

<Android.support.v4.widget.NestedScrollView
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"">

<LinearLayout
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:focusableInTouchMode="true"
    Android:focusable="true"
    Android:descendantFocusability="blocksDescendants"
    Android:orientation="vertical">

    <View
        Android:id="@+id/someView"
        Android:layout_width="wrap_content"
        Android:layout_height="350dp"/>

    <Android.support.v7.widget.RecyclerView
        Android:id="@+id/recyclerView"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"/>

</LinearLayout>
4

次のようにします:

LinearLayoutManager lm = new LinearLayoutManager(this);
lm.setAutoMeasureEnabled(true);
view.setLayoutManager(lm)
0
Chris Sherlock