2

私の Android アプリケーションでは、項目をリストに表示したいと考えています。このために、listView を使用しています。リスト項目はテキスト (名前) と editText (数量) で構成されているため、カスタム ArraryAdapter を使用しています。ユーザーが数量を変更できるようにしたいので、私は editText を使用しています。ユーザーが編集を停止したときに、新しい値を保存したいので、editTexts に onTextChanged イベントを追加しました。

アイテムのクラスを作成しました(リストに表示しています)。とてもシンプルで、名前と数量のみです。

public class Foo {
    final String name;
    int quantity;

    public Foo (String name, int quantity) {
        this.name = name;
        this.quantity = quantity;
    }

    // for debug message
    @Override
    public String toString () {
        return "name: " + this.name+ " quantity: " + this.quantity;
    }
}

メイン アクティビティの onCreate メソッドで、Foo 要素のリストを作成し、独自の Adapter を使用してそれらをリストに追加します。

public class MainActivity extends Activity {
    ListView list;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        list = (ListView) findViewById (R.id.list);
        List<Foo> elements = new ArrayList<Foo> ();
        elements.add(new Foo ("foo", 1));
        elements.add(new Foo ("bar", 2));
        elements.add(new Foo ("baz", 3));
        elements.add(new Foo ("foo2", 4));
        elements.add(new Foo ("bar2", 5));
        elements.add(new Foo ("baz2", 6));

        FooAdapter adapter = new FooAdapter (this, R.layout.foo_elements, elements);
        //where foo_elements contains a horizontal LinearLayout and in it
        //there's a TextView and an EditText
        list.setAdapter(adapter);
    }

したがって、私のアダプターは次のとおりです (ここでホルダー パターンを見つけました: http://www.vogella.com/articles/AndroidListView/article.html#adapterperformance_hoder ):

public class FooAdapter extends ArrayAdapter<Foo> {
    Context context;
    int layoutResourceId;
    List<Foo> elements;

    public FooAdapter (Context context, int layoutResourceId, List<Foo> elements) {
        super (context, layoutResourceId, elements);
        this.context = context;
        this.layoutResourceId = layoutResourceId;
        this.elements = elements;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View row = convertView;
        Holder holder = null;

        final Foo item = elements.get(position);

        if (row == null) {
            LayoutInflater inflater = ((Activity)context).getLayoutInflater ();
            row = inflater.inflate(layoutResourceId, parent, false);

            holder = new Holder ();
            holder.name = (TextView) row.findViewById (R.id.name);
            holder.quantity = (EditText) row.findViewById(R.id.quantity);

            holder.quantity.addTextChangedListener(new TextWatcher() {

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                    // TODO Auto-generated method stub
                }

                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                    // TODO Auto-generated method stub
                }

                @Override
                public void afterTextChanged(Editable s) {
                    Log.d("textchanged", "text has changed");
                    Log.d ("new text", s.toString());
                    item.quantity = Integer.parseInt(s.toString());
                }
            });

            row.setTag(holder);
        }
        else {
            holder = (Holder) row.getTag();
        }

        holder.name.setText (item.name);
        holder.quantity.setText (String.valueOf(item.quantity));

        return row;
    }

    class Holder {
        TextView name;
        EditText quantity;
    }
}

ご覧のとおり、textchanged イベントをリッスンするために TextWatcher を使用し、afterTextChanged 関数で新しい数量を Foo オブジェクトに設定したいと考えています。

そこで何が起こっているかを確認するためにいくつかのデバッグ メッセージを入れ、Foo オブジェクトを印刷するボタンを追加しました。アプリケーションを起動した後の出力は次のとおりです。

textchanged      text has changed
new text         1
textchanged      text has changed
new text         2
textchanged      text has changed
new text         3
textchanged      text has changed
new text         4
textchanged      text has changed
new text         5
textchanged      text has changed
new text         6
textchanged      text has changed
new text         6
textchanged      text has changed
new text         2
textchanged      text has changed
new text         3
textchanged      text has changed
new text         4
textchanged      text has changed
new text         5
textchanged      text has changed
new text         6

したがって、プログラムを起動した後の数量は次のとおりです。

name: foo quantity: 6 //instead of name: foo quantity: 1
name: bar quantity: 2
name: baz quantity: 3
name: foo2 quantity: 4
name: bar2 quantity: 5
name: baz2 quantity: 6

最後の要素を変更すると、最初の要素も変更されます。

name: foo quantity: 62 //instead of name: foo quantity: 1
name: bar quantity: 2
name: baz quantity: 3
name: foo2 quantity: 4
name: bar2 quantity: 5
name: baz2 quantity: 62

私は Android (Java でさえも) を初めて使いましたが、自分のせいではありませんでした。何か考えはありますか?そして、なぜこれほど多くのテキスト変更イベントが発生するのでしょうか? それはどのように機能しますか?listView の使い方は間違っていますか? 前もって感謝します。

4

1 に答える 1

0

あなたの問題はここだと思います。

item.quantity = Integer.parseInt(s.toString());

item 変数は、そこにある必要はありません。この投稿を参照してください: Android SimpleAdapter wrong data-item gets associated with a list rowは、getView を 1 回ではなく呼び出すことができ、ビューを再利用できることを示しています。ここで名前と値を設定することで、それを正常に実装できます。

holder.name.setText (item.name);
holder.quantity.setText (String.valueOf(item.quantity));

ただし、EditText ではできません。タグを編集ビューに設定するか、別の方法でアイテムを取得して修正してください。

それが役立つことを願っています。

于 2013-01-02T09:32:21.680 に答える