片段是不可见的,但它的视图可以被点击。

huangapple go评论78阅读模式
英文:

Fragment is invisible but its views could be clicked

问题

我正在尝试实现在点击列表项时启用用户转到新的 Fragment。我已经创建了一个接口,允许我从 FragmentA.java 类处理点击事件。当活动启动时,FragmentA 附加到我的活动上,我的活动扩展了 FragmentActivity

在我的活动类中:

@Override
protected void onCreate(Bundle savedInstanceState){
  //...
  getSupportFragmentManager().beginTransaction().replace(R.id.container, FragmentA.newInstance(param1, param2)).commit();
}

然后在 FragmentA.java 中,我将其设置为我的 RecyclerView 适配器的点击处理程序。我使用 add() 方法而不是 replace() 方法来更改片段,因为我希望在附加 FragmentB 时保存 FragmentA 的状态(例如 RecyclerView 位置等)。

private void setListeners(){
  mAdapter.setOnItemClickListener(itemClickListener);
}

private ItemListAdapter.ItemClickListener itemClickListener = new ItemListAdapter.ItemClickListener() {
  @Override
  public void onItemClicked(View v, ItemModel item) {
                
    FragmentManager manager =((FragmentActivity)mActivity).getSupportFragmentManager();
            
    manager.beginTransaction().add(R.id.post_activity_layout_container, FragmentB.newInstance(item, param2, param3)).addToBackStack("comment").commit();
                
  }
};

问题在于:在这种情况下,FragmentA 正在运行但不可见,而用户看到的是 FragmentB。用户可以访问 FragmentA 的视图,这会引起问题。我想保存 FragmentA 的最后状态,但用户不应该从 FragmentB 点击 FragmentA 的视图。如何处理这个问题?有没有更好的做法来实现保存最后的状态?

编辑
FragmentA 包含一些排序和过滤。当我使用 replace() 方法时,用户设置的所有过滤器都无效,而且 RecyclerView 的位置变为 0。想象一下,用户正在查看列表中的第 33 项,点击它,附加了 FragmentB,然后返回到 FragmentA。我希望用户可以从第 33 项继续,而不是让用户尝试找到他之前的位置。

英文:

I am trying to enable user to go to a new Fragment when a list item is clicked. That's OK. I created an interface which allows me to handle click events from my FragmentA.java class. FragmentA is attached to my activity when activity started. my activity extends FragmentActivity.

In my activity class:

@Override
protected void onCreate(Bundle savedInsantaceState){
  //...
  getSupportFragmentManager().beginTransaction().replace(R.id.container, FragmentA.newInstance(param1, param2)).commit();
}

And then in FragmentA.java, i set that to my RecyclerView Adapter as click handler. I use add() method instead of replace() method to change the fragment, because i want to save the FragmentA's state (like RecyclerView position etc.) when FragmentB is attached.

private void setListeners(){
  mAdapter.setOnItemClickListener(itemClickListener);
}
    
private ItemListAdapter.ItemClickListener itemClickListener = new ItemListAdapter.ItemClickListener() {
@Override
public void onItemClicked(View v, ItemModel item) {
                
  FragmentManager manager =((FragmentActivity)mActivity).getSupportFragmentManager();
            
  manager.beginTransaction().add(R.id.post_activity_layout_container, FragmentB.newInstance(item, param2, param3)).addToBackStack("comment").commit();
                
}
};

HERE IS THE ISSUE : In this case, FragmentA is running but invisible, while user sees FragmentB. User can reach views of FragmentA, and that cause problems. I wanna save the last state of FragmentA but user should not click on views of FragmentA from FragmentB. How to handle that issue? Is there a better practice to accomplish saving the last state?

EDIT
FragmentA contains some sorting, filtering. When i use replace() method, all filters that user set is invalidated, and also RecyclerView position became 0. Imagine that user is looking at (for example) 33. item in the list, clicks on it, FragmentB is attached, then go back to FragmentA. I want user to continue from 33. item, don't want user to try to find for where he was.

答案1

得分: 2

我不确定你所说的“我想保存FragmentA的最后状态”的确切意思,但据我所知,替换容器中的片段并不意味着它们会失去状态。例如,您仍然可以点击返回按钮,这将撤消事务,从后堆栈中获取上一个片段。

编辑:你观察到的效果很可能是由于销毁和重新创建片段视图层级所引起的。有一些方法可以解决这个问题。第一种方法是在重新初始化片段后存储 UI 状态,并在重新初始化片段后恢复它。不幸的是,对于 RecyclerView 的位置可能会比较棘手(你可以搜索一下)。另一种更简单的方法(这是一种 hack)是只在 onCreateView 中创建根视图一次,在片段内保留对它的引用,并在后续的 onCreateView 调用中返回相同的视图。如果你决定使用后一种方法,请小心,因为你将不完全按照片段的预期方式使用它们。

虽然与你的问题不直接相关,但我绝对建议避免手动管理片段。这将会非常痛苦。你可以使用官方的导航组件,或者选择一个更简单的解决方案,比如 FragNav 库。我在这篇文章中介绍了关于后者的内容,这可能会对你有所帮助。

英文:

I'm not sure what you mean by "I wanna save the last state of FragmentA" exactly, but, AFAIK, the fact that you replace Fragments in a container doesn't mean they lose state. For example, you can still click on back button and this will revert the transaction, bringing the previous Fragment from the back-stack.

Edit: the effects that you observe are most probably caused by the destruction and re-creation of Fragment's View hierarchy. There are couple of approaches around it. The first one would be to store UIs state and restore it after re-initialization of the Fragment. Unfortunately, it might be tricky with RecyclerView position (you can google it). Another simpler approach (which is a hack) is to create the root View in onCreateView only once, keep a reference to it inside Fragment and return the same View on subsequent calls to onCreateView. If you decide to use the later approach, be careful because you'll be using Fragments not exactly the way there were intended to use.

Not directly related to your question, but I absolutely recommend avoiding manual Fragments management. It'll be too painful. You can use the official Navigation Component, or, alternatively, a simpler solution like FragNav library. I wrote this post about the later and it might help you.

huangapple
  • 本文由 发表于 2020年8月25日 10:48:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/63571362.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定