I have a problem using 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 .
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.
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/
For the above code I change this things :
activity_main.xml
only changed ListView to 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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.