实现Fragment->ViewPager->Fragment嵌套,并保存内层Fragment view 状态
来源:互联网 发布:尔雅网络课程怎么快进 编辑:程序博客网 时间:2024/06/07 18:01
前段时间工作中遇到了Fragment->ViewPager->Fragment嵌套的情况,刚开始也没觉得有什么问题,但是测试阶段发现内层Fragment 如果有RecyclerView,并且采用StaggeredGridLayoutManager进行布局,会发现每次切换回来RecyclerView 中item位置会发生偏移。刚开始以为是由于FragmentPagerAdapter的问题导致的(切换时没有存储当前Fragment状态),于是又参照v4包中FragmentStatePagerAdapter重新实现了通用Fragment的相应版本,但是结果还是未达到预期效果(Fragment的状态在viewPager之间切换是可以保存view状态的,但是切换外层Fragment还是不行)。苦思良久无果后,只能源码跟踪,发现原来是外层切换Fragment的时候只是存储当前内层Fragment的了Framgentde 状态,但是其View状态却未保存(这一点是跟ViewPager切换Framement唯一的区别),于是乎开始采取措施,在自己实现FragmentStatePagerAdapter的saveState()中存储添加到FragmentManager中的view状态,然后在restoreState(Parcelable state,ClassLoader loader)中恢复,经过这么一折腾还真达到了目的。特此记录,以备后用。
1、sveState()方法内容如下:
@Override public Parcelable saveState() { if (DEBUG) { Log.d(TAG, "saveState"); } Bundle state = null; if (mSavedState.size() > 0) { state = new Bundle(); Fragment.SavedState[] fss = new Fragment.SavedState[mSavedState.size()]; mSavedState.toArray(fss); state.putParcelableArray("states", fss); } for (int i = 0; i < mFragments.size(); i++) { Fragment f = mFragments.get(i); if (f != null && f.isAdded()) { if (state == null) { state = new Bundle(); } String key = "f" + i; mFragmentManager.putFragment(state, key, f);// Log.d(TAG, "saveState,i=" + i); //save fragment view state Class userCla = (Class) f.getClass().getSuperclass().getSuperclass().getSuperclass().getSuperclass(); Field[] fs = userCla.getDeclaredFields(); for (int k = 0; k < fs.length; k++) { Field filed = fs[k]; filed.setAccessible(true); //设置些属性是可以访问的 if (TextUtils.equals("mView", filed.getName())) { try { View view = (View) filed.get(f); SparseArray<Parcelable> stateArray = new SparseArray<Parcelable>(); view.saveHierarchyState(stateArray); if (null == state) { state = new Bundle(); } state.putSparseParcelableArray("spa:view:" + i, stateArray);// Log.d(TAG, "saveViewState+++++++++++++++++++" + stateArray); } catch (IllegalAccessException e) { e.printStackTrace(); } break; } } // } } return state; }
2、restoreState()方法内容如下:
@Override public void restoreState(Parcelable state, ClassLoader loader) { if (DEBUG) { Log.d(TAG, "restoreState"); } if (state != null) { Bundle bundle = (Bundle) state; bundle.setClassLoader(loader); Parcelable[] fss = bundle.getParcelableArray("states"); mSavedState.clear(); mFragments.clear(); if (fss != null) { for (int i = 0; i < fss.length; i++) { mSavedState.add((Fragment.SavedState) fss[i]);// Log.d(TAG, "restoreState,fss,i=" + i + ""); } } HashMap<Integer, SparseArray<Parcelable>> fragViewState = new HashMap<Integer, SparseArray<Parcelable>>(); Iterable<String> keys = bundle.keySet(); for (String key : keys) { if (key.startsWith("spa:view:")) { int index = Integer.parseInt(key.substring(9)); SparseArray<Parcelable> savedViewState = bundle.getSparseParcelableArray("spa:view:" + index); if (null != savedViewState) { fragViewState.put(index, savedViewState);// Log.d(TAG, "restoreState,mFragViewState,index=" + index + ",viewstate="+savedViewState); } } } for (String key : keys) { if (key.startsWith("f")) { int index = Integer.parseInt(key.substring(1)); Fragment f; try { f = mFragmentManager.getFragment(bundle, key); if (f != null) { while (mFragments.size() <= index) { mFragments.add(null); } f.setMenuVisibility(false); SparseArray<Parcelable> savedViewState = fragViewState.get(index); if (null != savedViewState) { Class userCla = (Class) f.getClass().getSuperclass().getSuperclass().getSuperclass().getSuperclass(); Field[] fs = userCla.getDeclaredFields(); for (int k = 0; k < fs.length; k++) { Field filed = fs[k]; filed.setAccessible(true); //设置些属性是可以访问的 if (TextUtils.equals("mView", filed.getName())) { try { View view = (View) filed.get(f); if(null != view) { view.restoreHierarchyState(savedViewState);// Log.d(TAG, view + "+++++++++++++++++++"); } } catch (IllegalAccessException e) { e.printStackTrace(); } break; } } } mFragments.set(index, f);// Log.d(TAG, "restoreState,setFragment,i=" + i + ""); } else { Log.w(TAG, "Bad fragment at key " + key); } } catch (Exception e) { Log.w(TAG, "Bad fragment IllegalStateException" + e.getMessage()); } } } } }
1 0
- 实现Fragment->ViewPager->Fragment嵌套,并保存内层Fragment view 状态
- Android ViewPager中加fragment并保存fragment的状态
- viewpager fragment中fragment的状态保存
- viewPager+fragment嵌套viewPager+fragment
- ViewPager+Fragment嵌套ViewPager+Fragment
- Fragment嵌套内层不显示
- 关于viewPager嵌套viewPager,切换上层fragment内层fragment不显示的问题
- Fragment+Viewpager+嵌套Tablelayout+fragment
- Fragment嵌套Fragment和Viewpager
- Fragment嵌套Fragment和Viewpager
- Fragment和ViewPager多层嵌套,容易出现内层fragment某些页面数据丢失
- ViewPager加fragment如何保存fragment里面的状态
- android解决fragment+viewpager状态保存问题
- viewPager+多个Fragment状态保存
- Fragment里面嵌套ViewPager
- ViewPager+Fragment嵌套
- Fragment嵌套ViewPager
- fragment嵌套viewpager
- 关于时间复杂度之认识
- python:sys.path.append()
- 数据库服务端的字符集
- 66. Plus One
- Linux 解压cpio文件
- 实现Fragment->ViewPager->Fragment嵌套,并保存内层Fragment view 状态
- SMON: Restarting fast_start para…
- 关于RMAN恢复中的switch database …
- HTTP error 500 Internal server e…
- ORA-16146: STANDBY DESTINATION C…
- sqlldr加载 数据文件的字段超出最…
- 恢复删除的view
- 淘宝、天猫用的Android框架V-Layout,赶紧收藏
- Linux Shell——流程控制