6

我正在使用ViewPagerACL 来显示几个Fragments. 起初,这些 Fragments 中的所有ListFragments 都包含一个列表。我试图模仿一个 2 列的表,因此列表中的每个元素都包含另一个包含两个对象的列表。我希望每个单元格都可以长按(而不是整个列表项),因此我实现了自己的 ColumnLayout(也许它应该称为 CellLayout)。每个列表项包含两个可长按的 ColumnLayout,并实现getContextMenuInfo()返回有关长按哪个实体的信息。此方法查找 ViewPager,请求当前片段,然后调用片段以从长按视图返回实体 id。为了获得正确的行,片段需要做:

getListView().getPositionForView(v)

这就是问题开始的地方。有时会getListView()抛出IllegalStateException“尚未创建内容视图”。即onCreateView(...)没有被调用。这仅在应用程序恢复时才会发生。今天,我通过在我的 Galaxy Nexus 上启用“设置”>“开发人员”选项中的“不保留活动”选项,设法重现了这个问题。我启动应用程序,按主页,然后从最近的应用程序菜单重新打开应用程序,现在,如果我长按列表视图中的任何单元格,则会引发此异常。通过一些调试输出,我设法验证从未调用过 onCreateView。这有点奇怪,因为整个 ViewPager 及其 Fragment 及其 ListView 及其单元格项都已绘制!

我在#android-dev 上被告知ListFragment在 ACL 中不支持自定义布局,所以我在android.support.v4.app.Fragment不使用的情况下重新实现了我的布局,ListFragment但这并没有帮助。

简短摘要:我有一个自定义布局,它处理长按布局的事件,目的是创建一个MenuInfo对象,其中包含有关按下的单元格中实体的信息。为了找到布局中包含的实体,listview.getPositionForView(View v)最终会调用,有时会导致IllegalStateException.

ViewPager这是我的自定义布局(也许比在视图层次结构中挖掘更容易掌握):

package org.remotestick;

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View;
import android.widget.LinearLayout;

public class ColumnLayout extends LinearLayout {

    public ColumnLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ColumnLayout(Context context) {
        super(context);
    }

    @Override
    protected ContextMenuInfo getContextMenuInfo() {
        int itemTypeId = getChildAt(0).getId();
        int positionTypeId = getId();
        View currentView = this;
        ViewPager viewPager = null;
        while(currentView.getParent() != null) {
            currentView = (View) currentView.getParent();
            if(currentView.getId() == R.id.pager) {
                viewPager = (ViewPager) currentView;
                break;
            } else if (currentView.getId() == R.id.rootLayout)
                break;
        }
        if(viewPager == null)
            return null;

        WorkspaceAdapter adapter = (WorkspaceAdapter) viewPager.getAdapter();
        Pair<Integer, Integer> itemIdAndListPosition = adapter.getItemIdFromWorkspace(viewPager.getCurrentItem(), this, itemTypeId, (positionTypeId == R.id.leftColumn));
        if(itemIdAndListPosition == null)
            return null;
        else
            return new MatrixAdaptableContextMenuInfo(itemTypeId, itemIdAndListPosition.first, itemIdAndListPosition.second);
    }

    public static class MatrixAdaptableContextMenuInfo implements ContextMenuInfo {

        public final int itemTypeId;
        public final Integer itemId;
        public final Integer positionInList;

        public MatrixAdaptableContextMenuInfo(int itemTypeId, Integer itemId, Integer positionInList) {
            this.itemTypeId = itemTypeId;
            this.itemId = itemId;
            this.positionInList = positionInList;
        }

    }
}

这是(片段)Fragment

public class EntityTableFragment extends Fragment implements TelldusEntityChangeListener {

    protected static final String ARG_TITLE = "title";

    protected MatrixAdapter mAdapter;
    protected ProgressViewer mProgressViewer;
    protected MatrixFilter mFilter;
    protected Handler mHandler = new Handler();
    protected RemoteStickData db;

    public boolean onAttach = false;
    public boolean onCreateView = false;

    private ListView listView;

    public static EntityTableFragment newInstance(String title) {
        EntityTableFragment f = new EntityTableFragment();

        Bundle args = new Bundle();
        args.putString(ARG_TITLE, title);
        f.setArguments(args);
        return f;
    }

    @Override
    public void onAttach(SupportActivity activity) {
        super.onAttach(activity);
        onAttach = true;
            try {
            mProgressViewer = (ProgressViewer) activity;
            mAdapter = new MatrixAdapter(getActivity(), mProgressViewer, new ArrayList<List<MatrixEntity>>(), null);
            TelldusLiveService.addListener(this);
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement ProgressViewer");
        }
        db = new RemoteStickData(getActivity());
    }

    @Override
    public void onDetach() {
        super.onDetach();
        TelldusLiveService.removeListener(this);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        listView.setAdapter(mAdapter);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.list, null);
        listView = (ListView) view.findViewById(R.id.list);
        return view;
    }

    @Override
    public String toString() {
        return getArguments().getString(ARG_TITLE);
    }

    public Pair<Integer, Integer> getIdAndPositionForView(View v, boolean isLeft) {
        if(listView == null)
            throw new IllegalStateException("Listview not yet created");
        int positionForView = listView.getPositionForView(v);
        if(isLeft)
            return new Pair<Integer, Integer>(mAdapter.getItem(positionForView).get(0).getId(), positionForView);
        else
            return new Pair<Integer, Integer>(mAdapter.getItem(positionForView).get(1).getId(), positionForView);
    }

这不是很奇怪,当恢复应用程序时(如果活动被破坏),ViewPager 及其 Fragments 和它的 ListView 以及它的自定义布局都被绘制出来。然而,IllegalStateException如果我长按列表视图中的任何单元格,我会说视图尚未创建?

编辑/实际上,Log.d(Constants.TAG, "onCreateView!!!!");输出onCreateView显示我第一次启动应用程序时调用了两次方法(ViewPager 中的每个 Fragment 调用一次),但是当应用程序恢复时它再也不会被调用!?这是一个错误还是我做错了什么?

4

3 回答 3

5

重要的部分似乎是FragmentPagerAdapter(我没有包括在内)。调试显示getItem()重新创建活动时未调用。片段是通过其他方式重新创建的。这意味着我的实现FragmentPagerAdapterFragmentManager.

因此,当我需要查找片段时,我使用findFragmentByTag()(在 上FragmentManager)使用makeFragmentName()来获取适当的标签名称。FragmentPagerAdapter这是添加片段时使用的方法。不确定这是否是一种安全的方法。

于 2012-01-19T12:17:20.177 回答
1

使用getChildFragmentManager()而不是getFragmentManager()

例子:

new ViewPagerAdapter(getChildFragmentManager());

代替

new ViewPagerAdapter(((HomeActivity) context).getSupportFragmentManager())
于 2021-01-23T09:14:35.973 回答
0

更好地使用FragmentStatePagerAdapter相应地重新创建片段。

于 2019-02-26T01:47:50.883 回答