Добавить элементы внизу обзора Recycler
Код иллюстрации:
mLinearLayoutManager = new LinearLayoutManager(this);
mLinearLayoutManager.setReverseLayout(true);
mLinearLayoutManager.setStackFromEnd(true);
mMessageRecyclerView.setLayoutManager(mLinearLayoutManager);
Смотрите рисунок здесь
Как добавить новые элементы (в моем случае, сообщения) в снизу просмотра Recycler и по-прежнему удерживать "тяжести" вида сверху?
Итак, что теперь работает:
- Сверху вид сверху. Это хорошо! ✓
Что не работает:
- Новые сообщения добавляются в верхнюю часть представления. Это плохо ×
Я хочу, чтобы они были добавлены в нижней части представления (после предыдущего сообщения) следующим образом:
См. здесь
Ответы
Ответ 1
setStackFromEnd = true и setReverseLayout = true
Разница между этими двумя заключается в том, что setStackFromEnd
установит представление для отображения последнего элемента, направление макета останется тем же, тогда как setReverseLayout
изменит порядок элементов, добавленных адаптером.
Попробуйте удалить эти две строки или установить их false
layoutManager.setReverseLayout(true);
layoutManager.setStackFromEnd(true);
Попробуйте использовать это, чтобы переместить RecyclerView
и EditText
вверх при появлении клавиатуры
<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>
в AndroidManifest.xml
.
Чтобы перехватить RecyclerView вверху
<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" />
Чтобы сначала загрузить recyclerView внизу и нажимать его, когда клавиатура появляется.
<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>
Чтобы прокрутить recyclerView снизу, когда клавиатура появляется, т.е. когда изменяется макет вида ресайклера (вы можете сделать то же самое в "Редактировании текста" активным или сфокусированным или нажатым или что-то в этом роде. Я сделал это на макете просмотра ресайклеров измените.)
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);
}
}
});
Ответ 2
setReverseLayout (true), это изменит порядок обхода и расположения макета. Первый элемент завершится без просмотра или содержимого.
setStackFromEnd (true), это заполнит содержимое списка ресайклеров, начиная со дна представления.
Требуется setStackFromEnd(true)
не setReverseLayout(true)
И в XML Высота Recyclerview должна быть match_parent
Ниже приведен рабочий код.
активность 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>
Элемент списка элементов 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>
Класс адаптера
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;
}
}
Класс действия
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);
}
}
![введите описание изображения здесь]()
Ответ 3
Самый простой способ добиться этого - загрузить элементы в Recyclerview в обратном порядке, как они будут введены в базу данных Firebase.
@Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
Log.d(TAG, "Element " + position + " set.");
viewHolder.getTextView().setText(mDataSet.get(getItemCount() - 1 -position));
}
Что бы это могло сделать, так это то, что элемент, который вставлен последним, будет отображаться внизу, так как вы загружаете элементы сверху. Нет необходимости в каких-либо изменениях в любом из XML или любом другом коде.
У меня были те же проблемы, что и Recylerview, не изменяя размер, когда клавиатура всплывает, и поэтому я прибегал к этому методу.
Все самое лучшее!
Ответ 4
Я реализовал и вот моя реализация с использованием FirebaseRecyclerView
вам нужно установить этот setStackFromEnd=true
и setReverseLayout=true
my xml
Держатель рекуператора
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);
}
}
Класс тестирования
public class TestingUser {
public String UserName;
public String mUid;
public TestingUser() {
}
public TestingUser(String userName, String uid) {
UserName = userName;
mUid = uid;
}
}
Код действия
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("");
}
}
Результат
ссылка
Ответ 5
Попробуй, это работает для меня.
mLinearLayoutManager = new LinearLayoutManager(this);
mLinearLayoutManager.stackFromEnd(true)
mLinearLayoutManager.isSmoothScrollbarEnabled(true)
mMessageRecyclerView.setLayoutManager(mLinearLayoutManager);