当前位置: 首页 > 知识库问答 >
问题:

具有回收器的 Android 嵌套片段查看

倪风史
2023-03-14

我有一个嵌套片段的项目(https://github.com/checklist/NestedFragmentsRecycler)。FragmentA位于MainActivity中,包含带有适配器的RecyclerView。适配器中的每个项目都将返回FragmentB。因为我需要给一个id来装载FragmentB到位置,并且它需要是唯一的,所以我正在生成我自己的id。第一个片段显示得很好,但不幸的是,当我开始滚动时,我得到一个异常,无法找到我的唯一id:

D/FragmentManager:
android.support.v7.widget.RecyclerView{9b96575 VFEDH... F...0,0-2304,1464#7f0b0057 app: id/listView}D/FragmentManager:
android.widget.LinearLayout{e58090a V. E......-19,0-781,1464}W/ResourceType:获取资源号名称时没有包标识符0x00000001 D/FragmentManager:
android.widget.FrameLayout{c93513 V. E......0,0-800,1464#1}D/FragmentManager:
android.widget.LinearLayout{3899350 V. E......0,0-800,1464}D/FragmentManager:
android.support.v7.widget.AppCompatTextView{5f9157bV.ED....0,0-254,38#7f0b0070 app: id/text View}D/FragmentManager:
android.widget.LinearLayout{7bbcf98 V. E......781,0-1581,1464}W/Resour0,0-800,1464#2}D/FragmentManager:
android.widget.LinearLayout{c313105 V. E......0,0-800,1464}D/FragmentManager:
android.support.v7.widget.AppCompatTextView{bc7e3f1V.ED.......0,0-254,38#7f0b0070 app: id/text View}D/FragmentManager:
android.widget.LinearLayout{8f5abd6 V. E......1581,0-2381,1464}W/ResourceType:获取资源号名称时没有包标识符0x00000003 D/FragmentManager:
android.widget.FrameLayout{918d881 V. E......0,0-800,1464#3}D/FragmentManager:
android.widget.LinearLayout{651ad26 V. E......0,0-800,1464}D/FragmentManager:
android.support.v7.widget.AppCompatTextView{8798e57V.ED.......0,0-254,38#7f0b0070 app: id/text View}D/FragmentManager:
android.support.v7.widget.ActionBarContainer{36a4d44V.ED.......0,0-2560,128#7f0b0045 app: id/action_bar_container}D/FragmentManager:android.support.v7.widget.Toolbar{e65ce2d V. E......0,0-2560,128

48,37-153,91}D/FragmentManager:
android.support.v7.widget.ActionMenuView{c1eb8f3 V. E......2544,0-2544,128}D/FragmentManager:
9b{460f9b0 G. E.........0,0-0,0#7f0b0047 app: id/action_context_bar}D/FragmentManager:
Handler.java:95{77e2029android.os.Looper.loop...0,1704-2560,1800#1020030 android: id/NavigationBar}D/FragmentManager:
Looper.java:154{7365faeV.ED.......0,0-2560,48#102002f android: id/statusBarbackground}D/AndroidRuntime:关闭VM E/AndroidRuntime: FATAL EXCEPTION:主进程:example.com.demo, PID: 8156java.lang.IllegalArgumentException:找不到片段的id 0x4(未知)视图FragmentB{30cadandroid.os.Handler.dispatchMessage#3 id=0x4}在android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1107)在android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1295)在android.support.v4.app.BackStackRecord.run(BackStackRecord.java:801)在android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1682)在android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:541)在android.os.Handler.handleCallback(Handler.java:751)在android.support.v7.widget.ActionBarContextView(android.view.View)在V.ED.(android.view.View))在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)与目标VM断开连接,地址:'localhost: 8616',传输:'ocket'

2个主要类是FragmentAAdapter和FragmentB(如果需要,您可以在git repo中查看其他类):

public class FragmentAAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{

FragmentA fragmentA;
Activity activity;
RecyclerView listView;

public FragmentAAdapter(FragmentA fragmentA, Activity activity, RecyclerView listView) {
    this.fragmentA = fragmentA;
    this.activity = activity;
    this.listView = listView;
}


@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_b, parent, false);
    RecyclerView.ViewHolder vh = new BoardViewHolder(v, this);
    return vh;
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    if (holder instanceof BoardViewHolder){
        BoardViewHolder pHolder = (BoardViewHolder)holder;
        pHolder.onBindViewHolder(position);
    }
}

@Override
public int getItemCount() {
    return 10;
}

public class BoardViewHolder extends RecyclerView.ViewHolder {

    FragmentAAdapter adapter;
    FragmentB fragmentB;
    View view;

    public BoardViewHolder(View itemView, FragmentAAdapter adapter) {
        super(itemView);

        this.view = itemView;
        this.adapter = adapter;
    }

    public void onBindViewHolder(int position) {

        FragmentManager fm = fragmentA.getChildFragmentManager();
        if (fragmentB==null) {
            Bundle bundle = new Bundle();
            bundle.putString("TEXT", "This is Fragment B:" + position);
            fragmentB = FragmentB.getInstance(bundle);

            int boardId = generateViewId();
            // switch the id of the board to be unique
            View board = view.findViewById(R.id.board);
            board.setId(boardId);

            // now flip fragmentB
            FragmentTransaction ft = fm.beginTransaction();
            ft.replace(boardId, fragmentB);
            ft.commit();
        }
    }
}

private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);

public static int generateViewId() {
    for (;;) {
        final int result = sNextGeneratedId.get();
        // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
        int newValue = result + 1;
        if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
        if (sNextGeneratedId.compareAndSet(result, newValue)) {
            return result;
        }
    }
}

}

和片段B:

public class FragmentB extends Fragment {

View root;

Activity activity;

String text;
private TextView textView;

public static FragmentB getInstance(Bundle bundle) {
    FragmentB instance = new FragmentB();
    instance.setArguments(bundle);
    return instance;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    activity = (Activity) getActivity();

    if (getArguments()!=null) {
        text = getArguments().getString("TEXT");

    }
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    super.onCreateView(inflater, container, savedInstanceState);

    root = inflater.inflate(R.layout.row, null, false);

    textView = (TextView)root.findViewById(R.id.textView);
    textView.setText(text);

    return root;
}

}

完整代码:https://github.com/checklist/NestedFragmentsRecycler

谢啦!

共有1个答案

拓拔弘扬
2023-03-14

经过大量的灵魂探索,我可以确认在碎片内部生成id是不可能的。如果你这样做,Android在渲染UI时会变得混乱,应用程序会崩溃。

我在另一个项目中尝试过这一点,在该项目中,我们为动态生成的单选按钮和组生成了ID,并将其放置在片段和相同的行为中。两种解决方案: - 不要以编程方式创建,因此不需要生成id - 不要使用片段

 类似资料:
  • 根据谷歌的文档: 现在可以在片段中嵌入片段。这对于各种情况都很有用,在这些情况下,您需要将动态和可重用的UI组件放置到本身是动态和可重用的UI组件中。例如,如果使用ViewPager创建左右滑动并占用大部分屏幕空间的片段,现在可以将片段插入每个片段页面。要嵌套片段,只需对要添加片段的片段调用getChildFragmentManager()。这将返回一个FragmentManager,您可以像通常

  • 在我的应用程序中,一个

  • 我有一个ViewPagerContainer片段,在应用程序启动时加载。ViewPagerContainer片段将两个选项卡(选项卡A和选项卡B)添加到操作栏。选项卡B有两个项目的列表视图。 我所做的:我在选项卡B片段中的列表视图项上附加了一个click listener,这样当用户单击一个项时,它会在第一个片段(即选项卡B下)内打开另一个片段(子片段)。 我陷入困境的地方:当用户按下后退按钮时,

  • 我正在使用嵌套片段,当我按下时,我面临问题。 流量: 这是我的应用程序的结构。其中C、D、E、F是子片段,未添加到后堆栈中。D包含列表片段,从D中我称为B。但当我从B中按回来时,我想再次使用最后选定位置的D。我在后堆栈中添加了A和B。我怎样才能做到这一点。给我提供一些解决方案。我回忆起D,但选择的位置总是在变化。

  • 问题 我想在一个活动中创建带有2个片段的viewpager。这个片段有不同的菜单选项,并且一个片段是嵌套的-通过单击listview项目,打开带有新数据的相同片段(),但是viewpager不能正确替换(当我这样做时。 我用了这个答案——https://stackoverflow.com/a/18020219/5576117,,但是我有不同的菜单选项,而且菜单选项是从片段容器中膨胀出来的。 因此,

  • 我正在努力学习GraphQL( 我只得到一级字段,比如: 以下是我的模式: 我的解析器: 知道我做错了什么吗?