简体   繁体   English

RecyclerView Adapter在奇怪的位置插入行

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM