所以,我有一个自定义适配器,每行都有两个EditText字段。
除了将值保存在ArrayList中之外,我已经让大部分内容正常工作。
这是我到目前为止所做的代码:
private void holderTitleSavedOnScroll(final int position, IZUICartViewHolder holder) {
if (!(position == (variantArrayList.size() - 1)) && holder.title != null) {
holder.title.setText(variantArrayList.get(position).getVariantTitle());
final int finalPosition = position;
holder.title.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
final EditText newVariant = (EditText) v;
variantArrayList.get(finalPosition).setVariantTitle(newVariant.getText().toString());
}
});
}
}
所以这实际上做了我想要的,它在焦点改变时保存了值。除了一个问题,它只在焦点改变时保存值。
大多数情况下这是很棒的,除非用户实际按下使整个视图消失的按钮。焦点永远不会改变,并且值不会被设置。
所以我猜你们都在想,是的,我们只需调用addOnTextChangedListener并附加一个TextWatcher,添加如下内容:
holder.title.setText(variantArrayList.get(position).getVariantTitle());
final int finalPosition = position;
final EditText holderTitle = (EditText) holder.title;
if (holderTitle.getTag() != null) {
final TextWatcher textWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
variantArrayList.get(finalPosition).setVariantTitle(s.toString());
}
@Override
public void afterTextChanged(Editable s) {
}
};
holder.title.addTextChangedListener(textWatcher);
holder.title.setTag(true);
}
不,那也行不通。 当然它实际上保存了值,但是当你滚动时它也会混乱,因为listview重用了它认为来自一个单元格的值在另一个单元格中的单元格,然后从ArrayList中设置值。
我尝试过不同的方法,例如在更改值和内容时检查焦点,但它不起作用(原因或多或少)。
有什么创意解决方案可以解决这个问题吗?
更新(使用更多代码):
建议的TextWatcher方法:
我的getView方法(这里有很多其他无关的问题代码):
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
IZUICartViewHolder holder;
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
if (v == null) {
holder = new IZUICartViewHolder();
int type = getItemViewType(position);
switch (type) {
case TYPE_EDIT:
v = inflater.inflate(R.layout.iz_ui_modify_product_cell, parent, false);
holder.title = (EditText) v.findViewById(R.id.iz_prod_modify_variant_title);
holder.title.setHint(addVariantPlaceholder);
holder.deleteButton = v.findViewById(R.id.click_remove);
holder.price = (EditText) v.findViewById(R.id.iz_prod_modify_price);
holder.price.setHint(pricePlaceholder);
holder.price.setText(String.valueOf(0.0));
break;
}
v.setTag(holder);
} else {
holder = (IZUICartViewHolder) v.getTag();
}
hideDeleteButton(holder, position);
holderTitleSavedOnScroll(position, holder);
holderPriceSavedOnScroll(position, holder);
v.setTag(holder);
return v;
}
holderTitleSavedOnScroll方法
private void holderTitleSavedOnScroll(final int position, IZUICartViewHolder holder) {
if (!(position == (variantArrayList.size() - 1)) && holder.title != null) {
holder.title.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
v.requestFocus();
}
});
final int finalPosition = position;
final EditText holderTitle = (EditText) holder.title;
if (holderTitle != null) {
holder.title.setText(variantArrayList.get(position).getVariantTitle());
}
holderTitle.addTextChangedListener(new EditVariantTextWatcher(variantArrayList.get(finalPosition)));
}
}
TextWatcher类:
public class EditVariantTextWatcher implements TextWatcher {
private IZUIProductVariantContainer variantContainer;
protected EditVariantTextWatcher(IZUIProductVariantContainer variantContainer) {
this.variantContainer = variantContainer;
}
@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) {
variantContainer.setVariantTitle(s.toString());
}
}
答案 0 :(得分:6)
这可以通过仔细使用TextWatchers来完成。
在ViewHolder中包含对当前TextWatcher的引用。当视图被回收时,删除现有的TextWatcher并添加一个新的,键入当前位置。
这是一个完整的工作示例,包括状态保存以允许测试导航:
public class EditTextListActivity extends ListActivity {
private static final String SAVED_STATE_KEY = "saved_state_key";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EditTextAdapter editTextAdapter = new EditTextAdapter(this, R.layout.main);
setListAdapter(editTextAdapter);
// Restore our state, if there is any
if (savedInstanceState != null) {
List<String> savedStrings = savedInstanceState.getStringArrayList(SAVED_STATE_KEY);
for (String savedString : savedStrings)
editTextAdapter.add(new ListItem(savedString));
} else {
// Add some empty items so that we can see it in action
for (int i = 0; i < 30; i++)
editTextAdapter.add(new ListItem(""));
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
ArrayList<String> arrayList = new ArrayList<String>();
EditTextAdapter editTextAdapter = (EditTextAdapter) getListAdapter();
for (int i = 0; i < editTextAdapter.getCount(); i++)
arrayList.add(editTextAdapter.getItem(i).string1);
outState.putStringArrayList(SAVED_STATE_KEY, arrayList);
}
/**
* The object we have a list of, probably more complex in your app
*/
static class ListItem {
public String string1;
ListItem(String string1) {
this.string1 = string1;
}
}
/**
* ViewHolder which also tracks the TextWatcher for an EditText
*/
static class ViewHolder {
public TextView textView;
public EditText editText;
public TextWatcher textWatcher;
}
class EditTextAdapter extends ArrayAdapter<ListItem> {
EditTextAdapter(Context context, int resource) {
super(context, android.R.layout.simple_list_item_single_choice);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
if (rowView == null) {
// Not recycled, inflate a new view
rowView = getLayoutInflater().inflate(R.layout.main, null);
ViewHolder viewHolder = new ViewHolder();
viewHolder.textView = (TextView) rowView.findViewById(R.id.textview);
viewHolder.editText = (EditText) rowView.findViewById(R.id.edittext1);
rowView.setTag(viewHolder);
}
ViewHolder holder = (ViewHolder) rowView.getTag();
// Remove any existing TextWatcher that will be keyed to the wrong ListItem
if (holder.textWatcher != null)
holder.editText.removeTextChangedListener(holder.textWatcher);
final ListItem listItem = getItem(position);
// Keep a reference to the TextWatcher so that we can remove it later
holder.textWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
listItem.string1 = s.toString();
}
@Override
public void afterTextChanged(Editable s) {
}
};
holder.editText.addTextChangedListener(holder.textWatcher);
holder.editText.setText(listItem.string1);
holder.textView.setText(Integer.toString(position));
return rowView;
}
}
}
layout/main.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"
android:orientation="horizontal">
<TextView
android:id="@+id/textview"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content" />
<EditText
android:id="@+id/edittext1"
android:layout_width="0dp"
android:layout_height="?android:attr/listPreferredItemHeightSmall"
android:layout_weight="2"
android:inputType="text" />
<!-- This EditText is included to demonstrate problems with a naive approach. -->
<EditText
android:inputType="text"
android:layout_width="0dp"
android:layout_height="?android:attr/listPreferredItemHeightSmall"
android:layout_weight="2" />
</LinearLayout>
已知错误:当键盘出现时,EditText将失去初始焦点,请参阅this answer以了解该问题。
答案 1 :(得分:0)
我们可以借助TextWatcher
最好使用模型来存储和检索EditText的值。
public class RowData {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
接下来是TextWatcher侦听器
public class EditTextWatcher implements TextWatcher {
private RowData data;
public EditTextWatcher(RowData data) {
this.data = data;
}
@Override
public void afterTextChanged(Editable s) {
data.setValue(s.toString());
}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
}
@Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
}
}
您的适配器类
public class YourAdapter extends ArrayAdapter<RowData> {
private ArrayList<RowData> data;
private Context context;
public YourAdapter(Context context, ArrayList<RowData> data) {
super(context, 0, data);
this.data = data;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
View v = convertView;
final RowData row = data.get(position);
final EditText edittext = (EditText) v.findViewById(R.id.edittext);
if (edittext != null)
edittext.setText(row.getValue());
edittext.addTextChangedListener(new EditTextWatcher(row));
///////Your Code
/////
}
}
//
edittext.addTextChangedListener(new EditTextWatcher(row));
此行将存储
每个EditText的数据,即使您在创建单元格时滚动ListView
它将从Model(RowData)
试试这样,希望这会对你有帮助。