我正在撰写新的Android活动,但遇到ListFragment
时遇到问题。这里的想法是父活动托管ListFragment
,其数据是使用适配器从数据库中提取的。调用上下文操作栏(CAB)时,CheckBox
项(由ListView
托管的ListFragment
中每行的布局的一部分)变为可见。默认情况下,CheckBox
项不可见。在我的CheckBox
类MultiChoiceModeListener
方法中检查onItemCheckedStateChanged()
项。
我的目标是在屏幕方向改变时保留复选框的状态。
当方向在CAB激活时更改时,ListView的每一行中的CheckBox项(由ListFragment托管)变为不可见。我认为这是因为ListFragment
是通过onCreateView()
回调重新绘制的。
但是,我的问题是,当尝试重新启用复选框时,我收到一个NULL指针异常。何时从片段中访问行视图元素是否合适?如果我等待很长时间(即重新启用onItemCheckedStateChanged()
内部,这是不理想的,因为我不想重新点击所有内容!),可以访问该复选框并将其设置为可见。如果我尝试先从片段中访问它(例如在onCreateView()
或onViewCreated()
中),则复选框项为NULL,但行视图的其余部分不为空。
有什么建议吗?这是一些代码:
Null指针异常正在restoreSelectedCheckBoxes()
内抛出。这些行在下面标出。
来自家长Activity
// In the parent activity. Called from onCreate()
private void displayListViewTEMP() {
// add fragment to apropriate layout item, but do not overwrite!
FragmentTransaction fTrans;
FragmentManager fMan = getFragmentManager();
// fragContainer is null until something is added to it
if (fMan.findFragmentByTag(Activity_Home.NAME_LIST_FRAG_TAG) == null) {
Log.i(TAG, "Adding fragment to feed_list_container");
fTrans = fMan.beginTransaction();
fTrans.add(R.id.feed_list_container, new Name_List(), Activity_Home.NAME_LIST_FRAG_TAG);
fTrans.commit();
}
}
来自ListFragment
// this is the method I call to restore the checkboxes
public void restoreSelectedCheckBoxes() {
Log.i(TAG, "restoring selected button state");
ListView v = getListView();
// this variable holds the indices of selected items in the list
int selCnt = selectedListItems.size();
CheckBox bx;
for (int i = 0; i < selCnt; i++) {
Log.i(TAG, "v = " + v); <-- prints valid oref
bx = (CheckBox) v.findViewById(R.id.item_checkbox);
Log.i(TAG, "bx = " + bx); <-- prints 'null' after orientation change
bx.setChecked(true); <-- NULL pointer exception
}
}
以下是我用来设置CAB的数据:
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// omitted code to set up adapter
ListView listView = getListView();
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener(getChoiceListener());
}
// set up contextual action bar
private MultiChoiceModeListener getChoiceListener() {
if (this.choiceListener != null)
return this.choiceListener;
this.choiceListener = new MultiChoiceModeListener() {
@Override
// Inflate the menu for the CAB
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
Log.i(TAG, "Creating contextual action bar");
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.main_name_context, menu);
ListView v = getListView();
int vCnt = v.getCount();
View child;
CheckBox bx;
// set checkbox subviews as visible
for (int i = 0; i < vCnt; i++) {
child = v.getChildAt(i);
if (child == null)
continue;
bx = (CheckBox) child.findViewById(R.id.item_checkbox);
bx.setVisibility(View.VISIBLE);
}
return true;
}
// omitted other overridden methods that aren't relevant
};
return this.choiceListener;
}
* 非常感谢您的帮助!解决方案确实是按照建议覆盖适配器。查看最终代码:*
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = super.getView(position, convertView, parent);
if (selectedListItems.contains(position)) {
CheckBox bx = (CheckBox) v.findViewById(R.id.item_checkbox);
bx.setVisibility(View.VISIBLE);
bx.setChecked(true);
}
return v;
}
答案 0 :(得分:2)
您使用哪种适配器进行ListFragment?
我会通过扩展ArrayAdapter(或者你现在正在使用的任何东西)创建一个适配器类,并将状态恢复逻辑添加到adapter.getView()方法,而不是试图等待你的视图完成布局等。
如果您不确定如何扩展ArrayAdapter,请参阅此帖子:How can I make my ArrayAdapter follow the ViewHolder pattern?
答案 1 :(得分:-1)
试试这个:
getView().post(new Runnable() {
@Override
public void run() {
// code you want to run when view is visible/inflated for the first time
}
}
);