私は ExpandableListView を持っています。各子には CheckBox と TextView があります。ユーザーが子行をタップすると、CheckBox はその状態 (チェック済みとチェックなし) を変更することになっています。ユーザーがチェック ボックスを直接タップすると、これは正しく機能します。ただし、ユーザーがテキスト ビュー (同じ行、チェック ボックスのすぐ右) をタップすると、チェック ボックスを参照しようとするとすぐに null ポインター エラーが発生します。誰が何が間違っているかを見ることができますか?
編集: 以下の提案を読んだ後、いくつかの調査を行い、getChildView() の下のアダプター内に clickListener を実装できることに気付きました。これにより、子ビューへの参照を簡単に取得できるため、null ポインターに関する問題が解決されます。
ただし、これにより、エレガントな解決策が見当たらない別の問題が発生します。子がクリックされるたびに、リストビュー自体を変更する必要があります。このリストのデータは、スコープが (アダプタではなく) アクティビティ内にある ArrayList に存在します。clickListener が Adapter にある場合、Activity にコールバックして ArrayList を変更するにはどうすればよいですか?
これはキャッチ22のように私を襲います。データを操作できるようにしたい場合、子ビューへの参照を取得できません。しかし、子ビューへの参照が必要な場合、データは範囲外であるため、操作できません。人々はこれをどのように解決しますか?私は何かが欠けているに違いない。
子 onClickListener を追加しようとする私の試みの始まりを確認できる関連するアダプター コードを挿入します。
再度、感謝します!
public class Settings extends Activity {
//this is the list I need to access from the adapter if my click listener is there
private ArrayList<Categories> categoriesList = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_smart_settings);
db = new EventsDB(this);
expListGroups = new ArrayList<ExpandListGroup>();
setGroups();
/* Set up the data adapter */
expAdapter = new ExpandListAdapter(Settings.this, expListGroups);
populateExpandableGroups();
}
public void setGroups() {
/* Create lists of the individual line items */
categoriesList = db.getCategoriesForClient(client);
locationsList = db.getLocationsForClient(client);
/* Add an item to the locations list to allow the user to add a new location */
locationsList.add(new ClientSmartFinderLocations(client, "Add Location", null, false));
ExpandListGroup categoryGroup = new ExpandListCategory("Choose Categories", categoriesList);
ExpandListGroup locationGroup = new ExpandListLocation("Choose Locations", locationsList);
expListGroups.add(categoryGroup);
expListGroups.add(locationGroup);
}
private void populateExpandableGroups() {
expandableList = (ExpandableListView) findViewById(R.id.expandable_list);
expandableList.setAdapter(expAdapter);
//I've removed this section and moved it to the adapter, per my edit above
// expandableList.setOnChildClickListener(new OnChildClickListener() {
//
// @Override
// public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
//
// /* Update the finder setting for this client */
// String category = categoriesList.get(childPosition).getCategory();
// Boolean isSelected = !categoriesList.get(childPosition).getIsSelected();
// db.setClientCategory(client, category, isSelected);
//
// /* Update the check box to provide feedback to the user */
// View view = parent.getChildAt(childPosition - parent.getFirstVisiblePosition() + 1);
// CheckBox checkBox = (CheckBox) view.findViewById(R.id.check_box);
//
// //error occurs here
// checkBox.setChecked(!checkBox.isChecked());
// return true;
// }
// });
expAdapter.notifyDataSetChanged();
}
public class ExpandListAdapter extends BaseExpandableListAdapter {
//other methods
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View view, final ViewGroup parent) {
view = getCategoryChildView(groupPosition, childPosition, view);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TextView tv = (TextView) v.findViewById(R.id.expand_list_item);
CheckBox checkBox = (CheckBox) v.findViewById(R.id.check_box);
String category = tv.getText().toString();
Boolean isSelected = !checkBox.isSelected();
db = new EventsDB(context);
db.setClientCategory(client, category, isSelected);
checkBox.setChecked(!checkBox.isChecked());
//here I need to do some things that require me to manipulate the categoriesList from the Activity class - but it is out of scope
}
});
return view;
}
}
<CheckBox
android:id="@+id/check_box"
android:layout_marginLeft="30dp"
android:focusable="false"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/expand_list_item"
android:paddingLeft="10dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="@dimen/smart_finder_settings_font_size"
android:textColor="#FFFFFF" />