問題描述
仍然是 android 的新手,甚至是自定義光標適配器的新手,所以我無法理解如何防止我的列表視圖回收視圖以防止滾動時來自一個編輯文本的輸入顯示在另一個中.我在其他帖子上看到說要更改 convertview 的名稱,但是如何做到這一點我是空白的.我希望這里有人能夠根據我迄今為止編寫的代碼提供更多詳細信息或示例.
Still new to android and even more to custom cursor adapter so I'm having trouble understanding how to prevent my listview from recycling views to prevent input from one edittext to show up in another when scrolled. I've seen on other post saying to change the name of convertview but how to do that I'm drawing a blank. I was hoping someone here would be able to give more details or example of how to do based of what code I've wrote so far.
public class editview extends ListActivity {
private dbadapter mydbhelper;
private PopupWindow pw;
public static int editCount;
public static ListView listView;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mydbhelper = new dbadapter(this);
mydbhelper.open();
View footer = getLayoutInflater().inflate(R.layout.footer_layout, null);
ListView listView = getListView();
listView.addFooterView(footer);
showResults();
}
//Populate view
private void showResults (){
Cursor cursor = mydbhelper.getUserWord();
startManagingCursor(cursor);
String[] from = new String[] {dbadapter.KEY_USERWORD};
int[] to = new int[] {R.id.textType};
ItemAdapter adapter = new ItemAdapter(this, R.layout.edit_row, cursor,
from, to);
adapter.notifyDataSetChanged();
this.setListAdapter(adapter);
editCount = adapter.getCount();
}
//footer button
public void onClick(View footer){
final MediaPlayer editClickSound = MediaPlayer.create(this, R.raw.button50);
editClickSound.start();
startActivity(new Intent("wanted.pro.madlibs.OUTPUT"));
}
//custom cursor adapter
class ItemAdapter extends SimpleCursorAdapter {
private LayoutInflater mInflater;
private Cursor cursor;
public ItemAdapter(Context context, int layout, Cursor cursor, String[] from,
int[] to) {
super(context, layout, cursor, from, to);
this.cursor = cursor;
mInflater = LayoutInflater.from(context);
}
static class ViewHolder {
protected TextView text;
protected EditText edittext;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.edit_row, null);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.textType);
holder.edittext = (EditText) convertView.findViewById(R.id.editText);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
cursor.moveToPosition(position);
int label_index = cursor.getColumnIndex("userword");
String label = cursor.getString(label_index);
holder.text.setText(label);
return convertView;
}
}
改成
class ItemAdapter extends SimpleCursorAdapter {
private LayoutInflater mInflater;
private Cursor cursor;
Map<Integer, String> inputValues = new HashMap<Integer, String>();
public View getView(final int position, View convertView, ViewGroup parent) {
....
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.edit_row, null);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.textType);
holder.edittext = (EditText) convertView.findViewById(R.id.editText);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
cursor.moveToPosition(position);
int label_index = cursor.getColumnIndex("userword");
String label = cursor.getString(label_index);
holder.text.setText(label);
String oldText = inputValues.get(position);
holder.edittext.setText(oldText == null ? "" : oldText);
holder.edittext.addTextChangedListener(new TextWatcher(){
public void afterTextChanged(Editable editable) {
inputValues.put(position, editable.toString());
}
但在所有edittext都有數據之后它正在回收.嘗試使用 holder.edittext.setText(oldText) 但效果相同.
but it is recycling after all edittext have data. Tried using holder.edittext.setText(oldText) but same effect.
推薦答案
首先,你真的不想阻止列表視圖回收它的視圖.視圖回收是一個巨大的優化.有關列表的許多非常好的信息,請參閱 google IO 演講:http://www.youtube.com/watch?v=wDBM6wVEO70
First of all, you really don't want to prevent a list view from recycling its views. View recycling is a huge optimization. For a lot of really good info on lists, see the google IO talk: http://www.youtube.com/watch?v=wDBM6wVEO70
話雖如此,您已經正確地確定了您的問題:您的 EditTexts 比您列表中的項目少得多.當您滾動瀏覽列表時,這些 EditTexts 會被回收,因此您會一遍又一遍地看到相同的輸入.
That being said, you've correctly identified your problem: You have far fewer EditTexts than you do items in your list. As the you scroll through the list those EditTexts are recycled so you see the same input over and over again.
基本上,您需要做的是將 EditTexts 的輸入保存在某些數據結構中(如果他們只編輯幾個值,則為 HashMap,如果他們將更改大部分值,則可能是 List,兩者都可以)映射輸入的位置.您可以通過將 textChangedListener 添加到 getView 中的編輯文本來做到這一點:
Basically what you need to do is save the input for your EditTexts in some datastructure (a HashMap if they will only edit a few values, maybe a List if they will be changing most of the values, either would work) that maps the position to the input. You can do this by adding a textChangedListener to your edit texts in getView:
@Override
public View getView(final int position, View convertView, ViewGroup parent){
...
cursor.moveToPosition(position);
int label_index = cursor.getColumnIndex("userword");
String label = cursor.getString(label_index);
holder.text.setText(label);
//clear whatever text was there from some other position
//and set it to whatever text the user edited for the current
//position if available
String oldText = yourMapOfPositionsToValues.get(position);
holder.setText(oldText == null ? "" : oldText);
//every time the user adds/removes a character from the edit text, save
//the current value of the edit text to retrieve later
holder.edittext.addTextChangedListener(new TextWatcher(){
@Override
public void afterTextChanged(Editable editable) {
yourMapOfPositionsToValues.put(position, editable.toString());
}
....
};
return convertView;
}
每當您的用戶完成編輯后,您就可以遍歷您的數據結構并對這些值執行任何操作.
Whenever your user is done editing, you can run through your datastructure and do whatever with those values.
我將 onTextChanged 更改為 afterTextChanged,因為我以前使用過它并且我知道它有效.請記住,每次 LETTER 更改時都會調用 afterTextChanged,而不僅僅是在用戶輸入完一個單詞之后.如果用戶鍵入dog" afterTextChanged 將被調用 3 次,首先是 'd',然后是 'do',然后是 'dog'.
I changed onTextChanged to afterTextChanged because I've used that before and I know it works. Keep in mind that afterTextChanged is called every time a LETTER changes, not just after the user finishes typing a word. If the user types "dog" afterTextChanged will be called three times, first with 'd', then with 'do', then with 'dog'.
HashMap 很簡單:Map yourMapOfPositionsToValues = new HashMap();
A HashMap is simple: Map yourMapOfPositionsToValues = new HashMap();
添加或更新項目:yourMap.put(position, someText);獲取項目:yourMap.get(position);
to add or update an item: yourMap.put(position, someText); to fetch an item: yourMap.get(position);
如果哈希圖沒有意義,請花一些時間研究它們.它們是非常重要的數據結構.
if hashmaps don't make sense, spend some time researching them. They are an incredibly important data structure.
您的 TextWatcher 實現不正確.您的數據結構不應屬于單個視圖,而應屬于活動或適配器.在您看來,職位并不穩定,因為您的 List 歸每個視圖所有.位置本身是穩定的,除非基礎數據發生變化,否則光標每次都會為相同的位置返回相同的數據.但是,編輯文本用于多個不同的位置.
Your TextWatcher implementation is incorrect. Your data structure should not belong to a single view, but rather the activity or your adapter. It appears to you that positions aren't stable because your List is owned by each view. The positions themselves are stable in that unless the underlying data changes the cursor will return the same data every time for the same position. However, the edit text is used for multiple different positions.
創建一個哈希圖作為我在上面在適配器的構造函數中演示的實例變量.然后正好加上我原來寫的TextWatcher,不需要命名類,匿名更簡單.您的代碼應該可以工作.
Create a hashmap as an instance variable I demonstrated above in the constructor of your adapter. Then add exactly the TextWatcher I wrote originally, no need for a named class, anonymous is simpler. Your code should work.
這篇關于ListView 中的 EditText 沒有它回收輸入的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!