包含在 Android ListView 中的 EditText 的内容未保存 [英] The content of EditText contained into a Android ListView isn't saved

查看:20
本文介绍了包含在 Android ListView 中的 EditText 的内容未保存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的项目中,我必须向用户显示一个基本上包含 EditText 的 ListView.

On my project I have to show to the user a ListView which is contained basically of EditText.

这就像一个问卷,当他回答了一个问题时,他可以往下回答下一个问题.(然后回去)

It is like a questionnaire, when he answer to the question he can go down and answer to the next question. (and go back)

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.我没有找到如何纠正这种行为,而且真的很着急.

I don't know why but the user go down in the ListView, the content is unsaved and show some special values like others EditText. I didn't find how to correct that behaviour and it's really in a hurry.

基本上,我制作了一个 TextWatcher,它将数据注册到数据库中,并将数据注册到一个包含所有值的临时 HashMap.调用 GetView 时会回调该数据.如果我删除该初始化,则 EditText 将被删除.

Basically I made a TextWatcher which register data into the database and also into a temporary HashMap which contains all values. That data is called back when GetView is called. If I remove that initialisation, the EditText is erased.

注意:我在我的代码中做了一些测试,所以可能会有不同的问题.

Note : I made some test in my code so there may be different problem.

编辑

我上传了一个有问题的项目:http://dl.free.fr/rbqOhUfJF

I uploaded a project with the problem : http://dl.free.fr/rbqOhUfJF

这里是重现问题的步骤:

Here the steps to reproduce the problem :

  1. 在调试模式下启动项目

  1. launch the project in debug mode

写在第一行A,第二行B,第三行C

write in the first row A, in the second B, in the third C

向下滚动直到隐藏 C

向上滚动到顶部.结果:没有更多文本.

scroll up to the top. Result : There is no more text.

如果您仔细查看调试日志,您可以看到带有 afterText 的行.每次我们在第2部分写一些文字,都会有一个调试行,记录事件的注册.

If you look closely on the debug log you can see line with afterText. Each times we write some text in the part 2, there will be a debug line with the registration of the event.

但是在第 3 阶段,当您隐藏项目时.活动将以"

But at the phase 3, when you hide an item. the event will be launched with ""

结果:在第 4 阶段,它加载了 "" 字符串

Result : in the 4th phase, it loads the "" string

推荐答案

为了加快大多数移动应用程序 (Android iOS ...) 中的处理速度,通常会回收列表单元格.这可以节省内存,特别是对于长列表.因此,您必须获取新显示单元格的数据.当单元格离开屏幕时,它的布局/视图被破坏.在您的情况下,您必须将编辑文本的文本保存在某处.这就是您要对哈希图执行的操作.

To speed up things in most mobile apps (Android iOS ...) cells of lists are usually recycled. This spares memory especially for long lists. Therefore you have to get the data of a new displayed cell. When the cell goes outside the screen, its layout/view is destroyed. In your case you have to save the text of the edit text somewhere. That's what you are trying to do with the hashmap.

我没有在您的代码中看到任何特别的错误.

I don't see any particular mistake in your code.

如果问题是关于使用哈希图的解决方法",我确认对我来说,保存编辑文本的状态取决于您.使用哈希图是一种方法.

If the question is about the "workaround" of using the hashmap, I confirm that for me it is up to you to save the states of the edit text. Using a hashmap is one way of doing it.

顺便说一下,getItem(position).id 可以被替换为 getItemId(position),这是为了这个目的.

By the way getItem(position).id can be replaced by getItemId(position) which is here for that purpose.

不确定所有这些是否能回答您的问题.

Not sure if all this answers your question.

编辑

既然我正确理解了您的问题,我可以提供一些代码.我必须说,我对找到的解决方案并不完全满意,但至少它是有效的.

Now that I understood your question correctly I can provide some code. I must say that I am not fully happy with the solution found but at least it is working.

TextWatcher 的问题在于您无法访问上下文和相应视图.

The problem with the TextWatcher is that you have no access to the context and of the corresponding view.

使用 setOnFocusChangeListener 解决了这个问题.所以这是我终于开始工作的代码.

Using setOnFocusChangeListener solved the problem. So here is the code I finally got working.

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.

The previous code is working but I wasn't happy with it because you asked for addTextChangedListenerand not for 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());
        }
    }
}

这篇关于包含在 Android ListView 中的 EditText 的内容未保存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆