web-dev-qa-db-fra.com

RecycleView vole le focus à l'intérieur d'un NestedScrollView

Lorsque je mets un RecyclerView dans une vue de défilement imbriquée, l'écran passe toujours en haut du RecyclerView au lieu du haut de la page. Voici un exemple simple.

layout 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>

Activité avec adaptateur factice:

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);
}

}

Dans cet exemple, j'ai une vue vide de 350dp de haut sur le recycleview, car vous devez disposer de contenu sur le RecycleView pour que celui-ci apparaisse de manière évidente. RecycleView lui-même contient 100 vues de texte factices.

Une fois l'activité commencée, le défilement se trouve en haut de RecycleView au lieu du haut de la page. Ce doit être quelque chose à l'intérieur de LinearLayoutManager, mais je n'ai pas encore vraiment regardé.

Des idées pour résoudre ça? 

39
breakline

Faites votre vue de dessus focusable. "RecyclableView a" focusableInTouchMode "défini sur true pour gérer les changements de focus de ses enfants pendant la mise en page." Pertinent discussion de la question

Exemple:

<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>
113
Amagi82

Pour moi, la réponse acceptée ne fonctionnait pas. Je résous ce problème en ajoutant cet attribut pour parent:

Android:descendantFocusability="blocksDescendants"

21
dr-to-str

Merci @ Amagi82. Vous avez répondu m'a aidé mais ce n'était pas suffisant. J'ai ajouté plus 2 attributs. Cela a fonctionné pour moi:

<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
André Luiz Reis

Faites-le de cette façon:

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