在我的项目中,我必须向用户显示一个基本上包含 EditText 的 ListView。
这就像一份问卷,当他回答完问题后,他可以继续下去回答下一个问题。 (然后返回)
public class onAdapter extends BaseAdapter {
List<PointVerification> mObjects;
Context mContext;
LayoutInflater mInflater;
HashMap<Integer, List<ChoixPointVerification>> mChoix;
HashMap<Integer, ReponsePointVerification> mReponses;
HashMap<Integer, String> mReponsesActuel;
Integer mPositionSelectionne;
Integer mIdIntervention;
/**
* Constructeur
* @param context
* @param listePointsVerification Liste des points de vérification à afficher.
* @param listeChoixPointsVerification liste des choix de points de vérification pour chaque point de vérification.
* @param listeReponsesPointsVerification réponses déjà fournies pour chaque point de vérification
* @param idIntervention Identifiant de l'intervention
*/
public onAdapter(
Context context,
Integer idIntervention,
List<PointVerification> listePointsVerification,
List<ChoixPointVerification>> listeChoixPointsVerification,
ReponsePointVerification> listeReponsesPointsVerification) {
this.mInflater = LayoutInflater.from(context);
this.mContext = context;
this.mObjects = listePointsVerification;
this.mChoix = listeChoixPointsVerification;
this.mReponses = listeReponsesPointsVerification;
this.mIdIntervention = idIntervention;
// préparation des réponses par position
this.mReponsesActuel = new HashMap<Integer, String>();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row;
final Integer idPointVerification = getItem(position).id;
if (convertView == null)
{
row = mInflater.inflate(R.layout.intervention_reponses_controle_nombre, null);
EditText edValeur = (EditText) row.findViewById(R.id.edValeur);
// Ajout de l'évènement lorsque l'on change la valeur
// evènement d'enregistrement
edValeur.addTextChangedListener(new TextWatcher()
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void afterTextChanged(Editable s) {
// This hashmap is a try workaround to the bug
// i register all modifications into this hashmap
mReponsesActuel.put(
idPointVerification,
s.toString());
// SAVE PROCEDURE
// REMOVED FOR THE EXAMPLE
// BUT I UPDATE MY DATABASE
}
});
}
else
{
row = convertView;
}
EditText edValeur = (EditText) row.findViewById(R.id.edValeur);
// update of the text
// it is the contained in the hashmap
if (mReponsesActuel.containsKey(idPointVerification)) {
String valeur = mReponsesActuel.get(idPointVerification);
edValeur.setText(valeur);
// otherwhise i will look into the database
} else if (mReponses != null && mReponses.containsKey(idPointVerification)
&& mReponses.get(idPointVerification).valeur != null) {
edValeur.setText(mReponses.get(idPointVerification).valeur);
}
else
{
edValeur.setText("");
}
return row;
}
}
我不知道为什么,但是用户在ListView中向下移动,内容未保存并显示一些特殊值,例如其他EditText。我没有找到如何纠正这种行为,而且真的很匆忙。
基本上,我制作了一个 TextWatcher,它将数据注册到数据库中,并将数据注册到包含所有值的临时 HashMap 中。调用 GetView 时会回调该数据。如果我删除该初始化,EditText 将被删除。
注意:我在代码中做了一些测试,因此可能会出现不同的问题。
编辑
我上传了一个有问题的项目:http://dl.free.fr/rbqOhUfJF
以下是重现问题的步骤:
以 Debug模式启动项目
写在第一行A,第二行B,第三行C
向下滚动直到 C 隐藏
向上滚动到顶部。结果:没有更多文本。
如果仔细查看调试日志,您可以看到带有 afterText 的行。每次我们在第 2 部分中编写一些文本时,都会有一个带有事件注册的调试行。
但是在第 3 阶段,当你隐藏一个项目时。该 Activity 将以“”启动
结果:在第四阶段,加载“”字符串
最佳答案
为了加快大多数移动应用程序(Android iOS ...)中的速度,列表单元格通常会被回收。这可以节省内存,特别是对于长列表。因此,您必须获取新显示单元格的数据。当单元格移出屏幕时,其布局/ View 将被破坏。在您的情况下,您必须将编辑文本的文本保存在某处。这就是您尝试对 HashMap 执行的操作。
我在您的代码中没有发现任何特定错误。
如果问题是关于使用 HashMap 的“解决方法”,我确认对我来说,由您来保存编辑文本的状态。使用 HashMap 是实现此目的的一种方法。
顺便说一句,getItem(position).id
可以替换为 getItemId(position)
,这里就是为了这个目的。
不确定这是否能回答您的问题。
编辑
既然我正确理解了你的问题,我可以提供一些代码。我必须说,我对找到的解决方案并不完全满意,但至少它是有效的。
TextWatcher 的问题是您无法访问上下文和相应的 View 。
使用setOnFocusChangeListener解决了这个问题。这是我终于开始工作的代码。
public final class PointVerificationAdapter extends BaseAdapter {
List<BasicNameValuePair> mObjects;
Context mContext;
LayoutInflater mInflater;
HashMap<Integer, String> mReponsesActuel;
ArrayList<String> myItems = new ArrayList<String>();
public PointVerificationAdapter(
Context context,
List<BasicNameValuePair> listObjets
) {
this.mInflater = LayoutInflater.from(context);
this.mContext = context;
this.mObjects = listObjets;
for (int i = 0; i < 30; i++) {
myItems.add(Integer.toString(i));
}
}
@Override
public int getCount() {
return mObjects.size();
}
@Override
public BasicNameValuePair getItem(int position) {
return mObjects.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
static class ViewHolder {
EditText yourEditText;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null)
{
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.intervention_reponses_controle_nombre, parent, false);
convertView.setId(position);
holder.yourEditText = (EditText) convertView.findViewById(R.id.edValeur);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
((TextView) convertView.findViewById(R.id.tvNom)).setText(Integer.toString(position));
holder.yourEditText.setText(myItems.get(position));
holder.yourEditText.setId(position);
holder.yourEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
public void onFocusChange(View view, boolean hasFocus) {
if (!hasFocus){
final int position = view.getId();
final EditText editText = (EditText) view;
myItems.set(position, editText.getText().toString());
}
}
});
return convertView;
}
}
最终编辑
之前的代码可以工作,但我对此不满意,因为您要求的是 addTextChangedListener
而不是 onFocusChange
。
所以这是解决方案:
public final class PointVerificationAdapter extends BaseAdapter {
List<BasicNameValuePair> mObjects;
Context mContext;
LayoutInflater mInflater;
HashMap<Integer, String> mReponsesActuel;
ArrayList<String> myItems = new ArrayList<String>();
public PointVerificationAdapter(
Context context,
List<BasicNameValuePair> listObjets
) {
this.mInflater = LayoutInflater.from(context);
this.mContext = context;
this.mObjects = listObjets;
for (int i = 0; i < 30; i++) {
myItems.add(Integer.toString(i));
}
}
@Override
public int getCount() {
return mObjects.size();
}
@Override
public BasicNameValuePair getItem(int position) {
return mObjects.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
static class ViewHolder {
EditText yourEditText;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null)
{
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.intervention_reponses_controle_nombre, parent, false);
convertView.setId(position);
holder.yourEditText = (EditText) convertView.findViewById(R.id.edValeur);
holder.yourEditText.setId(position);
holder.yourEditText.addTextChangedListener(new GenericTextWatcher(holder.yourEditText));
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
holder.yourEditText.setId(position);
}
((TextView) convertView.findViewById(R.id.tvNom)).setText(Integer.toString(position));
holder.yourEditText.setText(myItems.get(position));
return convertView;
}
private class GenericTextWatcher implements TextWatcher{
private View view;
private GenericTextWatcher(View view) {
this.view = view;
}
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
public void afterTextChanged(Editable editable) {
final int position = view.getId();
final EditText editText = (EditText) view;
myItems.set(position, editText.getText().toString());
}
}
}
关于java - Android ListView 中包含的 EditText 内容未保存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19127524/