Viewpager实现类似网易新闻的效果

1、添加Adapter

public class NewsFragmentPagerAdapter extends FragmentPagerAdapter {
    private static final String TAG ="PagerAdapter";
	private ArrayList<Fragment> fragments;
	private FragmentManager fm;
	private List<ChannelItem> userChannels;
	private ArrayList<Boolean> fragmentsUpdateFlag=new ArrayList<>();

	public NewsFragmentPagerAdapter(FragmentManager fm) {
		super(fm);
		this.fm = fm;
	}

	public NewsFragmentPagerAdapter(FragmentManager fm, ArrayList<Fragment> fragments, List<ChannelItem> userChannels) {
		super(fm);
		this.fm = fm;
		this.fragments = fragments;
		initFlag();
		this.userChannels =userChannels;
	}

	/**
	 * 初始化更新标志位
	 */
	private void initFlag() {
		for (int i = 0; i < fragments.size(); i++) {
			fragmentsUpdateFlag.add(false);//初始化 都不需要更新
		}
	}

	@Override
	public int getCount() {
		return fragments.size();
	}

	/**
	 * @param position
	 * @return 艹 调用notifyDatasetChange getItem方法并没有被调用
	 */
	@Override
	public Fragment getItem(int position) {
		Log.e(TAG,"getItem()被调用:"+position);
		return fragments.get(position);
	}

	/**
	 * 如果 Item 的位置如果没有发生变化,则返回 POSITION_UNCHANGED。
	 * 如果返回了 POSITION_NONE,表示该位置的 Item 已经不存在了。
	 * 默认的实现是假设 Item 的位置永远不会发生变化,而返回 POSITION_UNCHANGED,所以notifyXXXX没有起作用
	 * @param object
	 * @return
	 */
	@Override
	public int getItemPosition(Object object) {
		return POSITION_NONE;
	}

	@Override
	public void destroyItem(ViewGroup container, int position, Object object) {
		super.destroyItem(container, position, object);
	}

	/**
	 * Viewpager 的刷新过程是这样的,在每次调用 PagerAdapter 的 notifyDataSetChanged() 方法时,都会激活 getItemPosition(Object object) 方法,
	 * 该方法会遍历 ViewPager 的所有 Item(由缓存的 Item 数量决定,默认为当前页和其左右加起来共3页,这个可以自行设定,但是至少会缓存2页),
	 * 为每个 Item 返回一个状态值(POSITION_NONE/POSITION_UNCHANGED),
	 * 如果是 POSITION_NONE,那么该 Item 会被 destroyItem(ViewGroup container, int position, Object object) 方法 remove 掉,然后重新加载,
	 * 如果是 POSITION_UNCHANGED,就不会重新加载,默认是 POSITION_UNCHANGED,
	 * 所以如果不重写 getItemPosition(Object object),修改返回值,就无法看到 notifyDataSetChanged() 的刷新效果。
	 * @param currentfrags 在这里将所有的Fragment都移除了,貌似不太好吧
	 */
	public void setFragments(ArrayList<Fragment> currentfrags,List<ChannelItem> currentChannels) {
		/**
		 * 这里可以确定哪些需要改变的么?
		 * 这里的条数 以新的Fragment为主
		 * */
		if(currentChannels.size()>=userChannels.size()){
			for (int i = 0; i < userChannels.size(); i++) {
				if (userChannels.get(i).getId()==currentChannels.get(i).getId()){
					fragmentsUpdateFlag.set(i, false);//如果相同 就不需要更新了
				}else {
					fragmentsUpdateFlag.set(i,true);//如果不同 就更新
				}
			}
			for (int i = userChannels.size(); i < currentChannels.size(); i++) {
				fragmentsUpdateFlag.add(i,true);//多出来的部分都要更新
			}
		}else {
			//如果栏目减少了,多出来的部分就不用管了
			for (int i = 0; i < currentChannels.size(); i++) {
				if (userChannels.get(i).getId()==currentChannels.get(i).getId()){
					fragmentsUpdateFlag.set(i,false);//如果相同 就不需要更新了
				}else {
					fragmentsUpdateFlag.set(i,true);//如果不同 就更新
				}
			}
		}
		//更新集合
		fragments = currentfrags;
		userChannels=currentChannels;
		notifyDataSetChanged();
	}

	/**
	 * @param container
	 * @param position
	 * @return
	 */
	@Override
	public Object instantiateItem(ViewGroup container, final int position) {
		/*Object obj = super.instantiateItem(container, position);
		return obj;*/
		//得到缓存的fragment
		Fragment fragment = (Fragment) super.instantiateItem(container, position);
		//得到tag,这点很重要
		String fragmentTag = fragment.getTag();
		if (fragmentsUpdateFlag.get(position % getCount())) {
		//如果这个fragment需要更新
			FragmentTransaction ft = fm.beginTransaction();
			//移除旧的fragment
			ft.remove(fragment);
			//换成新的fragment
			fragment = fragments.get(position % getCount());
			//添加新fragment时必须用前面获得的tag,这点很重要
			ft.add(container.getId(), fragment, fragmentTag);
			ft.attach(fragment);
			ft.commitAllowingStateLoss();
			//复位更新标志
			fragmentsUpdateFlag.set(position % getCount(),false);
		}

		return fragment;
	}



	@Override
	public CharSequence getPageTitle(int position) {
		return userChannels.get(position).getName();
	}


 

2、Viewpager填充Adapter

    homeViewPager = (ViewPager) view.findViewById(R.id.homepager_menu_detail);
        pagerAdapter = new NewsFragmentPagerAdapter(mContext.getSupportFragmentManager(),fragments,userChannels);
        homeViewPager.setAdapter(pagerAdapter);

3、填充效果


4、滑动tab页 Fragment加载顺序

从头条滑动到主题页面:
08-08 17:05:33.464 15970-15970图片的 onCreate()执行
08-08 17:05:33.464 15970-15970图片onCreateView()执行

从专题页滑动到图片页面:
08-08 17:07:08.344 15970-15970 原创的 onCreate()执行
08-08 17:07:08.344 15970-15970 原创onCreateView()执行
规律:viewPager会预加载下 一页的数据

当所有页面都create一遍后,viewpager预加载下一页只会调用onCreateView方法:
08-08 17:08:18.744 15970-15970/cn.com.zgsyb.oil E/BaseFragment: 原创onCreateView()执行
08-08 17:08:20.184 15970-15970/cn.com.zgsyb.oil E/BaseFragment: 图片onCreateView()执行
08-08 17:08:23.914 15970-15970/cn.com.zgsyb.oil E/BaseFragment: 专题onCreateView()执行
08-08 17:08:26.854 15970-15970/cn.com.zgsyb.oil E/BaseFragment: 头条onCreateView()执行
08-08 17:08:31.974 15970-15970/cn.com.zgsyb.oil E/BaseFragment: 图片onCreateView()执行
08-08 17:08:33.984 15970-15970/cn.com.zgsyb.oil E/BaseFragment: 原创onCreateView()执行
08-08 17:08:35.314 15970-15970/cn.com.zgsyb.oil E/BaseFragment: 本地onCreateView()执行
08-08 17:08:38.994 15970-15970/cn.com.zgsyb.oil E/BaseFragment: 培训onCreateView()执行


5、需要解决的问题

5.1消除预加载(显示界面的时候再加载数据)


5.2跳转页面顺序,刷新数据





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值