问题
After applying almost all answers from stack overflow on same topic but i can not find solution for my problem. my problem is i have a list view which contain a question and a edit text in each row. but when i scroll list view data in edit text change or it may happen it comes in other edit text. i.e if i write some thing in 1st editext after scroll it may happen it is in 2nd or 3rd row edittext.
Some of the thing i have even tried from cursoradapter class but still.
Please help me guys.
import android.content.Context;
import android.content.res.Resources;
import android.database.Cursor;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.EditText;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class TestViewAdapter extends CursorAdapter
{
protected Cursor cursor;
protected Context context;
protected Resources res;
protected Random random;
protected LayoutInflater inflater;
protected Map<Integer, String>myinputs;
protected int mRowIDColumn;
public TestViewAdapter(Context context, Cursor c)
{
super(context, c);
this.cursor = c;
this.context = context;
this.res = this.context.getResources();
this.random = new Random();
boolean cursorPresent = c != null;
mRowIDColumn = cursorPresent ? this.cursor.getColumnIndexOrThrow("_id") : -1;
this.inflater = (LayoutInflater) this.context.getSystemService(this.context.LAYOUT_INFLATER_SERVICE);
myinputs = new HashMap<>();
}
private static class Viewholder
{
TextView question;
TextView answer;
EditText useranswer;
String que = "" , randomStr ="";
}
@Override
public View newView(Context context, Cursor c, ViewGroup parent)
{
View rowlayout = this.inflater.inflate(R.layout.testlist_row, null);
final Viewholder viewHolder;
String [] meaningArray = new String[] {"synonyms", "antonyms"};
viewHolder = new Viewholder();
// Set view for each row
viewHolder.question = (TextView) rowlayout.findViewById(R.id.tv_test_question);
viewHolder.answer = (TextView) rowlayout.findViewById(R.id.tv_test_answer);
viewHolder.useranswer = (EditText) rowlayout.findViewById(R.id.et_test_useranswer);
viewHolder.que = this.res.getString(R.string.popup_question); //get value from string.xml
//viewHolder.randomStr = meaningArray[this.random.nextInt(meaningArray.length)];
viewHolder.useranswer.clearFocus();
rowlayout.setTag(viewHolder);
return rowlayout;
}
@Override
public int getCount() {
return cursor.getCount();
}
@Override
public long getItemId(int position) {
if (cursor != null) {
if (cursor.moveToPosition(position)) {
return cursor.getLong(mRowIDColumn);
} else {
return 0;
}
} else {
return 0;
}
}
@Override
public void bindView(View view, Context context, Cursor c)
{
final Viewholder viewHolder = (Viewholder) view.getTag();
final int rowPosition = (int) getItemId(c.getPosition());
String synonyms = "" , antonyms = "" , word = "",text = "" ,ans = "";
word = cursor.getString(cursor.getColumnIndex(cursor.getColumnName(1)));
synonyms = cursor.getString(cursor.getColumnIndex(cursor.getColumnName(2)));
antonyms = cursor.getString(cursor.getColumnIndex(cursor.getColumnName(3)));
if ( !synonyms.isEmpty())
{
text = String.format(viewHolder.que, "synonyms", word.toLowerCase());
ans = synonyms;
}
else if( !antonyms.isEmpty())
{
text = String.format(viewHolder.que, "antonyms", word.toLowerCase());
ans = antonyms;
}
viewHolder.question.setText(text);
viewHolder.answer.setText(ans);
viewHolder.useranswer.addTextChangedListener(new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count)
{
if (s.toString().length() > 0) {
Log.d("TestViewAdapterb", "pos -" + rowPosition + "," + s.toString());
myinputs.put(rowPosition , s.toString());
}
}
});
String v = myinputs.get(rowPosition);
viewHolder.useranswer.setText(v == "" ? "" : v);
}
}
I got the way and below one is my updated code for preserving user input. hope it will be helpful to some body.
public class TestViewAdapter extends CursorAdapter
{
protected Cursor cursor;
protected Context context;
protected Resources res;
protected Random random;
protected LayoutInflater inflater;
protected ArrayList<HashMap<String,String>> resultList;
protected int mRowIDColumn;
public TestViewAdapter(Context context, Cursor c)
{
super(context, c);
this.cursor = c;
this.context = context;
this.res = this.context.getResources();
this.random = new Random();
boolean cursorPresent = c != null;
mRowIDColumn = cursorPresent ? this.cursor.getColumnIndexOrThrow("_id") : -1;
this.inflater = (LayoutInflater) this.context.getSystemService(this.context.LAYOUT_INFLATER_SERVICE);
resultList = new ArrayList<HashMap<String,String>>();
if(c != null && c.getCount() > 0)
{
c.moveToFirst();
for (int i=0;i<c.getCount();i++)
{
HashMap<String,String> row = new HashMap<String,String>();
row.put("userans","");
resultList.add(row);
}
}
}
private static class Viewholder
{
TextView question;
TextView answer;
EditText useranswer;
String randomStr ="";
}
public ArrayList<HashMap<String,String>> getUserInputResult()
{
return resultList;
}
@Override
public View newView(Context context, Cursor c, ViewGroup parent)
{
View rowlayout = this.inflater.inflate(R.layout.testlist_row, null);
final Viewholder viewHolder;
String [] meaningArray = new String[] {"synonyms", "antonyms"};
viewHolder = new Viewholder();
// Set view for each row
viewHolder.question = (TextView) rowlayout.findViewById(R.id.tv_test_question);
viewHolder.answer = (TextView) rowlayout.findViewById(R.id.tv_test_answer);
viewHolder.useranswer = (EditText) rowlayout.findViewById(R.id.et_test_useranswer);
viewHolder.randomStr = meaningArray[this.random.nextInt(meaningArray.length)];
viewHolder.useranswer.clearFocus();
rowlayout.setTag(viewHolder);
return rowlayout;
}
@Override
public int getCount() {
return cursor.getCount();
}
@Override
public long getItemId(int position) {
if (cursor != null) {
if (cursor.moveToPosition(position)) {
return cursor.getLong(mRowIDColumn);
} else {
return 0;
}
} else {
return 0;
}
}
@Override
public void bindView(View view, Context context, Cursor c)
{
final Viewholder viewHolder = (Viewholder) view.getTag();
final int rowPosition = (int) getItemId(cursor.getPosition());
final int rowId = cursor.getInt(cursor.getColumnIndex(cursor.getColumnName(0)));
boolean isBoth = false, isSyno = false , isAnto = false, isQuestionset = false;
String que = "";
String synonyms = "";
String antonyms = "";
String word = "";
String text = "";
String ans = "";
que = this.res.getString(R.string.popup_question);
word = cursor.getString(cursor.getColumnIndex(cursor.getColumnName(1)));
synonyms = cursor.getString(cursor.getColumnIndex(cursor.getColumnName(2)));
antonyms = cursor.getString(cursor.getColumnIndex(cursor.getColumnName(3)));
if (!synonyms.isEmpty() && !antonyms.isEmpty())
{
isBoth = true;
isSyno = true;
isAnto = true;
}
else if (!synonyms.isEmpty())
{
isSyno = true;
}
else if (!antonyms.isEmpty())
{
isAnto = true;
}
if (isBoth)
{
if(viewHolder.randomStr.equals("synonyms"))
{
text = String.format(que, "synonyms", word.toLowerCase());
ans = synonyms;
}
else
{
text = String.format(que, "antonyms", word.toLowerCase());
ans = antonyms;
}
}
else if (isSyno)
{
if (viewHolder.randomStr.equals("synonyms"))
{
text = String.format(que, "synonyms", word.toLowerCase());
ans = synonyms;
isQuestionset = true;
}
else if (isAnto)
{
text = String.format(que, "antonyms", word.toLowerCase());
ans = antonyms;
isQuestionset = true;
}
if (!isQuestionset)
{
text = String.format(que, "synonyms", word.toLowerCase());
ans = synonyms;
isQuestionset = true;
}
}
else if (isAnto)
{
text = String.format(que, "antonyms", word.toLowerCase());
ans = antonyms;
}
viewHolder.question.setText(text);
viewHolder.answer.setText(ans);
HashMap<String,String> row = resultList.get(c.getPosition());
row.put("preans",ans);
viewHolder.useranswer.setId(cursor.getPosition());
viewHolder.useranswer.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus)
{
if (!hasFocus)
{
if (((EditText)v).getText().toString().length() > 0) {
Log.d("TestViewAdapterb", "pos -" + rowPosition + "," + ((EditText)v).getText().toString().trim());
HashMap<String,String> row = resultList.get(v.getId());
row.put("userans",((EditText)v).getText().toString().trim());
}
}
}
});
viewHolder.useranswer.setText(row.get("userans"));
}
}
One more thing add
android:descendantFocusability="beforeDescendants"
This will allow child view to get focus when user clicks on item of the list view.To store value when user scroll the listview i have used arraylist which holds hashmap object. second thing i learned is that never comparee string using '==' in place of it use isEmpty method or contains method.
回答1:
I imagine the issue lies in this line:
text = String.format(viewHolder.que, "synonyms", word.toLowerCase());
The reason I say this is because you're referencing the ViewHolder to get the value of the text. Since the ViewHolder recycles, the value of your text will recycle too.
Try getting the value of the text directly from the cursor without intervention from the ViewHolder.
来源:https://stackoverflow.com/questions/26286006/how-to-preserve-edittext-value-in-custom-cursor-adapter