Android使用ViewPager实现图片轮播和手势滑动

ViewPager常用来实现图片的轮播,比如淘宝首页,会把一些促销的商品的图片和描述信息来回的播放,这就是典型的使用ViewPager实现的。


ViewPager属于布局管理器,允许用户通过页面翻转查看左右的数据,下面通过一个实例来讲解ViewPager实现图片轮播和手势滑动,效果图如上:


1.布局文件如下(TextView用来显示图片下的文字,ll_point用来存放文字下面的小圆点):

<span style="font-size:18px;"><?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.administrator.viewpager.MainActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="180dp">
        <android.support.v4.view.ViewPager
            android:id="@+id/vp"
            android:layout_width="match_parent"
            android:layout_height="180dp" />
        
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:orientation="vertical"
            android:layout_alignParentBottom="true"
            android:padding="5dp"
            android:background="#6000"
            android:gravity="center_horizontal">
            <TextView
                android:id="@+id/tv_desc"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="#fff" />
            <LinearLayout
                android:id="@+id/ll_point"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:layout_marginTop="5dp">
            </LinearLayout>

        </LinearLayout>
    </RelativeLayout>
</RelativeLayout></span>

2.MianActivity的代码如下,下面的代码主要是实现图片轮播和手势滑动,同时也提供里一个解决图片轮播到最后一个或滑动到最后一个(或第一个时)停了下来的问题,这个问题对用户体验来说是很糟糕的,所以要解决。同时提供了温习了一下MVC开发模型,这种模型能够让代码显得结构清晰。为了保证代码的连贯性,把代码写在了一个类中。

<span style="font-size:18px;">package com.example.administrator.viewpager;

import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener{
    private ViewPager vp;
    private LinearLayout ll_point;
    private TextView tv_desc;
    private int[] imageResIds; //存放图片资源id的数组
    private ArrayList<ImageView> imageViews; //存放图片的集合
    private String[] contentDescs; //图片内容描述
    private int lastPosition;
    private boolean isRunning = false; //viewpager是否在自动轮询

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //使用M-V-C模型
        //V--view视图
        initViews();
        //M--model数据
        initData();
        //C--control控制器(即适配器)
        initAdapter();
        //开启图片的自动轮询
        new Thread(){
            @Override
            public void run() {
                isRunning = true;
                while(isRunning){
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() { //在子线程中开启子线程
                            //往下翻一页(setCurrentItem方法用来设置ViewPager的当前页)
                            vp.setCurrentItem(vp.getCurrentItem()+1);
                        }
                    });
                }
            }
        }.start();
    }

    /*
        初始化视图
     */
    private void initViews() {
        //初始化放小圆点的控件
        ll_point = (LinearLayout) findViewById(R.id.ll_point);
        //初始化ViewPager控件
        vp = (ViewPager) findViewById(R.id.vp);
        //设置ViewPager的滚动监听
        vp.setOnPageChangeListener(this);
        //显示图片描述信息的控件
        tv_desc = (TextView) findViewById(R.id.tv_desc);
    }

    /*
      初始化数据
     */
    private void initData() {
        //初始化填充ViewPager的图片资源
        imageResIds = new int[]{R.mipmap.aa,R.mipmap.ss,R.mipmap.dd,R.mipmap.ff,R.mipmap.gg};
        //图片的描述信息
        contentDescs = new String[]{
                "厦门特大香烟走私犯外逃14年今被遣返",
                "“机器换人”大潮之下 那些普通工人在想什么?",
                "外媒关注中国\"最美野长城毁容\":文物保护观念落后",
                "男子涉嫌骗取公司1亿资金理财 潜逃境外8天被抓获",
                "国家南海博物馆完成封顶 打造中国南海地标式建筑"
        };
        //保存图片资源的集合
        imageViews = new ArrayList<>();
        ImageView imageView;
        View pointView;
        //循环遍历图片资源,然后保存到集合中
        for (int i = 0; i < imageResIds.length; i++){
            //添加图片到集合中
            imageView = new ImageView(this);
            imageView.setBackgroundResource(imageResIds[i]);
            imageViews.add(imageView);

            //加小白点,指示器(这里的小圆点定义在了drawable下的选择器中了,也可以用小图片代替)
            pointView = new View(this);
            pointView.setBackgroundResource(R.drawable.selectot_bg_point); //使用选择器设置背景
            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(8, 8);
            if (i != 0){
                //如果不是第一个点,则设置点的左边距
                layoutParams.leftMargin = 10;
            }
            pointView.setEnabled(false); //默认都是暗色的
            ll_point.addView(pointView, layoutParams);
        }
    }

    /*
      初始化适配器
     */
    private void initAdapter() {
        ll_point.getChildAt(0).setEnabled(true); //初始化控件时,设置第一个小圆点为亮色
        tv_desc.setText(contentDescs[0]); //设置第一个图片对应的文字
        lastPosition = 0; //设置之前的位置为第一个
        vp.setAdapter(new MyPagerAdapter());
        //设置默认显示中间的某个位置(这样可以左右滑动),这个数只有在整数范围内,可以随便设置
        vp.setCurrentItem(5000000); //显示5000000这个位置的图片
    }

    //界面销毁时,停止viewpager的轮询
    @Override
    protected void onDestroy() {
        super.onDestroy();
        isRunning = false;
    }

    /*
      自定义适配器,继承自PagerAdapter
     */
    class MyPagerAdapter extends PagerAdapter{

        //返回显示数据的总条数,为了实现无限循环,把返回的值设置为最大整数
        @Override
        public int getCount() {
            return Integer.MAX_VALUE;
        }

        //指定复用的判断逻辑,固定写法:view == object
        @Override
        public boolean isViewFromObject(View view, Object object) {
            //当创建新的条目,又反回来,判断view是否可以被复用(即是否存在)
            return view == object;
        }

        //返回要显示的条目内容
        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            //container  容器  相当于用来存放imageView
            //从集合中获得图片
            int newPosition = position % 5; //数组中总共有5张图片,超过数组长度时,取摸,防止下标越界
            ImageView imageView = imageViews.get(newPosition);
            //把图片添加到container中
            container.addView(imageView);
            //把图片返回给框架,用来缓存
            return imageView;
        }

        //销毁条目
        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            //object:刚才创建的对象,即要销毁的对象
            container.removeView((View) object);
        }
    }

    //--------------以下是设置ViewPager的滚动监听所需实现的方法--------
    //页面滑动
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    //新的页面被选中
    @Override
    public void onPageSelected(int position) {
        //当前的位置可能很大,为了防止下标越界,对要显示的图片的总数进行取余
        int newPosition = position % 5;
        //设置描述信息
        tv_desc.setText(contentDescs[newPosition]);
        //设置小圆点为高亮或暗色
        ll_point.getChildAt(lastPosition).setEnabled(false);
        ll_point.getChildAt(newPosition).setEnabled(true);
        lastPosition = newPosition; //记录之前的点
    }

    //页面滑动状态发生改变
    @Override
    public void onPageScrollStateChanged(int state) {

    }
}</span>

3.在drawable目录下实现小圆点的enable两种不同状态时的选择器:

(1) enable为false时的选择器point_disenable.xml:

<span style="font-size:18px;"><?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <corners android:radius="8dp"/>
    <solid android:color="@android:color/darker_gray"/>
</shape></span>


(2) enable为true时的选择器point_enable.xml:

<span style="font-size:18px;"><?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <corners android:radius="8dp"/>
    <solid android:color="#fff"/>
</shape></span>

(3) 然后把两种状态的选择器集中到同一个选择器中point_selector.xml:

<span style="font-size:18px;"><?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_enabled="true"  android:drawable="@drawable/bg_point_enable"/>
    <item android:state_enabled="false"  android:drawable="@drawable/bg_point_disable"/>
</selector></span>

这里提示一点,ViewPager的使用必须要和适配器结合在一起,但ViewPager有自己的适配器,即PagerAdapter,此适配器的实现非常简单,每次的代码都是一个套路,多些两便就会了。


  • 5
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
### 回答1: ViewPager2 可以使用 androidx 库中的 ViewPager2,在 dependencies 中添加 ```Groovy implementation 'androidx.viewpager2:viewpager2:1.0.0' ``` 然后在布局文件中添加 ViewPager2 控件,例如: ```xml <androidx.viewpager2.widget.ViewPager2 android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 接着,在代码中创建 FragmentAdapter,例如: ```Kotlin class MyFragmentAdapter(fragmentManager: FragmentManager, lifecycle: Lifecycle) : FragmentStateAdapter(fragmentManager, lifecycle) { override fun getItemCount(): Int = 3 // Fragment 数量 override fun createFragment(position: Int): Fragment { return when (position) { 0 -> FragmentOne() 1 -> FragmentTwo() 2 -> FragmentThree() else -> throw IndexOutOfBoundsException() } } } ``` 其中,getItemCount 返回 Fragment 数量,createFragment 返回指定位置的 Fragment 对象,例子中返回了三个 FragmentOne、FragmentTwo、FragmentThree。 最后,在 Activity 或 Fragment 中设置 ViewPager2 和 FragmentAdapter,例如: ```Kotlin val viewPager: ViewPager2 = findViewById(R.id.view_pager) val adapter = MyFragmentAdapter(supportFragmentManager, lifecycle) viewPager.adapter = adapter ``` 这样就实现了在 Fragment 之间滑动的功能。 ### 回答2: 要使用ViewPager2在Fragment之间滑动,首先需要在布局文件中定义一个ViewPager2控件,并添加相应的Fragment。 在Activity中,需要先获取ViewPager2控件的实例,并创建一个适配器来管理Fragment的切换。适配器需要继承FragmentStateAdapter,并重写getItemCount()方法和createFragment()方法。 getItemCount()方法返回Fragment的数量。 createFragment()方法根据position返回相应位置的Fragment。 然后,将适配器设置给ViewPager2控件。 接下来,就可以通过手势滑动或者使用setCurrentItem()方法来实现Fragment之间的切换。如果想要禁用滑动,可以使用setUserInputEnabled()方法来设置。 以下是一个简单的示例代码: 在布局文件中: ``` <androidx.viewpager2.widget.ViewPager2 android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 在Activity中: ```java ViewPager2 viewPager = findViewById(R.id.viewPager); FragmentStateAdapter adapter = new MyAdapter(this); viewPager.setAdapter(adapter); // 实现禁用滑动的功能 // viewPager.setUserInputEnabled(false); // 实现手动切换到指定Fragment的功能 // viewPager.setCurrentItem(2, false); ``` 适配器类: ```java private class MyAdapter extends FragmentStateAdapter { public MyAdapter(FragmentActivity fa) { super(fa); } @Override public int getItemCount() { return 3; // 返回Fragment的数量 } @NonNull @Override public Fragment createFragment(int position) { switch (position) { case 0: return new Fragment1(); case 1: return new Fragment2(); case 2: return new Fragment3(); default: return null; } } } ``` 这样,便可以在ViewPager2中实现Fragment之间的滑动切换了。 ### 回答3: ViewPager2 是 Android Support Library 中的一个组件,用于在多个 fragment 之间进行滑动切换。要在 fragment 之间使用 ViewPager2 进行滑动切换,首先需要进行以下几个步骤: 1. 添加依赖:在项目的 build.gradle 文件中添加以下依赖: ``` implementation 'androidx.viewpager2:viewpager2:1.0.0' ``` 2. 创建 Fragment:创建需要滑动切换的多个 fragment,并在它们的布局文件中添加相应的内容。 3. 创建 ViewPager2:在主 Activity 或者容器 fragment 的布局文件中添加 ViewPager2 组件: ```xml <androidx.viewpager2.widget.ViewPager2 android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 4. 创建适配器:创建一个继承自 FragmentStateAdapter 的适配器类,用于管理 fragment 的创建和绑定。在适配器中实现以下两个方法: ```java @Override public int getItemCount() { return fragmentList.size(); } @Override public Fragment createFragment(int position) { return fragmentList.get(position); } ``` 5. 绑定适配器:在主 Activity 或者容器 fragment 的代码中,实例化 ViewPager2,并设置适配器: ```java ViewPager2 viewPager = findViewById(R.id.viewPager); viewPager.setAdapter(new MyAdapter(getSupportFragmentManager(), getLifecycle())); ``` 6. 处理切换事件:可以添加切换事件监听器,监听页面的切换操作,例如: ```java viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { @Override public void onPageSelected(int position) { // 处理页面切换事件 } }); ``` 通过以上步骤,就可以在 fragment 之间使用 ViewPager2 进行滑动切换了。根据实际需求,还可以自定义每个 fragment 的布局和显示内容,以及指示器等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值