0

Edit3: 完全に実行可能なテスト ケースのコードを交換しました。

Edit2: 5 秒後にボタンの数を更新するコードを追加しました。これが発生すると、使用するレイアウトに関係なく、ボタンをクリックできなくなります。

Edit1:これは、ListView に使用されるレイアウトに依存しているようです。さらに調査します。

ボタンを一度作成したい、つまりキャッシュしたい。提供された convertView を使用して、さまざまな理由で編集することはできません (最終的にすべての行には、別のフレームワークによって作成されたいくつかのコンポーネントが含まれます)。

以下のようなアダプターを作成すると、非常に合理的で、imo が機能するはずです。ListView の外側にあり、スクロールして戻ったボタンのみがクリック可能になります。

ボタンのクリック可能領域が最初の表示で正しく設定されていないようです。誰でも理由を説明できますか?

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Timer;
import java.util.TimerTask;

public class TestActivity extends Activity
{
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        final ListView listView = new ListView(this);

        final ArrayList<View> cachedButtons = new ArrayList<View>(Arrays.asList(new View[20]));

        listView.setAdapter(new BaseAdapter() {
            public View getView(int position, View convertView, ViewGroup parent)
            {
                if (cachedButtons.get(position) == null) {
                    Button b = new Button(parent.getContext());
                    b.setText("Button " + position);
                    b.setClickable(true);
                    cachedButtons.set(position, b);
                }
                return cachedButtons.get(position);
            }

            public int getCount() { return cachedButtons.size(); }
            public Object getItem(int position) { return null; }
            public long getItemId(int position) { return position; }
        });

        // Add a new button after five seconds
        new Timer().schedule(new TimerTask() {
            public void run()
            {
                runOnUiThread(new Runnable() {
                    public void run()
                    {
                        cachedButtons.addAll(Arrays.asList(new View[1])); // Add one more
                        ((BaseAdapter) listView.getAdapter()).notifyDataSetChanged();
                        Toast.makeText(listView.getContext(), "Now you can't press the buttons anymore", 0).show();
                    }
                });
            }
        }, 5000);

        // Doesn't work with these lines
        LinearLayout layout = new LinearLayout(this);
        layout.addView(listView);
        setContentView(layout);

        // Works with this, so no Layout works.
        //setContentView(layout);
    }
}
4

2 に答える 2

2

Androidがビューを再利用しているため、問題が発生していると思います。ビューホルダーを使用することをお勧めします。これは、ビューを保持する静的クラスです。このチュートリアルを参照してください。

于 2012-04-15T12:41:10.653 に答える
2

答えは非常に単純でしたが、何時間も私を逃しました。getItemViewType をオーバーライドするだけで、ビューはリサイクルされません。少なくとも今のところは機能しているようです。私はまだJavaDocsがこれについて混乱していると思います。

public int getItemViewType(int position)
{
    return AdapterView.ITEM_VIEW_TYPE_IGNORE;
}
于 2012-04-15T15:18:05.180 に答える