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重新初始化这个页面)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!