简体   繁体   English

使用 ArrayAdapter 添加/删除包含 EditText 的 ListView 项目

[英]Add/Delete item on ListView containing EditText with ArrayAdapter

I have a problem using CustomAdaptor.我在使用 CustomAdaptor 时遇到问题。 On a add/edit recipe I want to display a list with the ingredient and the amount and possibility to delete this item with a button.在添加/编辑食谱中,我想显示一个包含成分的列表以及使用按钮删除该项目的数量和可能性。 As you can see on the pictures, at first the list is only one item (without delete button because visibility = INVISIBLE in order to oblige to give at least one ingredient) and I have a button below the list to add other blank item but the other need to keep editing text .正如您在图片上看到的,起初列表只有一个项目(没有删除按钮,因为可见性 = INVISIBLE 以便有义务提供至少一种成分),我在列表下方有一个按钮来添加其他空白项目,但其他需要继续编辑文本

Firstly, when I clicked on this button I lose all edited text.首先,当我点击这个按钮时,我丢失了所有编辑过的文本。 Secondly, I don't see who to manage to delete an item (I tried this solution ).其次,我不知道由谁来管理删除项目(我试过这个解决方案)。

I hope someone has already solved this thing and could help me :)我希望有人已经解决了这个问题并且可以帮助我:)


activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_above="@id/btn_save">

        <LinearLayout
            android:id="@+id/block_ingredient"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

            <ListView
                android:id="@+id/listview_ingredient"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />

            <Button
                android:id="@+id/btn_add"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:text="+" />

        </LinearLayout>

    </ScrollView>

    <Button
        android:id="@+id/btn_save"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:text="SAVE" />

</RelativeLayout>

list_ingredient.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" >

    <EditText
        android:id="@+id/quantite"
        android:layout_width="0dp"
        android:layout_weight="45"
        android:layout_height="wrap_content"
        android:hint="Quantite" />

    <EditText
        android:id="@+id/ingredient"
        android:layout_width="0dp"
        android:layout_weight="45"
        android:layout_height="wrap_content"
        android:hint="Ingredient" />

    <Button
        android:id="@+id/btn_delete"
        android:layout_width="0dp"
        android:layout_weight="10"
        android:layout_height="wrap_content"
        android:text="X" />
</LinearLayout>

Item.java

public class Item {
    private String Quantite;
    private String Ingredient;

    // --- CONSTRUCTORS ---
    public Item() {};
    public Item(String Quantite, String Ingredient) {
        this.Quantite = Quantite;
        this.Ingredient = Ingredient;
    }

    // --- GETTER ---
    public String getQuantite() { return Quantite; }
    public String getIngredient() { return Ingredient; }

    // --- SETTER ---
    public void setQuantite(String Quantite) { this.Quantite = Quantite; }
    public void setIngredient(String Ingredient) { this.Ingredient = Ingredient; }
}

IngredientAdapter.java

public class IngredientAdapter extends ArrayAdapter {

    private Context context;
    private ArrayList<Item> listItem;
    private static LayoutInflater inflater = null;
    private View v;
    private ViewHolder viewHolder;

    public IngredientAdapter(Context context, ArrayList<Item> listItem) {
        super(context, 0, listItem);
        this.context = context;
        this.listItem = listItem;
        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override public int getCount() { return listItem.size(); }

    @Override public Object getItem(int i) { return null; }

    public ArrayList<Item> getItems() {
        return new ArrayList<Item>(listItem);
    }

    @Override public View getView(int i, View convertView, ViewGroup parent) {
        View finalView = convertView;
        final int position = i;
        Item item = listItem.get(position);
        if (convertView == null) {
            finalView = inflater.inflate(R.layout.list_ingredient, null);
            viewHolder = new ViewHolder();
            viewHolder.Quantite = finalView.findViewById(R.id.quantite);
            viewHolder.Ingredient = finalView.findViewById(R.id.ingredient);
            viewHolder.Btn_delete = finalView.findViewById(R.id.btn_delete);
            finalView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        viewHolder.Quantite.setText(item.getQuantite());
        viewHolder.Ingredient.setText(item.getIngredient());
        if (listItem.size() < 2) {
            viewHolder.Btn_delete.setVisibility(View.INVISIBLE);
        }

        viewHolder.Btn_delete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Integer position = (Integer) view.getTag();
                listItem.remove(position);
                notifyDataSetChanged();
            }
        });

        return finalView;
    }

    public ArrayList<Item> getAll() { return listItem; }

    public class ViewHolder {
        EditText Quantite;
        EditText Ingredient;
        Button Btn_delete;
    }

    public void setItems(ArrayList<Item> listItem) {
        this.listItem = listItem;
    }
}

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private ListView listview_ingredient;
    private Button btn_add;
    private Button btn_save;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        listview_ingredient = findViewById(R.id.listview_ingredient);
        btn_add = findViewById(R.id.btn_add);
        btn_save = findViewById(R.id.btn_save);

        final ArrayList<Item> IngredientList = new ArrayList<Item>();
        if (IngredientList.size() == 0) {
            IngredientList.add(new Item());
        }

        final IngredientAdapter ingredientAdapter = new IngredientAdapter(this, IngredientList);
        listview_ingredient.setAdapter(ingredientAdapter);

        btn_add.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                // Ajouter un item vide
                IngredientList.add(new Item());
                final IngredientAdapter ingredientAdapter = new IngredientAdapter(MainActivity.this, IngredientList);
                listview_ingredient.setAdapter(ingredientAdapter);

            }
        });

        btn_save.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                // Sauvegarder les réponses

            }
        });

    }
}

I know the list show only one item with scrollbar but I already have a code to correct, it's just more readeable without.我知道列表只显示一个带有滚动条的项目,但我已经有一个代码可以更正,没有它就更易读了。

As Barns suggest, I moved to RecyclerView and used notifyDataSetChanged() when I add new Item.正如 Barns 所建议的那样,我移到 RecyclerView 并在添加新项目时使用了 notifyDataSetChanged()。

If it's helped others I had my changes below and I add this link because it's good tutorial to RecyclerView with EditText : https://demonuts.com/android-recyclerview-with-edittext/如果它对其他人有帮助,我在下面进行了更改并添加了此链接,因为它是使用 EditText 的 RecyclerView 的好教程: https : //demonuts.com/android-recyclerview-with-edittext/

For the above code I change this things :对于上面的代码,我更改了以下内容:

activity_main.xml

only changed ListView to RecyclerView仅将 ListView 更改为 RecyclerView

MainActivity.java

when I call the Adapter :当我调用适配器时:

ingredientAdapter = new IngredientAdapter(this, IngredientList);
listview_ingredient.setAdapter(ingredientAdapter);
listview_ingredient.setLayoutManager(new LinearLayoutManager(getApplicationContext()) {
    @Override public boolean canScrollVertically() {
        return false;
    }
});

On click add button :点击添加按钮:

IngredientList.add(new Item());
ingredientAdapter.notifyDataSetChanged();

and the Adapter become和适配器成为

public class IngredientAdapter extends RecyclerView.Adapter<IngredientAdapter.ViewHolder> {

    private Context context;
    public static ArrayList<Item> IngredientList;
    private static LayoutInflater inflater = null;
    private ViewHolder viewHolder;

    // --- CONSTRUCTOR ---
    public IngredientAdapter(Context context, ArrayList<Item> listItem) {
        inflater = LayoutInflater.from(context);
        this.context = context;
        this.IngredientList = listItem;
    }

    // --- ADAPTER ---
    @Override public IngredientAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = inflater.inflate(R.layout.list_ingredient, parent, false);
        ViewHolder holder = new ViewHolder(view);
        return holder;
    }

    // --- SET TEXT TO THE ELEMENT OF THE LIST
    @Override public void onBindViewHolder(final IngredientAdapter.ViewHolder holder, final int position) {
        holder.Quantite.setText(IngredientList.get(position).getQuantite());
        holder.Ingredient.setText(IngredientList.get(position).getIngredient());
        if (getItemCount() == 1) {
            holder.Delete.setVisibility(View.INVISIBLE);
        } else {
            holder.Delete.setVisibility(View.VISIBLE);
        }
    }

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

    class ViewHolder extends RecyclerView.ViewHolder {

        protected EditText Quantite;
        protected EditText Ingredient;
        protected Button Delete;

        public ViewHolder(View itemView) {
            super(itemView);
            Quantite = (EditText) itemView.findViewById(R.id.quantite);
            Ingredient = (EditText) itemView.findViewById(R.id.ingredient);
            Delete = (Button) itemView.findViewById(R.id.btn_delete);

            Quantite.addTextChangedListener(new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

                }

                @Override
                public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                    IngredientList.get(getAdapterPosition()).setQuantite(Quantite.getText().toString());
                }

                @Override
                public void afterTextChanged(Editable editable) {

                }
            });

            Ingredient.addTextChangedListener(new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

                }

                @Override
                public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                    IngredientList.get(getAdapterPosition()).setIngredient(Ingredient.getText().toString());
                }

                @Override
                public void afterTextChanged(Editable editable) {

                }
            });

            Delete.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    IngredientList.remove(getAdapterPosition());
//                    notifyItemRemoved(getAdapterPosition());
                    notifyDataSetChanged();
                }
            });

        }
    }
}

On delete Item you can change notifyDataSetChanged() to notifyItemRemoved() but since I have condition on list size to hide or display delete button I have to "restart" the adapter.在删除项目时,您可以将 notifyDataSetChanged() 更改为 notifyItemRemoved() 但由于我对列表大小有条件来隐藏或显示删除按钮,因此我必须“重新启动”适配器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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