ListFragment视图何时完全膨胀?上下文操作栏的问题

时间:2014-03-07 18:44:47

标签: android checkbox

我正在撰写新的Android活动,但遇到ListFragment时遇到问题。这里的想法是父活动托管ListFragment,其数据是使用适配器从数据库中提取的。调用上下文操作栏(CAB)时,CheckBox项(由ListView托管的ListFragment中每行的布局的一部分)变为可见。默认情况下,CheckBox项不可见。在我的CheckBoxMultiChoiceModeListener方法中检查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;
}

2 个答案:

答案 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
    }
 }
);