避免在执行选项卡切换时重新创建相同的视图 [英] Avoid recreating same view when perform tab switching

查看:70
本文介绍了避免在执行选项卡切换时重新创建相同的视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当前,我有2个 Fragments ,可以通过 ActionBar 的选项卡进行切换.

  getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);ActionBar.Tab newTab = getSupportActionBar().newTab();newTab.setText("history");newTab.setTabListener(new TabListenerHistoryFragment>(this,"history",HistoryFragment.class)); 


  @Overridepublic void onTabSelected(标签"标签,FragmentTransaction ft){//检查片段是否已经初始化如果(mFragment == null){//如果没有,请实例化并将其添加到活动中mFragment = Fragment.instantiate(mActivity,mClass.getName());mFragment.setRetainInstance(true);ft.add(android.R.id.content,mFragment,mTag);} 别的 {//如果存在,只需附加它以显示它ft.attach(mFragment);}} 

我意识到第一次启动我的 Activity (此活动包含2个片段),将按以下顺序调用 Fragment s的方法.

onCreate->onCreateView->onStart

当我执行Tab切换,然后再将Tab切换回相同的Fragment时,将再次调用以下方法.

onCreateView->onStart

当切换回Tab时,我只希望保留相同的GUI视图状态.

  • 我希望图表继续放大到上一级.
  • 我希望图表水平滚动保持在先前的水平.
  • 我希望我的列表继续滚动以保持在上一级.
  • ...

我知道在切换Tab时可以使用以下方法保存/恢复简单变量

android片段-如何将片段中的视图状态保存到另一个片段上

但是,这不是我想要的,因为很难在整堆原始值中描述我的GUI状态.

我尝试以下方法.当然,它不会起作用,因为我遇到了以下运行时错误.

 公共类HistoryFragment扩展Fragment {视图view = null;@Override公共视图onCreateView(LayoutInflater充气器,ViewGroup容器,捆绑保存的实例状态){如果(this.view!= null){返回this.view;}this.view = inflater.inflate(R.layout.history_activity,container,false);}} 

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

我意识到以下演示示例可以在进行Tab切换时保留其片段GUI状态(例如,列表的垂直滚动位置).但是我想,也许是因为他们正在使用ListFragment吗?我发现它们没有执行任何特殊处理来保留GUI状态.

  • com.example.android.apis.app.FragmentTabs
  • com.example.android.apis.app.LoaderCursor.CursorLoaderListFragment

我可以知道,在执行选项卡切换时如何避免重新创建相同的视图?

解决方案

我遇到了同样的问题,并尝试遵循错误消息中的建议.我尝试了以下代码,并且对我有用.

  public View onCreateView(LayoutInflater充气器,ViewGroup容器,捆绑状态){如果(mMyView == null){mMyView =新的MyView(getActivity());} 别的 {((ViewGroup)mMyView.getParent()).removeView(mMyView);}返回mPuzzleView;} 

Current, I have 2 Fragments, which is switch-able through ActionBar's tab.

    getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
    ActionBar.Tab newTab = getSupportActionBar().newTab();
    newTab.setText("history");
    newTab.setTabListener(new TabListenerHistoryFragment>(this, "history",
        HistoryFragment.class));


 @Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
    // Check if the fragment is already initialized
    if (mFragment == null) {

        // If not, instantiate and add it to the activity
        mFragment = Fragment.instantiate(mActivity, mClass.getName());
        mFragment.setRetainInstance(true);
        ft.add(android.R.id.content, mFragment, mTag);
    } else {
        // If it exists, simply attach it in order to show it
        ft.attach(mFragment);
    }        
}

I realize the first time of my Activity (This activity is holding 2 fragments) being launched, Fragments' methods will be called in the following sequence.

onCreate -> onCreateView -> onStart

When I perform Tab switching, and then Tab switching back to the same Fragment, the following methods will be called again.

onCreateView -> onStart

I just wish to retain the same GUI view state, when Tab is being switched back.

  • I want my chart continue to be zoomed into previous level.
  • I want my chart horizontal scroll stay at previous level.
  • I want my list continue scroll stay at previous level.
  • ...

I know that I can save/restore simple variables using the following method when Tab switching

android fragment- How to save states of views in a fragment when another fragment is pushed on top of it

But, that is not something I want, as my GUI state is pretty difficult to describe within whole bunch of primitive values.

I try the following approach. Of course it won't work, as I am getting the following runtime error.

public class HistoryFragment extends Fragment {
    View view = null;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        if (this.view != null) {
            return this.view;
        }
        this.view = inflater.inflate(R.layout.history_activity, container, false); 
    }
}

java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

I realize the following demo example is able to preserve its fragment GUI state (For instance, the position of vertical scroll of list) when there is Tab switching. But I guess, perhaps it is because they are using ListFragment? As I do not find they perform any special handling to preserve GUI state.

  • com.example.android.apis.app.FragmentTabs
  • com.example.android.apis.app.LoaderCursor.CursorLoaderListFragment

May I know, how I can avoid from recreating same view when perform tab switching?

解决方案

I had the same problem, and tried to follow the suggestion in the error message. I tried the following code, and it worked for me.

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle state)  {
     if (mMyView == null) {
         mMyView = new MyView(getActivity());
     } else {
         ((ViewGroup) mMyView.getParent()).removeView(mMyView);
     }

     return mPuzzleView; 
}

这篇关于避免在执行选项卡切换时重新创建相同的视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆