ViewPager实现可滑动的Fragment,滑动页面时报错的解决方案

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);
		}
	}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值