web-dev-qa-db-fra.com

Ajouter des éléments au bas de la vue Recycleur

Code de l'illustration:

mLinearLayoutManager = new LinearLayoutManager(this);
mLinearLayoutManager.setReverseLayout(true);
mLinearLayoutManager.setStackFromEnd(true);
mMessageRecyclerView.setLayoutManager(mLinearLayoutManager);

Voir l'illustration ici

Comment puis-je ajouter de nouveaux éléments (dans mon cas, des messages) en bas de la vue Recycler et garder la "gravité" de la vue en haut ?

Donc, ce qui fonctionne maintenant est le suivant:

  • La gravité de la vue est au sommet. C'est bon! ✓

Ce qui ne fonctionne pas:

  • De nouveaux messages sont ajoutés en haut de la vue. C'est mauvais × Je veux qu'ils soient ajoutés en bas de la vue (après le message précédent) comme ceci: Voir ici
24
user8618899

setStackFromEnd = true et setReverseLayout = true

setStackFromEnd définira la vue pour afficher le dernier élément, la direction de la mise en page restera la même tandis que setReverseLayout changera l'ordre des éléments ajoutés par l'adaptateur.
Essayez de supprimer ces deux lignes ou de les définir false

layoutManager.setReverseLayout(true);
layoutManager.setStackFromEnd(true);

Essayez d'utiliser ceci pour déplacer votre RecyclerView et EditText vers le haut lorsque le clavier apparaît

<activity name="YourActivity"
Android:windowSoftInputMode="stateHidden|adjustResize">
//stateHidden--->keyboard is hidden when you first open the activity and adjustResize---> this will adjust the layout resize option.
...
</activity>  

dans AndroidManifest.xml.

Pour accrocher le RecyclerView en haut

    <Android.support.v7.widget.RecyclerView
    Android:id="@+id/messageRecyclerViewRep"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:layout_alignParentLeft="true"
    Android:layout_alignParentStart="true"
    Android:layout_below="@+id/linearLayout3"
    Android:layout_marginLeft="36dp"
    Android:scrollbars="vertical" />

Pour mettre le recyclerView en bas en premier et poussez-le lorsque le clavier apparaît.

 <LinearLayout
    Android:id="@+id/recyclerContainer"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:layout_below="@+id/linearLayout3"
    Android:layout_above="@+id/linearLayout"
    Android:gravity="bottom">
    <Android.support.v7.widget.RecyclerView
        Android:id="@+id/messageRecyclerViewRep"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:layout_marginLeft="36dp"
        Android:scrollbars="vertical" />
</LinearLayout>

Pour faire défiler le recyclerView vers le bas lorsque le clavier apparaît, c'est-à-dire lorsque la disposition de la vue du recycleur est modifiée (vous pouvez faire la même chose sur Modifier le texte actif ou concentré ou cliqué ou quelque chose comme ça. Je l'ai fait sur le changement de disposition de la vue du recycleur.)

   recyclerView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
            @Override
            public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
                if (bottom < oldBottom) {
                    recyclerView.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            recyclerView.smoothScrollToPosition(mAdapter.getItemCount());
                        }
                    }, 100);
                }
            }
        });
14
Niraj Niroula

setReverseLayout (true) cela inversera l'ordre de parcours et de mise en page de l'élément. Le premier élément finira par ne pas afficher ni contenu.

setStackFromEnd (true) cela remplira le contenu de la liste des recycleurs à partir du bas de la vue.

Besoin de setStackFromEnd(true) pas setReverseLayout(true)

Et dans XML Recyclerview, la hauteur doit être match_parent

Ci-dessous, j'ai donné le code de travail.

activité xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:orientation="vertical">

    <Button
        Android:id="@+id/btnAdd"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:text="Add" />

    <Android.support.v7.widget.RecyclerView
        Android:id="@+id/rcList"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:clipToPadding="true" />


</LinearLayout>

Élément de liste disposition xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:layout_marginLeft="20dp"
    Android:layout_marginRight="20dp"
    Android:gravity="center_vertical">

    <TextView
        Android:id="@+id/textView"
        Android:layout_width="wrap_content" Android:textSize="23sp"
        Android:layout_height="wrap_content" Android:textColor="#4a4883"
        Android:text="Test Text" />
</FrameLayout>

Classe d'adaptateur

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> {
    private static final String TAG = "CustomAdapter";

    private ArrayList<String> mDataSet;
    private int size = 0;


    public static class ViewHolder extends RecyclerView.ViewHolder {
        private final TextView textView;

        public ViewHolder(View v) {
            super(v);
            v.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Log.d(TAG, "Element " + getAdapterPosition() + " clicked.");
                }
            });
            textView = (TextView) v.findViewById(R.id.textView);
        }

        public TextView getTextView() {
            return textView;
        }
    }


    public CustomAdapter(ArrayList<String> dataSet) {
        mDataSet = dataSet;
        if (mDataSet != null && !mDataSet.isEmpty()) {
            size = mDataSet.size();
        }
    }

    public void refreshData(String add) {
        if (!TextUtils.isEmpty(add)) {
            mDataSet.add(add);
            size = mDataSet.size();
            notifyDataSetChanged();

        }

    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        // Create a new view.
        View v = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.list_item, viewGroup, false);

        return new ViewHolder(v);
    }

    @Override
    public void onBindViewHolder(ViewHolder viewHolder, final int position) {
        Log.d(TAG, "Element " + position + " set.");

        viewHolder.getTextView().setText(mDataSet.get(position));
    }

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

Classe d'activité

public class MainActivity extends AppCompatActivity {
    private RecyclerView mRecyclerView;
    protected CustomAdapter mAdapter;
    protected LinearLayoutManager mLayoutManager;
    protected ArrayList<String> listString = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mRecyclerView = (RecyclerView) findViewById(R.id.rcList);
        mLayoutManager = new LinearLayoutManager(this);
        mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        /**
         *setStackFromEnd true will fill the content(list item) from the bottom of the view
         */
        mLayoutManager.setStackFromEnd(true);
        mLayoutManager.setReverseLayout(true);
        mRecyclerView.setLayoutManager(mLayoutManager);
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());
        findViewById(R.id.btnAdd).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int temp = mAdapter.getItemCount() + 1;
                mAdapter.refreshData("Test text " + temp);
                mRecyclerView.smoothScrollToPosition(mAdapter.getItemCount());
            }
        });
        mAdapter = new CustomAdapter(listString);
        mRecyclerView.setAdapter(mAdapter);

    }
}

enter image description here

4
user1140237

Le moyen le plus simple d'y parvenir serait de charger les éléments dans Recyclerview dans l'ordre inverse de la façon dont ils sont entrés dans la base de données Firebase.

@Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
    Log.d(TAG, "Element " + position + " set.");
    viewHolder.getTextView().setText(mDataSet.get(getItemCount() - 1 -position));
}

Ce que cela ferait, c'est que l'élément inséré en dernier sera affiché en bas puisque vous chargez les éléments par le haut. Pas besoin de modifier les XML ou tout autre code.

J'ai eu les mêmes problèmes avec Recylerview ne se redimensionnant pas lorsque le clavier apparaît et j'ai donc recouru à cette méthode.

Bonne chance!!

2
Abhishek

J'ai implémenté et voici mon implémentation en utilisant FirebaseRecyclerView, vous devez définir cela setStackFromEnd=true et setReverseLayout=true

mon xml

Support de vue recycleur

public class TestingFirebaseHolder extends RecyclerView.ViewHolder {

    private TextView mTextView;
    private TextView mTextView2;

    public TestingFirebaseHolder(View itemView) {
        super(itemView);
        mTextView = itemView.findViewById(R.id.textViewTesting);
        mTextView2 = itemView.findViewById(R.id.textViewTesting2);
    }

    public void setTextView(String text,String text2)
    {
        mTextView.setText(text);
        mTextView2.setText(text2);
    }
}

Classe de test

public class TestingUser {

    public String UserName;
    public String mUid;

    public TestingUser() {
    }

    public TestingUser(String userName, String uid) {
        UserName = userName;
        mUid = uid;
    }
}

Code d'activité

private EditText mEditText;
private RecyclerView mRecyclerView;
private FirebaseRecyclerAdapter<TestingUser,TestingFirebaseHolder> mAdapter;
private FirebaseUser mUser;
private DatabaseReference mReference;

    mEditText = findViewById(R.id.testingEditText);
    mRecyclerView = findViewById(R.id.hello_rec);
    mUser = FirebaseAuth.getInstance().getCurrentUser();
    mReference = FirebaseDatabase.getInstance().getReference();
    LinearLayoutManager ll = new LinearLayoutManager(this);
    ll.setReverseLayout(true); // set this
    ll.setStackFromEnd(true); // set this
    mRecyclerView.setLayoutManager(ll);

    Query query = mReference.child("Testing").child(mUser.getUid()).orderByValue();



    mAdapter = new FirebaseRecyclerAdapter<TestingUser, TestingFirebaseHolder>(
            TestingUser.class,R.layout.testing_recycler_layout,TestingFirebaseHolder.class,query
    ) {
        @Override
        protected void populateViewHolder(TestingFirebaseHolder viewHolder, TestingUser model, int position) {

            viewHolder.setTextView(model.mUid,model.UserName);

        }
    };

    mRecyclerView.setAdapter(mAdapter);


public void buttonClick(View view) {

        if(!mEditText.getText().toString().isEmpty())
        {
            TestingUser user = new TestingUser("Salman",mEditText.getText().toString());
            mReference.child("Testing").child(mUser.getUid()).Push().setValue(user);
            mEditText.setText("");
        }

    }

Le résultat est lien

1
Salman500

Essayez ça, ça marche pour moi.

mLinearLayoutManager = new LinearLayoutManager(this);
mLinearLayoutManager.stackFromEnd(true)
mLinearLayoutManager.isSmoothScrollbarEnabled(true)
mMessageRecyclerView.setLayoutManager(mLinearLayoutManager);
1
Ramesh