使用ViewPager加载Fragment

来源:互联网 发布:祝利荣牛熊线指标源码 编辑:程序博客网 时间:2024/05/18 03:09

ViewPager的简介与使用

<?xml version="1.0" encoding="utf-8"?><resources>    <item name="viewPager" type="id"></item></resources>
package com.huangfei.criminalintent;import java.util.ArrayList;import java.util.UUID;import android.os.Bundle;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentActivity;import android.support.v4.app.FragmentManager;import android.support.v4.app.FragmentStatePagerAdapter;import android.support.v4.view.ViewPager;import android.support.v4.view.ViewPager.OnPageChangeListener;public class CrimePagerActivity extends FragmentActivity {    private ViewPager mViewPager;    private ArrayList<Crime> mCrimes;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        /**         * 以代码的方式创建视图并不奇怪,但我们还无法完全弃用XML文件,因为某些构件块依然需要资源ID。         * FragmentManager要求任何用作fragment容器的视图都必须具有资源ID。         * ViewPager是一个fragment容器,因此,必须赋予其资源ID。         *          * 以代码的方式创建视图,应完成以下任务项:         * 1、为ViewPager创建资源ID;         * 2、创建ViewPager实例并赋值给mViewPager         * 3、赋值资源ID给ViewPager,并对其进行配置;         * 4、设置ViewPager为activity的内容视图         *          * 定义独立资源ID与定义字符串资源ID并没有什么不同:在res/values目录下的XML文件中创建一个名为ids.xml的Android XML资源文件,         * 用以存储资源ID,并在其中新增一个名为viewPager的ID。         */        mViewPager = new ViewPager(this);        mViewPager.setId(R.id.viewPager);        setContentView(mViewPager);        mCrimes = CrimeLab.get(this).getCrimes();        FragmentManager fm = getSupportFragmentManager();        /**         * FragmentStatePagerAdapter与FragmentPagerAdapter的区别:         * FragmentStatePagerAdapter:使用FragmentStatePagerAdapter会销毁掉不需要的fragment。事务提交后。可将fragment从activity         * 的FragmentManager中彻底移除。因此FragmentStatePagerAdapter更节省内存。         *          * FragmentPagerAdapter:对于不需要的fragment,FragmentPagerAdapter则选择调用事务的detach(Fragment)方法,         * 而非remove(Fragment)方法。FragmentPagerAdapter只销毁了fragment的视图,但仍将fragment实例保留在FragmentManager中。         * 因此,FragmentPagerAdapter创建的fragment永远不会被销毁。         *          * 当有大量fragment实例时,可选择FragmentStatePagerAdapter;而当用户只需少量且固定的fragment时,则选择FragmentPagerAdapter。         */        mViewPager.setAdapter(new FragmentStatePagerAdapter(fm) {            @Override            public int getCount() {                return mCrimes.size();            }            @Override            public Fragment getItem(int position) {                Crime crime = mCrimes.get(position);                return CrimeFragment.newInstance(crime.getId());            }        });        /**         * onPageScrolled(...)方法可告知我们页面将滑向哪里。         * onPageScrollStateChanged(...)方法可告知我们当前页面所处的行为状态,如正在被用户滑动、页面滑动入位到完全静止以及页面切换完成后的闲置状态。         * onPageSelected(...)方法可告知我们当前哪一个页面被选中。         */        mViewPager.setOnPageChangeListener(new OnPageChangeListener() {            @Override            public void onPageSelected(int position) {                Crime crime = mCrimes.get(position);                setTitle(crime.getTitle());            }            @Override            public void onPageScrolled(int position, float posOffset, int posOffsetPixels) {            }            @Override            public void onPageScrollStateChanged(int state) {            }        });        UUID crimeId = (UUID) getIntent().getSerializableExtra(CrimeFragment.EXTRA_CRIME_ID);        for (int i = 0; i < mCrimes.size(); i++) {            if(mCrimes.get(i).getId().equals(crimeId)){                mViewPager.setCurrentItem(i);                break;            }        }    }}

ViewPager的工作原理

为什么选择使用ViewPager而不是AdapterView呢?AdapterView有一个用起来和ViewPager差不多的Gallery子类,为什么不用它呢?

由于无法使用现有的Fragment,在应用中,如使用AdapterView,则需要处理大量的内部实现工作。Adapter需要我们及时地提供View。然而,决定Fragment视图何时创建的是FragmentManager,而不是我们。所以,当Gallery要求提供Fragment视图时,我们无法立即创建Fragment视并提供其视图。

ViewPager使用的是PagerAdapter,而非原来的Adapter,PagerAdapter要比Adapter复杂的多,因为要处理更多的视图管理相关工作。PagerAdapter中代替可返回视图的getView(…)方法,采用了如下方法:

public Object instantiateItem(ViewGroup container, int position)
public void destroyItem(ViewGroup container, int position,Object object)
public boolean isViewFromObject(View view, Object object)

instantiateItem(ViewGroup, int)方法告诉PagerAdapter创建指定位置的列表项视图,然后将其添加ViewGroup给视图容器,而destroyItem(ViewGroup, int ,Object)方法则告诉PagerAdapter销毁已建视图。注意,instantiateItem(ViewGroup, int)方法对何时创建视图并无要求。因此,PagerAdapter可自行决定何时创建视图。

视图创建完成后,ViewPager会在某个时点注意它。为确定该视图所属的对象,ViewPager会调用isViewFromObject(View, Object)方法。这里,Object参数是instantiateItem(ViewGroup, int)方法返回的对象。因此,假设ViewPager调用instantiateItem(ViewGroup, 5)方法返回一个A对象,那么,只要传入参数是第5个对象的视图,isViewFromObject(View, Object)方法则应返回true,否则会返回false。

对ViewPager来说,这是一个复杂的过程,但对于PagerAdapter来说,这算不上什么,因为PagerAdapter只要能够创建、销毁视图以及识别视图来自那个对象即可。这样宽松的要求使得PagerAdapter能够比较自由地通过instantiateItem(ViewGroup, int)方法创建并添加新的Fragment,然后返回可以跟踪管理的FragmentObject。以下是isViewFromObject(View, Object)方法的具体实现。

@Overridepublic boolean isViewFromObject(View view, Object object) {    return ((Fragment)object).getView() == view;}

代码地址

0 0