ViewPager实现轮播图功能

先看下效果图

普通轮播图的实现

1.布局文件




    

    

2.activity代码

需要为viewpager设置适配器,适配器继承PagerAdapter,并重写getCount、isViewFromObject、instantiateItem和destroyItem四个方法。

package com.matrix.viewpagerbanner;

import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private List mBannerSrc = new ArrayList<>();
    private ViewPager mViewPager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mBannerSrc.add(R.drawable.banner01);
        mBannerSrc.add(R.drawable.banner02);
        mBannerSrc.add(R.drawable.banner03);
        mBannerSrc.add(R.drawable.banner04);
        mBannerSrc.add(R.drawable.banner05);

        mViewPager = findViewById(R.id.view_pager);
        mViewPager.setAdapter(new MyAdapter());
    }

    class MyAdapter extends PagerAdapter {

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

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

        @NonNull
        @Override
        public Object instantiateItem(@NonNull ViewGroup container, int position) {
            View inflate = LayoutInflater.from(MainActivity.this).inflate(R.layout.item_banner, null);
            ImageView imageView = inflate.findViewById(R.id.image);
            imageView.setImageResource(mBannerSrc.get(position));
            container.addView(inflate);
            return inflate;
        }

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

3.效果图

无限循环轮播图

到此,我们已经完成了最基础的轮播图效果。从上面的效果图可以看出来,我们无法无限往左或往右滑动,即没有实现循环轮播的功能,接下来我们实现此功能,主要通过Integer.MAX_VALUE来实现伪循环。修改activity中的相关代码即可。getCount方法的返回值设置为Integer.MAX_VALUE;instantiateItem方法中代码修改

imageView.setImageResource(mBannerSrc.get(position % mBannerSrc.size())); // 取模

同时设置ViewPager的默认初始值

int pos = Integer.MAX_VALUE / 2 - (Integer.MAX_VALUE / 2 % mBannerSrc.size());
mViewPager.setCurrentItem(pos);

看下效果

自动循环轮播图--Handler

    private Handler mHandler = new Handler(new Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            switch (msg.what) {
                case 100:
                    mViewPager.setCurrentItem(mViewPager.getCurrentItem() + 1);
                    mHandler.sendEmptyMessageDelayed(100, 3000);
                    break;
            }
            return false;
        }
    });
mHandler.sendEmptyMessageDelayed(100, 3000);

带指示器的轮播图

自定义一个指示器控件类DotIndicator,代码如下:

package com.matrix.viewpagerbanner;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

/**
 * 

描述:ViewPager小圆点指示器 dot

*

作者:xc

*

创建时间:9/20 2018

*/ public class DotIndicator extends View { private Paint mForePaint; private Paint mBackgroundPaint; // 圆圈半径 private int mRadius; // 前景 * 坐标 private float foreOffX = 0f; // 数量 private int mNumbers; // 圆心与圆心之间的间距 private float mGapWidth; private int mForeColor; private int mBackgroundColor; public ViewPagerIndicator(Context context) { super(context); } public ViewPagerIndicator(Context context, AttributeSet attrs) { super(context, attrs); TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.ViewPagerIndicator); mForeColor = attributes.getColor(R.styleable.ViewPagerIndicator_foreColor, Color.RED); mBackgroundColor = attributes.getColor(R.styleable.ViewPagerIndicator_backgroundColor, Color.GRAY); mNumbers = attributes.getInt(R.styleable.ViewPagerIndicator_numbers, 4); // mRadius = attributes.getInt(R.styleable.ViewPagerIndicator_radius, 4); mRadius = dpTopx(attributes.getInt(R.styleable.ViewPagerIndicator_radius, 4)); attributes.recycle(); // 回收TypeArray资源 // 初始化画笔 initPaint(); } /** * 初始化画笔 */ private void initPaint() { // 前景圆点画笔 mForePaint = new Paint(); mForePaint.setColor(mForeColor); mForePaint.setStyle(Paint.Style.FILL); // 背景圆点画笔 mBackgroundPaint = new Paint(); mBackgroundPaint.setColor(mBackgroundColor); mBackgroundPaint.setStyle(Paint.Style.FILL); // 圆点间距(圆心到圆心的距离) mGapWidth = (float) (3.0 * mRadius); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); for (int i = 0; i < mNumbers; i++) { // 起始x轴坐标 = 半径 + i * 间隔;y轴坐标不变为半径 canvas.drawCircle(mRadius + i * mGapWidth, mRadius, mRadius, mBackgroundPaint); } canvas.drawCircle(mRadius + foreOffX, mRadius, mRadius, mForePaint); } /** * @param position 索引位置 * @param pec 偏移量 */ public void setOffX(int position, float pec) { // 当前页X坐标 float pagerX = (float) position * mGapWidth; // 计算出偏移 foreOffX = pagerX + mGapWidth * pec; // 重绘 invalidate(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec); int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec); int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec); int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec); //这里就是对wrap_content的支持 if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST) { //这里设定的根据你自己自定义View的情况而定 setMeasuredDimension(2 * mRadius + (mNumbers - 1) * 3 * mRadius, 2 * mRadius); } else if (widthSpecMode == MeasureSpec.AT_MOST) { setMeasuredDimension(2 * mRadius + (mNumbers - 1) * 3 * mRadius, heightSpecSize); } else if (heightSpecMode == MeasureSpec.AT_MOST) { setMeasuredDimension(widthSpecSize, 2 * mRadius); } } public int dpTopx(int values) { float density = getResources().getDisplayMetrics().density; return (int) (values * density + 0.5f); } }

在attrs.xml文件中配置该控件的属性参数



    
        
        
        
        
        
        
        
        
    

修改布局文件




    

        

        

        
    

在activity中为ViewPager控件设置addOnPageChangeListener监听。

    mViewPager.addOnPageChangeListener(new OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int i1) {
                // 设置偏移量,positionOffset值为0.0f--1.0f
                mViewPagerIndicator.setOffX(position % mBannerSrc.size(), positionOffset);
            }

            @Override
            public void onPageSelected(int i) {

            }

            @Override
            public void onPageScrollStateChanged(int i) {

            }
        });

效果图:

画廊效果的实现

在xml布局文件中使用android:clipChildren="false"属性。默认情况下,在ViewGroup绘制前,子View都被限制在它们自己的区域内无法得到绘制,这可以让ViewGroup通过重写该方法来实现一些动画效果,该值默认为true。子控件和父控件必须都添加才有效。同时在xml文件中为ViewPager设置layout_marginLeft和layout_marginRight属性,代码中设置setPageMargin方法。

ViewPager实现轮播图功能_第1张图片

修改后的xml文件

 




    

        

        

        
    

修改后的activity代码

package com.matrix.viewpagerbanner;

import android.os.Bundle;
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private List mBannerSrc = new ArrayList<>();
    private ViewPager mViewPager;
    private ViewPagerIndicator mViewPagerIndicator;
    private Handler mHandler = new Handler(new Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            switch (msg.what) {
                case 100:
                    mViewPager.setCurrentItem(mViewPager.getCurrentItem() + 1);
                    mHandler.sendEmptyMessageDelayed(100, 3000);
                    break;
            }
            return false;
        }
    });

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mViewPagerIndicator = findViewById(R.id.banner_indicator);

        mBannerSrc.add(R.drawable.banner01);
        mBannerSrc.add(R.drawable.banner02);
        mBannerSrc.add(R.drawable.banner03);
        mBannerSrc.add(R.drawable.banner04);
        mBannerSrc.add(R.drawable.banner05);

        mViewPager = findViewById(R.id.view_pager);
        mViewPager.setAdapter(new MyAdapter());
        float density = getResources().getDisplayMetrics().density;
        mViewPager.setPageMargin((int) (10 * density + 0.5f)); // 设置每页之间的间隔,单位:px
        mViewPager.setOffscreenPageLimit(3); // 预加载页数,默认1
        int pos = Integer.MAX_VALUE / 2 - (Integer.MAX_VALUE / 2 % mBannerSrc.size());
        mViewPager.setCurrentItem(pos);

        mHandler.sendEmptyMessageDelayed(100, 3000);

        mViewPager.addOnPageChangeListener(new OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int i1) {
                // 设置偏移量,positionOffset值为0.0f--1.0f
                mViewPagerIndicator.setOffX(position % mBannerSrc.size(), positionOffset);
            }

            @Override
            public void onPageSelected(int i) {

            }

            @Override
            public void onPageScrollStateChanged(int i) {

            }
        });

    }

    class MyAdapter extends PagerAdapter {

        @Override
        public int getCount() {
            return Integer.MAX_VALUE;
        }

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

        @NonNull
        @Override
        public Object instantiateItem(@NonNull ViewGroup container, int position) {
            View inflate = LayoutInflater.from(MainActivity.this).inflate(R.layout.item_banner, null);
            ImageView imageView = inflate.findViewById(R.id.image);
            imageView.setImageResource(mBannerSrc.get(position % mBannerSrc.size())); // 取模
            container.addView(inflate);
            return inflate;
        }

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

最后效果图

完整DEMO下载

你可能感兴趣的:(Android)