问题
I have searched for this one but to no avail I haven't get the exact answer to the issue.
I have a button inside a ListView
, when that button is clicked it shows an alert dialog to choose a date and after choosing date, the selected date will be the text of the button. The code works fine but when i scroll down and up the date will be randomly change
here is my code for the getView()
method of my adapter.This also happens to the EditText
when i type to any of the EditText
works fine but when i start scrolling the values also change.
Here is my get view method
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder;
if(convertView == null){
convertView = layoutInflater.inflate(R.layout.repeat_entry_listview,null);
viewHolder = new ViewHolder();
viewHolder.btnDate = (Button) convertView.findViewById(R.id.rpbtnDate);
viewHolder.txtNotes = (EditText) convertView.findViewById(R.id.rpNotes);
convertView.setTag(viewHolder);
}else{
viewHolder = (ViewHolder) convertView.getTag();
}
RepeatEntryList repeatEntryList = listData.get(position);
viewHolder.btnDate.setText(repeatEntryList.getDate());
viewHolder.btnDate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//EVEN IF I REMOVE THE CODE FOR SETTING THE BUTTON TEXT TO JUST LIKE THE BELOW CODE. SCROLLING ISSUES STILL PERSIST
viewHolder.btnDate.setText("just sample date text");
//**NOTE UPDATED**
//MY EDITTEXT ALSO HAVE THE SAME BEHAVIOR
}
});
viewHolder.txtNotes.setHint(contx.getResources().getString(R.string.placeholder_txt));
return convertView;
}
Note Let's say i have 20 buttons and 20 EditText
inside the ListView
. When i type something to all of the EditText
and change the text of the button by clicking it ,then scroll down and up the ListView
,the text or values of EditText
and button will change or interchange and sometimes gone.
With regards to my problem can someone explain to me why ListView
is behaving like this and how to avoid this certain behavior.
回答1:
make changes in your code remove if(convertView == null){ }else{} condition and directly use as follow
convertView = layoutInflater.inflate(R.layout.repeat_entry_listview,null);
Button btnDate = (Button) convertView.findViewById(R.id.rpbtnDate);
TextView txtNotes = (EditText) convertView.findViewById(R.id.rpNotes);
回答2:
Just add below line, repeatEntryList.setDate("Selected Date")
datePickerTo.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String strdate = (pickerTo.getMonth() + 1) + "-" + pickerTo.getDayOfMonth() + "-" + pickerTo.getYear();
viewHolder.btnDate.setText(mainActivity.pickerStringTodate(strdate));
//Here is your new line
repeatEntryList.setDate(mainActivity.pickerStringTodate(strdate))
try {
Date date1 = mainActivity.dateFormat.parse(viewHolder.btnDate.getText().toString());
Date date2 = mainActivity.dateFormat.parse(mainActivity.dateFormat.format(new Date()));
if (date1.before(date2)) {
Toast.makeText(contx, "You cannot select past date", Toast.LENGTH_LONG).show();
viewHolder.btnDate.setText(mainActivity.dateFormat.format(new Date()));
}
} catch (ParseException e) {
e.printStackTrace();
}
}
}).setNegativeButton("Cancel", null);
datePickerTo.show();
回答3:
Make your position
variable final
in getView
final int position
And also make your modal class as Final.
final RepeatEntryList repeatEntryList = listData.get(position);
回答4:
You are using an if condition:
if (date1.before(date2)) {
Toast.makeText(contx, "You cannot select past date", Toast.LENGTH_LONG).show();
viewHolder.btnDate.setText(mainActivity.dateFormat.format(new Date()));
}else{viewHolder.btnDate.setVisibility(View.GONE);}
But there is no else case. The else case should be handled too.
回答5:
This is what i have done to solve my problem is incase someone might have the same problem:
1. First i create i variable inside my custom Adapter class which is RepeatEntryListAdapter and called it listData
public ArrayList<RepeatEntryList> listData;
2. i reference listData variable to be the array list of RepeatEntryList class which is my getter and setter class like this.
public RepeatEntryListAdapter(Context context,ArrayList<RepeatEntryList> listdata){
this.listData = listdata;
this.contx = context;
mainActivity = (MainActivity) context;
layoutInflater= LayoutInflater.from(context);
}
3. Inside getview method i created click event for the button .Inside the click event I instantiated my getter class then use the instantiated variable of my getter class and use settext,for setting the text of the button and also set the date for the lisData variable.and the important part is use the listData variable in which i use the position variable to set the value of a certain position of the listData varaible like this.
RepeatEntryList re = rListData;
viewHolder.btnDate.setText('07-06-2015')//say the date selected is the string inside setText re.setDate(viewHolder.btnDate.getText().toString());//set Date is a setter method inside my RepeatEntryList class
listData.set(position, re);//position variable should be final
4. This is the most trickiest part which is part in solving the scrolling problem of my custom list view which is caused by the edittext watcher which fires when scrolling . what i did is.
a. i Created a class that implements TextWatcher like this
class EditTextWatcher implements TextWatcher{
private int mPosition;
private boolean mActive;
void setPosition(int position){
mPosition = position;
}
void setActive(boolean active){
mActive = active;
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if(mActive){
//rNotes.set(mPosition,s.toString());
RepeatEntryList re = listData.get(mPosition);
re.setNotes(s.toString());
listData.set(mPosition,re);
}
}
}
b. i also created a variable for EditeTextWatcher inside my static class ViewHolder
static class ViewHolder{
public Button btnDate;
public EditText txtNotes;
public EditTextWatcher mWatcher;
}
c. inside my getview method ,i created a new instance of EditTextWatcher() which also create a new textwatcher and not use the last event because i create a new instance of the textwatcher
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder;
final RepeatEntryList rListData = listData.get(position);
if(convertView == null){
convertView = layoutInflater.inflate(R.layout.repeat_entry_listview,null);
viewHolder = new ViewHolder();
viewHolder.btnDate = (Button) convertView.findViewById(R.id.rpbtnDate);
viewHolder.mWatcher = new EditTextWatcher();
viewHolder.txtNotes = (EditText) convertView.findViewById(R.id.rpNotes);
viewHolder.txtNotes.addTextChangedListener(viewHolder.mWatcher);
convertView.setTag(viewHolder);
}else{
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.btnDate.setText(rListData.getDate());
viewHolder.mWatcher.setActive(false);
viewHolder.txtNotes.setText(rListData.getNotes());
viewHolder.mWatcher.setPosition(position);
viewHolder.mWatcher.setActive(true);
//here is the part of button click event i mention above (no 3.)
return convertView;
}
来源:https://stackoverflow.com/questions/31309654/customized-listview-when-scrolling-changes-randomly-button-text-or-edittext