您的位置:首页 > 移动开发 > Android开发

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

以上是实验的环境,本人想要实现如下的效果:



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 fragment viewpager