3

私は現在、ある種のアイテムを表示するためにListViewを使用しています。複数のアイテムを選択し、Android4.xでうまく機能する大量に削除するアクションモードを実装しました。しかし、APIバージョン8または9(android 2.2.x / 2.3.x)で試したところ、選択は期待どおりに内部的に機能しますが、行アイテムはランダムに色付けされます。

ユーザーが最初の行を選択すると、内部的に最初の行が選択されますが、行番号4は色付きです。別の行をクリックすると、この行と最初の行が色付けされます。これは、4.xデバイスと同じように正常に動作すると予想される奇妙な動作です。

オーバーライドを長押ししてアクションモードをアクティブにし、ListViewの長クリック項目を確認します。

@Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int position, long id) {
    if (actionMode == null) {
        listView.setOnItemClickListener(new CABClickListener());
        actionMode = startActionMode(new ListActionMode());
        // Check item pressed with long click
        listView.setItemChecked(position, true);
        view.setBackgroundColor(checkedColor);
        logger.debug("Item at pos. " + position + ", checked.");
    }
    return true;
}

CABClickListenerは、ListViewの項目をチェック/チェック解除し、それらを内部的にマークし、その背景色を変更します。

private final class CABClickListener implements AdapterView.OnItemClickListener {
    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
        if (listView.isItemChecked(position)) {
            view.setBackgroundColor(checkedColor);
            logger.debug("Item at pos. " + position + ", checked.");
        } else {
            view.setBackgroundColor(uncheckedColor);
            logger.debug("Item at pos. " + position + ", unchecked.");
        }
    }
}

これらのクラス/メソッドはアクティビティ内にあり、そのlistView上で宣言されています。

その他の考慮事項:

  • ActionBarSherlock(CABが表示されますが、ここでは重要ではないと思います)とRoboguiceを使用しますが、問題はありません。
  • 私はいつもエミュレーターで開発していました。さらに、Android 3.xでアプリを試すことができなかったため(このバージョンで問題が発生し、エミュレーターが起動しません)、これらのバージョンで問題が解決するかどうかはわかりません。更新:android 3.0 API 11でテストされ、4.xでも正常に動作します。
  • コードをデバッグしましたViewが、両方のメソッドのsは問題ありませんが、呼び出すと view.setBackgroundColor(checkedColor);、別のメソッドがView色付きになります。

なにか提案を?誰もが助けてくれることを願っています!

4

1 に答える 1

3

うわー、問題は私自身の実装にありArrayAdapter、ビューホルダーパターンを適用しようとしました。単純なもので同じものをテストしたので、最初はこれを破棄しましたがArrayAdapter、問題はまだありました。

android APIの違いは、8-10 APIでアイテムをクリックすると、既存のビューを再利用してすべてのリストが再描画されることです。したがって、アイテム(ビュー)をクリックすると、これは色付きになりますが、すぐにandroidがすべてのリストを再描画し、ビューを再利用して、色付きのリストを別の位置にします。リストビューアイテムが>11APIでクリックされると、すべてが再描画され(はい、バージョン間のパフォーマンスが大幅に向上します)、正しいアイテムビューが正常に描画されます(適切に呼び出しますview.setBackgroundColor(checkedColor))。

最後に、この奇妙な動作を解決し、チェックされた状態をエンティティに保存しました。これにより、ビューを再利用する必要がある場合に、チェックされた値を復元し、リストアイテムを問題なく色付けすることができます。

GenericListAdapter.getView()メソッドを投稿し、興味のある人に関連しています。

GenericListAdapter<T>.getView()

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ItemViewHolder<T> viewHolder = null;

    if (convertView == null || !(convertView.getTag() instanceof ItemViewHolder<?>)) {
        logger.debug("New view: " + convertView + " at position: " + position);
        LayoutInflater mInflater = LayoutInflater.from(context);
        convertView = mInflater.inflate(resource, null);

        viewHolder = GenericViewHolderFactory.createInstance(clazz);
        viewHolder.setContext(context);
        viewHolder.saveViewContents(convertView);

        convertView.setTag(viewHolder);
    } else {
        logger.debug("Reusing view: " + convertView + ", at position: " + position);
        viewHolder = (ItemViewHolder<T>) convertView.getTag();
    }

    T entity = getItem(position);
    viewHolder.setViewFields(entity, convertView);

    return convertView;
}

そして、ViewHolderリサイクルされたビューを更新する実装:

public class EventItemViewHolder implements ItemViewHolder<Event> {

...

    @Override
    public void setViewFields(Event event, View convertView) {
        name.setText(event.getName());
        amount.setText(event.getTotalAmount().toString());

        if (event.isChecked()) {
            convertView.setBackgroundColor(checkedColor);
        } else {
            convertView.setBackgroundColor(uncheckedColor);
        }
    }
}

私は自分自身をうまく説明したと思います。

于 2012-07-27T18:44:17.607 に答える