2種類のアイテムを表示するListViewがあります。これらの種類の1つには、CheckedTextViewが含まれています。アダプターとして、内部のチェック済み/非チェック状態に関する情報を含むデータ構造を持つArrayAdapterを拡張するカスタムアダプターを使用しています。
一部のアイテムは(私のデータ構造で)選択済みとしてマークされているので、もちろん、ListViewの作成時にチェックボックスをマークしたいと思います。 CheckedTextViewのsetChecked()メソッドを使用してアダプターのgetView()メソッドでそれを実行しようとしましたが、機能しません。 setItemChecked()を使用してListViewレベルで実行する必要があるという情報を見つけましたが、機能しますが、機能させるには、setItemChecked()を呼び出すアクティビティのonCreate()内のすべてのアイテムをループする必要があるため、意味がありません。選択されたもののために。アイテムのリストは非常に長く、そのうちのいくつかしか選択されていない可能性があるため、無駄です。
GetView()でsetChecked()を呼び出すことが機能しないのはなぜですか?これを行うためのより良い方法はありますか(私はAndroid初心者です)。
以下に私のチェック項目のレイアウトとアダプターがあります。
レイアウト:
<?xml version="1.0" encoding="utf-8"?>
<CheckedTextView xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@Android:id/text1"
Android:layout_width="fill_parent"
Android:layout_height="?android:attr/listPreferredItemHeight"
Android:gravity="center_vertical"
Android:textAppearance="@style/listViewItemText"
Android:checkMark="?android:attr/listChoiceIndicatorMultiple"
Android:paddingLeft="6dp"
Android:paddingRight="6dp"
/>
アダプタ:
package com.melog.re.droid.search;
import Java.util.ArrayList;
import Java.util.List;
import Android.content.Context;
import Android.os.Parcel;
import Android.os.Parcelable;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.ViewGroup;
import Android.widget.ArrayAdapter;
import Android.widget.CheckedTextView;
import Android.widget.TextView;
import com.melog.re.droid.core.R;
import com.melog.re.droid.search.MultiCriterionValue.MultiCriterionSingleValue;
import com.melog.re.droid.search.MultiListAdapter.MultiChoiceItem;
public class MultiListAdapter extends ArrayAdapter<MultiChoiceItem> {
private static final int VIEW_TYPES_COUNT = 2;
public static final int VIEW_TYPE_GROUP = 0;
public static final int VIEW_TYPE_ITEM = 1;
private LayoutInflater mInflater;
public MultiListAdapter(Context context, int textViewResourceId, List<MultiChoiceItem> objects) {
super(context, textViewResourceId, objects);
mInflater = LayoutInflater.from(context);
}
@Override
public int getItemViewType(int position) {
MultiChoiceItem item = getItem(position);
return (item.children.size() == 0) ? VIEW_TYPE_ITEM : VIEW_TYPE_GROUP;
}
@Override
public int getViewTypeCount() {
return VIEW_TYPES_COUNT;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO: optymalizacja ViewHolder
MultiChoiceItem item = getItem(position);
int viewType = getItemViewType(position);
switch (viewType) {
case VIEW_TYPE_GROUP:
if (convertView == null) {
convertView = mInflater.inflate(R.layout.multi_choice_group_item, parent, false);
}
TextView groupLabel = (TextView) convertView.findViewById(Android.R.id.text1);
groupLabel.setText(item.toString());
break;
case VIEW_TYPE_ITEM:
if (convertView == null) {
convertView = mInflater.inflate(R.layout.multi_choice_child_item, parent, false);
}
CheckedTextView itemLabel = (CheckedTextView) convertView.findViewById(Android.R.id.text1);
itemLabel.setText(item.toString());
itemLabel.setChecked(item.selected);
break;
}
return convertView;
}
public static class MultiChoiceItem implements Parcelable {
public static final int CONTENTS_DESCR = 1;
public String label;
public String value;
public boolean selected = false;
public ArrayList<MultiChoiceItem> children = new ArrayList<MultiChoiceItem>();
public MultiChoiceItem(String l, String v, boolean sel) {
label = l;
value = v;
selected = sel;
}
public MultiChoiceItem(MultiCriterionSingleValue v) {
label = v.toString();
value = v.value;
}
public MultiChoiceItem(Parcel in) {
label = in.readString();
value = in.readString();
selected = (in.readInt() == 1);
}
@Override
public String toString() {
return label;
}
@Override
public int describeContents() {
return CONTENTS_DESCR;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(label);
dest.writeString(value);
dest.writeInt(selected ? 1 : 0);
}
public static final Parcelable.Creator<MultiChoiceItem> CREATOR = new Parcelable.Creator<MultiChoiceItem>() {
public MultiChoiceItem createFromParcel(Parcel in) {
return new MultiChoiceItem(in);
}
public MultiChoiceItem[] newArray(int size) {
return new MultiChoiceItem[size];
}
};
}
}
そして、アクティビティのonCreate()
...
mAdapter = new MultiListAdapter(this, R.id.head, mItems);
setListAdapter(mAdapter);
final ListView listView = getListView();
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
listView.setItemsCanFocus(false);
...
編集:
より良い解決策が見つかるまで、アクティビティでチェックを実装しました。
...
int len = mListView.getCount();
for (int i = 0; i < len; i++) {
if (((MultiChoiceItem) mListView.getItemAtPosition(i)).selected) {
mListView.setItemChecked(i, true);
}
}
...
パフォーマンスが唯一の潜在的な問題になると思いましたが、別の問題を見つけました-はるかに深刻です。リストでテキストフィルターが有効になっています(mListView.setTextFilterEnabled(true))。失敗のシナリオは次のとおりです。
SetItemChecked()は、チェックされたリストの固定位置をマークしていると思いますが、その位置に保持されているアイテムをマークするものが必要です。リストの位置が変わっても状態を維持します。
パフォーマンスの問題は(ある程度は)無視できますが、この新しい問題は本当に私をブロックしているので、助けていただければ幸いです。
ListView.CHOICE_MODE_MULTIPLE
またはCHOICE_MODE_SINGLE
を使用する場合、アイテムのチェック状態は、getView
が呼び出された後にListViewによってオーバーライドされます。次の構成を使用する必要があります。
@Override
public View getView(int position, View convertView, ViewGroup parent) {
((ListView)parent).setItemChecked(position, true);
}
もう1つの可能性は、ListView.CHOICE_MODE_NONE
を使用して、チェック状態を自分で管理することです。