[英]RecyclerView Adapter inserting rows in weird positions
I have a Fragment
inside of my MainActivity
that contains a RecyclerView
being populated by a RecyclerView.Adapter
. 我的MainActivity
内部有一个Fragment
,其中包含由RecyclerView
填充的RecyclerView.Adapter
。 The RecyclerView
inflates row_layout.xml
file, which has one EditText
and one ImageButton
, like this: RecyclerView
使row_layout.xml
文件膨胀,该文件具有一个EditText
和一个ImageButton
,如下所示:
The button is initially loaded with an "add" image. 该按钮最初加载有“添加”图像。 When clicked, my adapter does this: 单击后,我的适配器将执行以下操作:
package com.fragments.homework04;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageView;
import java.util.ArrayList;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
public static int positionAdapter;
private ArrayList<ItemData> itemsData;
AdapterButtonInterface mListener;
public MyAdapter(ArrayList<ItemData> itemsData, AdapterButtonInterface adapterButtonInterface) {
this.itemsData = itemsData;
try{
mListener = adapterButtonInterface;
}
catch(ClassCastException e){
throw new ClassCastException("Class does not implement interface!");
}
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public EditText txtIngredients;
public ImageView imgViewIcon;
public ViewHolder(View itemLayoutView) {
super(itemLayoutView);
txtIngredients = itemLayoutView.findViewById(R.id.etIngredientName);
imgViewIcon = itemLayoutView.findViewById(R.id.btnAddRemoveIngredient);
}
}
@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_layout, null);
Log.d("itemsSizeAdapter", String.valueOf(itemsData.size()));
ViewHolder viewHolder = new ViewHolder(itemLayoutView);
return viewHolder;
}
@Override
public void onBindViewHolder(final ViewHolder viewHolder, final int position) {
viewHolder.imgViewIcon.setTag(itemsData.get(position).getTag());
viewHolder.imgViewIcon.setImageResource(itemsData.get(position).getImageUrl());
viewHolder.imgViewIcon.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
positionAdapter = viewHolder.getAdapterPosition();
if(itemsData.get(position).getTag().contains("Add")){
if(getItemCount() < 5){
itemsData.get(position).setIngredientValue(viewHolder.txtIngredients.getText().toString());
mListener.addBtnClicked(positionAdapter, getItemCount(), itemsData.get(position).getIngredientValue());
}
}
else{
if(getItemCount() > 0){
Log.d("adapterPosition:", String.valueOf(position));
mListener.removeBtnClicked(positionAdapter, getItemCount());
}
}
}
});
}
// Return the size of your itemsData (invoked by the layout manager)
@Override
public int getItemCount() {
return itemsData.size();
}
public interface AdapterButtonInterface{
void addBtnClicked(int position, int itemCount, String ingredientValue);
void removeBtnClicked(int position, int itemCount);
}
}
Basically calls the method in the interface, that is being implemented by my fragment. 基本上在接口中调用该方法,该方法由我的片段实现。 In my fragment, I am doing this: 在我的片段中,我正在这样做:
ArrayList<ItemData> itemsData;
public void addBtnClicked(int position, int itemCount, String ingredientValue) {
if(itemCount == 4){
//Requirement that there can only be 5 rows at any time.
//Hence when itemCount == 4, we are adding the 5th row and it needs to be a remove instead of add
itemsData.add(position + 1, new ItemData("Remove" + itemCount, R.mipmap.remove_ing, ""));
}
else{
itemsData.add(position + 1, new ItemData("Add" + itemCount, R.mipmap.add_ing, ""));
}
//When the row is added, the EditText's value isn't stored anywhere
//So I am adding it to the arraylist I have
itemsData.get(position).setIngredientValue(ingredientValue);
itemsData.get(position).setImageUrl(R.mipmap.remove_ing);
itemsData.get(position).setTag("Remove");
mAdapter.notifyDataSetChanged();
}
@Override
public void removeBtnClicked(int position, int itemCount) {
Log.d("listenerPosition:", String.valueOf(position));
itemsData.remove(position);
if(itemCount == 5){
itemsData.get(3).setImageUrl(R.mipmap.add_ing);
itemsData.get(3).setTag("Add3");
}
mAdapter.notifyDataSetChanged();
}
A good bit of this works perfectly. 其中很大一部分效果很好。 When my app loads, I see one EditText and one ImageButton. 应用加载时,我看到一个EditText和一个ImageButton。 When I click the ImageButton for the first time, it adds my second EditText and my second ImageButton underneath my first. 当我第一次单击ImageButton时,它将在第二个EditText和第二个ImageButton的下面添加它。
BUT, the problem arises when I click my button the second time. 但是,第二次单击按钮时出现了问题。 The third row gets inserted in the top of the RecyclerView
instead of the bottom. 第三行插入在RecyclerView
的顶部而不是底部。 My already existent 1st and 2nd rows get pushed down (along with the contents of the EditText), and my newly added row goes to the top of the recycler. 我已经存在的第一和第二行(与EditText的内容一起)被下推,而我新添加的行位于回收站的顶部。
It gets even weirder, when I click on the "remove" button on my newly inserted top row. 当我单击新插入的第一行上的“删除”按钮时,它甚至变得更奇怪。 It removes one row (as expected) and it clears all my EditTexts (WHY). 它删除一行(按预期方式),并清除我所有的EditTexts(WHY)。
If anyone can look at this and tell me where I am making a mistake, I'd appreciate it. 如果有人可以看看并告诉我我在哪里犯错,我将不胜感激。 I can provide more of my code if needed. 如果需要,我可以提供更多代码。
You specify that the position is final
in the ViewHolder
so you can reference it in the onClick()
handler. 您可以在ViewHolder
指定该位置为final
位置,以便可以在onClick()
处理程序中引用该位置。 Since that variable is final
it will not change regardless of any new position that the ViewHolder
may take. 由于该变量是final
变量,因此无论ViewHolder
可能处于任何新位置,它都不会改变。 Instead of a final
variable, try using getAdapterPosition()
. 代替使用final
变量,请尝试使用getAdapterPosition()
。
getAdapterPosition getAdapterPosition
int getAdapterPosition () int getAdapterPosition()
Returns the Adapter position of the item represented by this ViewHolder. 返回此ViewHolder表示的项目的Adapter位置。
This may not be your problem, but give it a try. 这可能不是您的问题,但请尝试一下。
Use this two methods in adapter 在适配器中使用这两种方法
@Override
public long getItemId(int position) {
return super.getItemId(position);
}
@Override
public int getItemViewType(int position) {
return super.getItemViewType(position);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.