2

私のプロジェクトでは、基本的に 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

問題を再現する手順は次のとおりです。

  1. プロジェクトをデバッグモードで起動する

  2. 最初の行 A に、2 番目の B に、3 番目の C に書きます

  3. C が非表示になるまで下にスクロールします

  4. 一番上までスクロールします。結果 : これ以上テキストはありません。

デバッグ ログをよく見ると、afterText の行が表示されます。パート 2 でテキストを記述するたびに、イベントの登録を含むデバッグ行が表示されます。

しかし、フェーズ 3 では、アイテムを非表示にします。イベントは「」で開始されます

結果: 4 番目のフェーズで、"" 文字列をロードします。

4

1 に答える 1

5

ほとんどのモバイル アプリ (Android iOS ...) で処理を高速化するために、通常、リストのセルは再利用されます。これにより、特に長いリストの場合にメモリが節約されます。したがって、新しく表示されたセルのデータを取得する必要があります。セルが画面の外に出ると、そのレイアウト/ビューは破棄されます。あなたの場合、編集テキストのテキストをどこかに保存する必要があります。それが、ハッシュマップでやろうとしていることです。

あなたのコードには特に間違いはありません。

質問がハッシュマップを使用する「回避策」に関するものである場合、編集テキストの状態を保存するのはあなた次第であることを確認します。ハッシュマップを使用することは、それを行う 1 つの方法です。

ちなみに、その目的のためにここにある whichgetItem(position).idに置き換えることができます。getItemId(position)

これがすべてあなたの質問に答えているかどうかはわかりません。

編集

あなたの質問を正しく理解したので、コードを提供できます。見つかったソリューションに完全に満足しているわけではありませんが、少なくとも機能していると言わざるを得ません。

TextWatcher の問題は、コンテキストと対応するビューにアクセスできないことです。

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());
        }
    }
}
于 2013-10-02T06:04:21.643 に答える