Hey so the goal is that when the button cancel of a list item is clicked, the state of the item must be shown as "Canceled" and the button goes black. However, when pressing on the button the button does go black but the list item doesn't change state. Instead, the last button of the view list changes state. Can you help me out?
Adapter class:
package com.example.myappfinal.Adapter;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.graphics.drawable.DrawableCompat;
import com.example.myappfinal.Logic.Appointment;
import com.example.myappfinal.R;
import java.util.ArrayList;
public class AppointmentListAdapter extends ArrayAdapter<Appointment> {
private String state,date,time;
private TextView stateT,dateT,timeT;
private Context mContext;
int mRecource;
public AppointmentListAdapter(@NonNull Context context, int resource, @NonNull ArrayList<Appointment> objects) {
super(context, resource, objects);
mContext=context;
mRecource=resource;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
state=getItem(position).getState();
String service=getItem(position).getService().getName();
date = getItem(position).getDate();
time = getItem(position).getStartTime();
LayoutInflater inflater = LayoutInflater.from(mContext);
convertView = inflater.inflate(mRecource,parent,false);
stateT = (TextView) convertView.findViewById(R.id.state);
TextView serviceT = (TextView) convertView.findViewById(R.id.service);
TextView dateT = (TextView) convertView.findViewById(R.id.date);
TextView timeT = (TextView) convertView.findViewById(R.id.time);
stateT.setText(state);
serviceT.setText(service);
dateT.setText(date);
timeT.setText(time);
Button button =(Button)convertView.findViewById(R.id.button);
if(state.equals("Canceled")){
Drawable buttonDrawable = button.getBackground();
buttonDrawable = DrawableCompat.wrap(buttonDrawable);
DrawableCompat.setTint(buttonDrawable, Color.BLACK);
button.setBackground(buttonDrawable);
}
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//do something
if(state.equals("Active")) {
getItem(position).cancel();
state = getItem(position).getState();
stateT.setText(state);
Drawable buttonDrawable = button.getBackground();
buttonDrawable = DrawableCompat.wrap(buttonDrawable);
DrawableCompat.setTint(buttonDrawable, Color.BLACK);
button.setBackground(buttonDrawable);
}
}
});
return convertView;
}
CodePudding user response:
The problem is that stateT
is a class member in the adapter that you override for each row's getView
call, so after the list is populated it always refers to the last row. You should not save the views (e.g. stateT
) as class members. Every call to getView
will override the prior values held there.
For your case you should probably do something like this (hard to say for sure without the full code)
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
// Don't re-inflate unless necessary
if( convertView == null ) {
LayoutInflater inflater = LayoutInflater.from(mContext);
convertView = inflater.inflate(mRecource,parent,false);
}
// Get the state of the current row
Appointment appt = getItem(position);
String state = appt.getState();
String service = appt.getService().getName();
String date = appt.getDate();
String time = appt.getStartTime();
// These should NOT be class members
TextView stateT = convertView.findViewById(R.id.state);
TextView serviceT = convertView.findViewById(R.id.service);
TextView dateT = convertView.findViewById(R.id.date);
TextView timeT = convertView.findViewById(R.id.time);
// Set the row's values
stateT.setText(state);
serviceT.setText(service);
dateT.setText(date);
timeT.setText(time);
Button button = convertView.findViewById(R.id.button);
if(state.equals("Canceled")){
Drawable buttonDrawable = button.getBackground();
buttonDrawable = DrawableCompat.wrap(buttonDrawable);
DrawableCompat.setTint(buttonDrawable, Color.BLACK);
button.setBackground(buttonDrawable);
// may also want to disable the button
button.setEnabled(false);
}
else {
button.setEnabled(true);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// get the current row state - since it may have been
// updated since the listener was created
String rowState = appt.getState();
if(rowState.equals("Active")) {
appt.cancel();
String newState = appt.getState();
// stateT here refers to just this row's TextView now
stateT.setText(newState);
Drawable buttonDrawable = button.getBackground();
buttonDrawable = DrawableCompat.wrap(buttonDrawable);
DrawableCompat.setTint(buttonDrawable, Color.BLACK);
button.setBackground(buttonDrawable);
// may also want to disable the button
button.setEnabled(false);
}
}
});
}
return convertView;
}