ViewPager 的基本用法

使用场景:轮播图 ViewPager + 自定义 PagerAdapter

创建一个页面 VpActivity.java

复制代码
public class VpActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.vp_activity);
        List<String> list = new ArrayList<>();
        for(int i=0;i<5;i++){
            list.add("第"+i+"页");
        }

        ViewPager vp = (ViewPager) findViewById(R.id.vp_box);
        vp.setAdapter(new MyPageraAdapter(this,list));
        vp.setPageTransformer(false, new DepthPageTransformer());

    }
}
复制代码

创建与之对应的layout文件 :

复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <androidx.viewpager.widget.ViewPager
        android:id="@+id/vp_box"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        ></androidx.viewpager.widget.ViewPager>

</LinearLayout>
复制代码

在这个文件,创建一个 ViewPager的标签 ,基本的工作完成了,接下来就是 自定义一个PagerAdapter.java

复制代码
public class MyPageraAdapter extends PagerAdapter {

    private Context mContext;
    private List<String> mData;

    public MyPageraAdapter(Context context,List<String> list){
        mContext = context;
        mData = list;
    }

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

    @Override
    public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
        //return false;
        return view == object;
    }

    @NonNull
    @Override
    public Object instantiateItem(@NonNull ViewGroup container, int position) {
        //return super.instantiateItem(container, position);
        View view = View.inflate(mContext,R.layout.item_base,null);

        TextView tv = (TextView) view.findViewById(R.id.tv);
        tv.setText(mData.get(position));
        container.addView(view);
        return view;

    }

    @Override
    public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
        //super.destroyItem(container, position, object);
        container.removeView((View)object);
    }
}
复制代码

item_base.xml 这个文件中简单了放了一个 TextView。

复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" 
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/tv"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:textSize="40dp"
        android:gravity="center"
        android:background="#3F51B5"
        />
</LinearLayout>
复制代码

这里还有一个要注意的  vp.setPageTransformer(false,new DepthPageTransformer()) 这个是给 ViewPager添加了一个页面切换效果。

复制代码
public class DepthPageTransformer implements ViewPager.PageTransformer {
    private static final float MIN_SCALE=0.75f;
    @Override
    public void transformPage(@NonNull View page, float position) {
        
        int pageWidth = page.getWidth();
        if(position < -1){
            page.setAlpha(0);
        }else if(position<=0){
            page.setAlpha(1);
            page.setTranslationX(0);
            page.setScaleX(1);
            page.setScaleY(1);
        }else if(position<=1){
            page.setAlpha(1-position);
            page.setTranslationX(pageWidth * -position);
            float scaleFactor = MIN_SCALE +(1-MIN_SCALE)*(1-Math.abs(position));
            page.setScaleX(scaleFactor);
            page.setScaleY(scaleFactor);
        }else{
            page.setAlpha(0);
        }
    }
}
复制代码

以上就是全部的代码啦!

引用一下大神对 PagerAdapter的注释;作为初学者这个很重要。

子类继承PagerAdapter需要实现方法说明


Object instantiateItem(ViewGroup container, int position)


一句话:要显示的页面或需要缓存的页面,会调用这个方法进行布局的初始化。


这个方法是ViewPager需要加载某个页面时调用,container就是ViewPager自己,position页面索引;
我们需要实现的是添加一个view到container中,然后返回一个跟这个view能够关联起来的对象,这个对象可以是view自身,也可以是其他对象(比如FragmentPagerAdapter返回的就是一个Fragment),关键是在isViewFromObject能够将view和这个object关联起来


void destroyItem(ViewGroup container, int position, Object object)


一句话:当ViewPager需要销毁一个页面时调用,我们需要将position对应的view从container中移除。


这时参数除了position就只有object,其实就是上面instantiateItem方法返回的对象,这时要通过object找到对应的View,然后将其移除掉,如果你的instantiateItem方法返回的就是View,这里就直接强转成View移除即可:container.removeView((View) object);如果不是,一般会自己创建一个List缓存view列表,然后根据position从List中找到对应的view移除;(当然你也可以不移除,内存泄漏)。

FragmentPagerAdapter的实现是:mCurTransaction.detach((Fragment)object),其实也就是将fragemnt的view从container中移除


isViewFromObject(View view, Object object)


一句话:这个方法用于判断是否由对象生成界面,官方建议直接返回 return view == object;
从名称理解起来像是判断view是否来自object,跟进一步解释应该是上面instantiateItem方法中
向container中添加的view和方法返回的对象两者之间一对一的关系;因为在ViewPager内部有个方法叫infoForChild,
这个方法是通过view去找到对应页面信息缓存类ItemInfo(内部调用了isViewFromObject),如果找不到,说明这个view是个野孩子,ViewPager会认为不是Adapter提供的View,所以这个View不会显示出来;
总结一下:isViewFromObject 方法是让view和object(内部为ItemInfo)一一对应起来


int getItemPosition(Object object)


该方法是判断当前object对应的View是否需要更新,在调用notifyDataSetChanged时会间接触发该方法,
如果返回POSITION_UNCHANGED表示该页面不需要更新,如果返回POSITION_NONE则表示该页面无效了,需要销毁并触发destroyItem方法(并且有可能调用instantiateItem重新初始化这个页面)

 

 

posted @   星锋  阅读(378)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
点击右上角即可分享
微信分享提示