-1

这是这种情况。我在片段 A 中有一个列表视图,其中有一个无限列表,当用户到达底部时,该列表通过 Web 服务填充。

列表视图中的每个项目都有一个“查看更多”链接,可打开该项目的详细片段 B。

我正在使用 FragmentManager.replace() 方法和“addToBackStack”。(我是“替换”而不是“添加”,因为我在片段 A 中有我不想在片段 B 中显示的菜单项。我已经尝试了不同的方法来添加片段,而不是在打开时删除并尝试隐藏菜单项片段 B 已经工作,但以一些其他问题结束,所以我更喜欢使用替换")

假设用户正在查看列表中的第 25 项,然后打开详细信息片段。当用户然后点击后退按钮时,我希望用户继续在同一位置查看列表。

这很容易通过“添加片段”而不是“替换”来实现,因为片段从未被删除。使用“替换”时,片段会被删除,然后当被击退时,它将再次呈现(又名,将再次调用 onCreateView)

但是此时,已经为片段创建了视图,因为 FragmentManager.remove 仅从视图层次结构中删除视图,但不破坏片段。所以我“理论上”可以做这样的事情:

if(view == null){
    //Create view
    view = (ViewGroup) inflater.inflate(R.layout.news_list, container, false);
}
return view;

但在这种情况下,它会导致

java.lang.IllegalStateException:指定的孩子已经有一个父母。您必须首先在孩子的父母上调用 removeView()。

所以,我的解决方案如下:

if(view == null){
    view = (ViewGroup) inflater.inflate(R.layout.news_list, container, false);
} else {
    ((ViewGroup) view.getParent()).removeView(view);
}
return view;

这对我有用,但我不知道除了这个解决方案之外是否会有一些我现在没有看到的“隐藏”错误。

我想听听你的建议。提前致谢

4

2 回答 2

0

为什么不记住直到用户在片段的 onPause 中滚动的位置并将列表视图位置设置为 onResume 中的滚动位置?只是一个想法,我不确定您的解决方案是否有任何不利影响/错误。

  @Override
  public void onPause() {
    // TODO Auto-generated method stub
    super.onPause();

   try{
         index = this.getListView().getFirstVisiblePosition();
         View v = this.getListView().getChildAt(0);
         top = (v == null) ? 0 : v.getTop();
      }
      catch(Throwable t){
         t.printStackTrace();
      }

在片段的 onResume 中:

   @Override
public void onResume() {
    // TODO Auto-generated method stub
    super.onResume();

    /**
     *  Check to see if there is any scroll position
     *  saved up, this is done in case of user returning 
     *  back from the contact detail screen
     */
    setListAdapter(adapter);
      if(index!=-1){
         this.getListView().setSelectionFromTop(index, top);
      }
}

希望这可以帮助 !

于 2014-05-07T14:10:48.080 回答
0

如果在执行删除片段的事务时不调用 addToBackStack(),则在提交事务时该片段将被销毁,并且用户无法导航回该片段。然而,如果您在删除片段时确实调用了 addToBackStack(),那么片段将停止,并且如果用户导航回来,它将恢复。

提示:对于每个片段事务,您可以通过在提交之前调用 setTransition() 来应用过渡动画。

调用 commit() 不会立即执行事务。相反,一旦线程能够这样做,它就会安排它在活动的 UI 线程(“主”线程)上运行。但是,如有必要,您可以从 UI 线程调用 executePendingTransactions() 以立即执行由 commit() 提交的事务。除非事务是其他线程中作业的依赖项,否则通常不需要这样做。

于 2016-11-19T19:15:25.273 回答