Add items to bottom of Recycler View
Solution 1
Try removing these two lines or setting them false
layoutManager.setReverseLayout(true);
layoutManager.setStackFromEnd(true);
setStackFromEnd
will set the view to show the last element, the layout direction will remain the same whereas setReverseLayout
will change the order of the elements added by the Adapter.
Try using this to move your RecyclerView
and EditText
up when keyboard appears
<activity name="YourActivity"
android:windowSoftInputMode="stateHidden|adjustResize">
//stateHidden -> keyboard is hidden when you first open the activity
//adjustResize -> this will adjust the layout resize option
...
</activity>
in AndroidManifest.xml
.
To hook the RecyclerView at top
<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" />
To put the recyclerView at bottom first and push it up as the keyboard pops up.
<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>
To scroll the recyclerView to bottom when keyboard pops up i.e. when the recycler view's layout is changed ( You can do the same thing on Edit Text active or focused or clicked or something like that. I've done it on recycler view's layout change. )
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);
}
}
});
Solution 2
setReverseLayout(true) this will reverse the item traversal & layout order.The first item will come to end not view or content.
setStackFromEnd(true) this will fill the recycler list content starting from the bottom of the view.
Need to setStackFromEnd(true)
not setReverseLayout(true)
And in XML Recyclerview height should be match_parent
Below i have given working code.
activity 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>
list item xml layout
<?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>
Adapter class
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;
}
}
Activity class
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);
}
}
Solution 3
The simplest way to achieve this would be to load the elements into the Recyclerview in the reverse order to how they are entered in the Firebase Database.
@Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
Log.d(TAG, "Element " + position + " set.");
viewHolder.getTextView().setText(mDataSet.get(getItemCount() - 1 -position));
}
What this would do is that the item which is inserted last will get displayed at bottom since you are loading the items from top. No need for any change in any of the XMLs or any other code.
I had same issues with Recylerview not resizing itself when the keyboard pops up and therefore I resorted to this method.
All the best!!
Solution 4
I have implemented and here is my Implementation using FirebaseRecyclerView
you need to set this setStackFromEnd=true
and setReverseLayout=true
Recycler View Holder
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);
}
}
Testing Class
public class TestingUser {
public String UserName;
public String mUid;
public TestingUser() {
}
public TestingUser(String userName, String uid) {
UserName = userName;
mUid = uid;
}
}
Activity Code
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("");
}
}
Result is link
Solution 5
Try this, it works for me.
mLinearLayoutManager = new LinearLayoutManager(this);
mLinearLayoutManager.stackFromEnd(true)
mLinearLayoutManager.isSmoothScrollbarEnabled(true)
mMessageRecyclerView.setLayoutManager(mLinearLayoutManager);
Related videos on Youtube
Admin
Updated on September 14, 2022Comments
-
Admin over 1 year
Code of the illustration:
mLinearLayoutManager = new LinearLayoutManager(this); mLinearLayoutManager.setReverseLayout(true); mLinearLayoutManager.setStackFromEnd(true); mMessageRecyclerView.setLayoutManager(mLinearLayoutManager);
How can I add new items (in my case, messages) to the bottom of Recycler View and still keep the "gravity" of the view to the top?
So, what works now is the following:
- The gravity of the view is at the top. That's good! ✓
What doesn't work:
- New messages are added to the top of the view. That's bad × I want them to be added at the bottom of the view (after the previous message) like so: See here
-
Admin over 6 yearsThanks for your long answer. But, I am already using FirebaseRecyclerAdapter Here's a similar project that also uses FirebaseRecyclerAdapter: github.com/firebase/friendlychat-android/tree/master/android
-
Admin over 6 yearsI don't who deleted the he previous comments but here's my XML file again: pastebin.com/XGrN5Dsj
-
Jonathan Doe over 6 yearsThe bounty will be awarded once the asker's problem is resolved.
-
Admin over 6 yearsThe issue is still not fixed.
-
Admin over 6 yearsI want when the soft keyboard pops up, the RecyclerView to pushed also.
-
Niraj Niroula over 6 yearsDid you tried the edited one. Man, why don't you experiment your xml! Just take your time.