我有一个ExpandableListView。每个孩子都有一个CheckBox和一个TextView。当用户点击一个子行时,CheckBox应该改变其状态(选中或未选中)。如果用户直接点击复选框,此功能将正常工作。但是,如果用户点击文本视图(同一行,紧挨着复选框的右侧),只要尝试引用复选框,就会收到空指针错误。任何人都可以看到什么是错的?Android ExpandableListView在哪里放置onClickListener
编辑:在阅读下面的建议后,我做了一些调查,并意识到我可以在getChildView()我的适配器内实现我的clickListener。这解决了我对空指针的问题,因为我可以很容易地获得对子视图的引用。
但是,它造成了另一个问题,我看不到优雅的解决方案。每次点击一个孩子时,我需要对列表视图本身进行更改。此列表的数据位于范围在Activity内的ArrayList中(不在Adapter中)。如果我的clickListener在适配器中,我怎样才能回调活动来修改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" />
谢谢。我确实在适配器内设置了复选框的初始状态。这里我正在尝试处理onChildClick事件。除了切换复选框的状态之外,在解决空指针问题之后还需要执行其他处理。你是否说我应该在适配器内部进行此操作?我会在适配器中做什么?再次感谢! – Alex