ViewPager实现可滑动的Fragment,滑动页面时报错的解决方案
2015-05-28 17:55
363 查看
1. 主Activity和主布局,线性布局中只有一个ViewPager控件:
MainActivity.java
activity.xml
2. 三个继承Fragment的类和对应布局:
FragmentOne.java
FragmentTwo.java
FragmentThree.java
fragment_one.xml
fragment_two.xml
fragment_three.xml
3. 继承FragmentPagerAdapter的类,用于管理ViewPager控件:
MyPagerAdapter.java
Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if(view == null) {//<span style="color:#ff0000;">注意这里,view是私有成员变量。</span>
view = inflater.inflate(R.layout.fragment_one, container, false);
Log.i("my", "s");
}
Log.i("my", "FragmentOne.onCreateView");
return view;
}
MyPagerAdapter.java代码如下。我只重写了构造构造函数和getItem(int
arg0), getCount()两个方法。
package guoweidong.android.test06;
import java.util.ArrayList;
import java.util.List;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.util.Log;
import android.view.ViewGroup;
public class MyPagerAdapter extends FragmentPagerAdapter{
private List<Fragment> list;
private FragmentManager fm;
public MyPagerAdapter(FragmentManager fm) {
super(fm);
this.fm = fm;
list = new ArrayList<Fragment>();
}
public MyPagerAdapter(FragmentManager fm, List<Fragment> list) {
super(fm);
this.fm = fm;
this.list = list;
}
@Override
public Fragment getItem(int arg0) {
// TODO Auto-generated method stub
return list.get(arg0);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return list.size();
}
}
我们考虑一个问题:当Fragment被移除ViewPager后,又重新调用instantiateItem方法添加到ViewPager,但是在instantiateItem方法中不光添加到ViewPager,还添加到FragmentManager中,这就带来了重复添加问题。
删掉FragmentOne的onCreateView的if判断语句,得到下面代码:
方案二:
复写FragmentViewPager的instantiateItem和destroyItem方法,使它不重复添加Fragment。
在MyPagerAdapter中添加下面的方法:
MainActivity.java
activity.xml
2. 三个继承Fragment的类和对应布局:
FragmentOne.java
FragmentTwo.java
FragmentThree.java
fragment_one.xml
fragment_two.xml
fragment_three.xml
3. 继承FragmentPagerAdapter的类,用于管理ViewPager控件:
MyPagerAdapter.java
以上是实验的环境,本人想要实现如下的效果:
1. 问题描述
但是,在左右滑动Fragment时,会报错:Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
2. 部分代码
在FragmentOne的onCreateView方法中,我是按如下代码写的。注意红字部分,我对view进行了判断,如果为空才创建。这是为了防止多次调用onCreateView而创建出多个view。@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if(view == null) {//<span style="color:#ff0000;">注意这里,view是私有成员变量。</span>
view = inflater.inflate(R.layout.fragment_one, container, false);
Log.i("my", "s");
}
Log.i("my", "FragmentOne.onCreateView");
return view;
}
MyPagerAdapter.java代码如下。我只重写了构造构造函数和getItem(int
arg0), getCount()两个方法。
package guoweidong.android.test06;
import java.util.ArrayList;
import java.util.List;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.util.Log;
import android.view.ViewGroup;
public class MyPagerAdapter extends FragmentPagerAdapter{
private List<Fragment> list;
private FragmentManager fm;
public MyPagerAdapter(FragmentManager fm) {
super(fm);
this.fm = fm;
list = new ArrayList<Fragment>();
}
public MyPagerAdapter(FragmentManager fm, List<Fragment> list) {
super(fm);
this.fm = fm;
this.list = list;
}
@Override
public Fragment getItem(int arg0) {
// TODO Auto-generated method stub
return list.get(arg0);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return list.size();
}
}
3. 问题发现
在FragmentPagerAdapter中有两个方法:public Object instantiateItem(ViewGroup container, int position); public void destroyItem(ViewGroup container, int position, Object object);这两个方法中第一个是用来将Fragment通过FragmentManager添加到ViewPager中的;第二个是用来将Fragment移除ViewPager的。在我们左右滑动Fragment时,在ViewPager中始终只保留两个Fragment,剩余的Fragment会移除ViewPager,但是并不会将此Fragment移除FragmentManager。
我们考虑一个问题:当Fragment被移除ViewPager后,又重新调用instantiateItem方法添加到ViewPager,但是在instantiateItem方法中不光添加到ViewPager,还添加到FragmentManager中,这就带来了重复添加问题。
4. 解决方案
方案一:删掉FragmentOne的onCreateView的if判断语句,得到下面代码:
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { view = inflater.inflate(R.layout.fragment_one, container, false); return view; }这样每次返回的view都是新建的,所以不存在重复添加问题。但是这么做,会不断增加FragmentManager的负担。
方案二:
复写FragmentViewPager的instantiateItem和destroyItem方法,使它不重复添加Fragment。
在MyPagerAdapter中添加下面的方法:
@Override public Object instantiateItem(ViewGroup container, int position) { String name = ""+ container.getId() + position; Fragment fragment = fm.findFragmentByTag(name); Log.i("my", name); if(fragment != null) { fm.beginTransaction() .attach(fragment) .commit(); Log.i("my", "attach"); } else { fragment = getItem(position); fm.beginTransaction() .add(container.getId(), fragment, name) .commit(); } return fragment; } @Override public void destroyItem(ViewGroup container, int position, Object object) { // TODO Auto-generated method stub String name = ""+ container.getId() + position; Fragment fragment = fm.findFragmentByTag(name); if(fragment != null) { fm.beginTransaction() .detach(fragment); } }
相关文章推荐
- Android 利用ViewPager、Fragment、PagerTabStrip实现多页面滑动效果
- 自学android笔记之TabLayout结合ViewPager和Fragment实现多页面滑动
- Android 利用ViewPager、Fragment、PagerTabStrip实现多页面滑动效果(转载)
- Viewpager+Fragment实现页面的滑动
- Android ViewPager + Fragment实现滑动页面效果
- Viewpager+Fragment实现左右滑动切换页面
- Android 利用ViewPager、Fragment、PagerTabStrip实现多页面滑动效果
- 利用viewpager、Fragment、pagertabStrip 实现多页面滑动效果
- 如何利用ViewPager、Fragment、PagerTabStrip实现多页面滑动效果
- Android开发之ViewPager结合Fragment实现滑动页面的效果(源代码分享)
- Android ViewPager+Fragment(碎片)实现页面滑动
- 不用ViewPager和Fragment实现滑动页面的效果
- ViewPager+Fragment实现页面滑动切换
- Fragment嵌套ViewPager加上RadioButton实现微信页面滑动点击效果
- Fragment + ViewPager实现滑动页面
- ViewPager+Fragment实现页面点击切换和手势滑动
- Android之ViewPager+Fragment实现页面点击切换和手势滑动
- ViewPager+Fragment实现滑动页面
- fragment+viewpager+tablayou实现滑动切换页面
- Viewpager_Fragment实现的页面滑动