我有一个嵌套片段的项目(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
谢啦!
经过大量的灵魂探索,我可以确认在碎片内部生成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( 我只得到一级字段,比如: 以下是我的模式: 我的解析器: 知道我做错了什么吗?