Android 中使用ViewPager制作圆角banner+自动轮播+无限滑动+点击事件

本人新手一枚,请大家多多指教!!!

先来看效果图


首先自定义一个RelativeLayout,里面添加viewpager,及其所需要的banner底部描述的TextView 和指示器(imageview)

思路:无限滑动其实是左右两边各多出对应序号的相同页面,如下有5个页面,当当前页面为第一个页面时(序号3)迅速设置当前页面为第四个页面(序号也是3的相同页面)ViewPager.setCurrentItem(3,false)设置无动画切换,同理当当前页面为第五页面时,切换当前页面为第二个相同页面(序号1)ViewPager.setCurrentItem(1,false)

点击事件在adapter里面


具体的操作:先给ViewPager.addOnPageChangeListener,(如果不了解可以先看看这篇文章https://www.cnblogs.com/Dionexin/p/5727297.html)接着在onPageScrollStateChanged()方法中实现

当监听到当前页面为第一个或最后一个时,便会执行切换当前页面操作:/*无滑动动画,直接跳转*/   vp_Banner.setCurrentItem(pageIndex, false);  


实现圆角:主要有以下类,可以自定义圆角view 和圆形view ,主要是以下三个类,

ViewStyleSetter、RoundViewOutlineProvider、OvalViewOutlineProvider。

使用的时候只需要实例化ViewStyleSetter对象,调用里面的setRound(float radius) 和 setOval() 方法实现圆角或者圆形;

原文:https://blog.csdn.net/zhqw_csdn/article/details/82120451 ,原文写的很详细,还有更多实现的方法,想了解更多可以进去加强知识哦。



package com.example.his.cloudlibaray.utils;

import android.support.annotation.RequiresApi;

import android.view.View;

/*、

*

* 自定义圆角view*/

public class ViewStyleSetter {

private ViewmView;

public ViewStyleSetter(View view) {

this.mView = view;

}

public void setRound(float radius) {

this.mView.setClipToOutline(true);//用outline裁剪内容区域

        this.mView.setOutlineProvider(new RoundViewOutlineProvider(radius));

}

public void setOval() {

this.mView.setClipToOutline(true);//用outline裁剪内容区域

        this.mView.setOutlineProvider(new OvalViewOutlineProvider());

}

public void clearShapeStyle() {

this.mView.setClipToOutline(false);

}

}

package com.example.his.cloudlibaray.utils;

import android.graphics.Outline;

import android.graphics.Rect;

import android.view.View;

import android.view.ViewOutlineProvider;

/*、

*

* 圆角绘制*/

public class OvalViewOutlineProviderextends ViewOutlineProvider {

public OvalViewOutlineProvider() {

}

@Override

    public void getOutline(final View view,final Outline outline) {

Rect selfRect;

Rect rect =new Rect();

view.getGlobalVisibleRect(rect);

selfRect = getOvalRect(rect);

outline.setOval(selfRect);

}

/**

* 以矩形的中心点为圆心,较短的边为直径画圆

*

    * @param rect

    * @return

    */

    private Rect getOvalRect(Rect rect) {

int width = rect.right - rect.left;

int height = rect.bottom - rect.top;

int left, top, right, bottom;

int dW = width /2;

int dH = height /2;

if (width > height) {

left = dW - dH;

top =0;

right = dW + dH;

bottom = dH *2;

}else {

left = dH - dW;

top =0;

right = dH + dW;

bottom = dW *2;

}

return new Rect(left, top, right, bottom);

}

}

package com.example.his.cloudlibaray.utils;

import android.graphics.Outline;

import android.graphics.Rect;

import android.view.View;

import android.view.ViewOutlineProvider;

/*、

*

* 圆角矩形绘制*/

public class RoundViewOutlineProviderextends ViewOutlineProvider {

private float mRadius;//圆角弧度

    public RoundViewOutlineProvider(float radius) {

this.mRadius = radius;

}

@Override

    public void getOutline(View view, Outline outline) {

Rect rect =new Rect();

view.getGlobalVisibleRect(rect);//将view的区域保存在rect中

        Rect selfRect =new Rect(0,0, rect.right - rect.left, rect.bottom - rect.top);//绘制区域

        outline.setRoundRect(selfRect,mRadius);

}

}

全部代码:

package com.example.his.cloudlibaray.model;

import android.annotation.SuppressLint;

import android.content.Context;

import android.graphics.Canvas;

import android.graphics.Paint;

import android.graphics.PaintFlagsDrawFilter;

import android.graphics.Path;

import android.graphics.PorterDuffXfermode;

import android.graphics.Rect;

import android.graphics.RectF;

import android.os.Handler;

import android.os.Message;

import android.support.v4.view.ViewPager;

import android.util.AttributeSet;

import android.util.Log;

import android.view.Gravity;

import android.view.View;

import android.view.ViewGroup;

import android.widget.ImageView;

import android.widget.LinearLayout;

import android.widget.RelativeLayout;

import android.widget.TextView;

import com.example.his.cloudlibaray.R;

import java.util.ArrayList;

import java.util.List;

import java.util.Timer;

import java.util.TimerTask;

import com.example.his.cloudlibaray.activity.BannerDescribe;

import com.example.his.cloudlibaray.model.CloudLibrary.CloudLibraryData.Topic;

import com.example.his.cloudlibaray.utils.Utils;

import com.example.his.cloudlibaray.utils.ViewStyleSetter;

/*

* banner轮播无限播放+

* 自动播放+

* 圆角view

*

* */

public class BannerViewextends RelativeLayout {

private final StringTAG = BannerView.class.getSimpleName();

private int mPosition =1;

private ContextmContext;

public ViewPagervp_Banner;

private LinearLayoutll_indicator;//指示器

/*Banner 展示的view*/

    private int vp_Views =5;

private Listdot_images =new ArrayList<>();

private ListmData;

/*指示器的图片资源*/

    private int[]indicatorImgRes = {R.drawable.indicator_off, R.drawable.indicator_on};

private TimermTimer;

@SuppressLint("HandlerLeak")

private HandlermHandler =new Handler() {

@Override

        public void handleMessage(Message msg) {

super.handleMessage(msg);

/*实现viewpager自动播放效果*/

            vp_Banner.setCurrentItem(mPosition +1);

Log.d(TAG,"页面的大小: " +vp_Banner.getChildCount());

Log.d(TAG,"handleMessage: " +mPosition);

}

};

private IndexViewPagerAdapterbannerAdapter;

private TextViewbannerTv;

public BannerView(Context context, List data) {

super(context);

mData = data;

initView(context);

}

public BannerView(Context context, AttributeSet attrs) {

super(context, attrs);

initView(context);

}

public BannerView(Context context, AttributeSet attrs,int defStyleAttr) {

super(context, attrs, defStyleAttr);

mContext = context;

initView(context);

}

/*用java代码创建布局*/

    private void initView(Context context) {

mContext = context;

vp_Banner =new ViewPager(mContext);

LinearLayout.LayoutParams vp_param =new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);

vp_Banner.setLayoutParams(vp_param);

/*banner底部详情线性布局*/

        ll_indicator =new LinearLayout(mContext);

RelativeLayout.LayoutParams dot_param =new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);

dot_param.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);

dot_param.setMargins(0,0,0,0);

/*给ll_indicator设置布局*/

        ll_indicator.setLayoutParams(dot_param);

ll_indicator.setOrientation(LinearLayout.HORIZONTAL);

ll_indicator.setGravity(Gravity.CENTER_HORIZONTAL);

ll_indicator.setBackgroundResource(R.color.trans_gray);

bannerTv =new TextView(mContext);

LinearLayout.LayoutParams bannerTvlp =new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT);

bannerTvlp.weight =1;

bannerTv.setTextSize(Utils.sp2px(mContext,6));

bannerTv.setGravity(CENTER_HORIZONTAL);

/*设置初始的banner描述*/

        bannerTv.setText(mData.get(0).getDescribe());

bannerTv.setTextColor(mContext.getResources().getColor(android.R.color.white));

ll_indicator.addView(bannerTv, bannerTvlp);

/*添加view到布局上面*/

        this.addView(vp_Banner);

this.addView(ll_indicator);

setView(vp_Views);

startAutoPlay(3000);

setCorner(20);

}

/*

* 设置banner展示的view,指示器图片为默认图片

* @param views banner展示的view

*

* */

    private void setView(int views) {

setView(views,indicatorImgRes);

}

/*

* 设置banner展示的图片和指示器的图片

*

*

* */

    private void setView(int views,int[] indicatorRes) {

if (views !=0) {

vp_Views = views;

}

bannerAdapter =new IndexViewPagerAdapter(mContext,mData);

vp_Banner.setAdapter(bannerAdapter);

vp_Banner.setOffscreenPageLimit(1);

vp_Banner.setCurrentItem(1);

vp_Banner.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {

@Override

            public void onPageScrolled(int i,float v,int i1) {

/*滑动时*/

                bannerTv.setText(mData.get(i).getDescribe());

}

@Override

            public void onPageSelected(int position) {

/*选中时,指示器跳转*/

                mPosition = position;

int pageIndex =mPosition;

if (mPosition ==0) {

pageIndex =dot_images.size();

}else if (mPosition ==dot_images.size() +1) {

pageIndex =1;

}

setIndicator(pageIndex);

}

@Override

            public void onPageScrollStateChanged(int i) {

switch (i) {

case 0://静止状态

                        startAutoPlay(3000);

break;

case 1://正在滑动

                        stopAutoPlay();

break;

case 2://滑动完成

                        stopAutoPlay();

break;

}

/*状态发生改变时,viewpager跳转*/

                int pageIndex =mPosition;

if (mPosition ==0) {

pageIndex =dot_images.size();

}else if (mPosition ==dot_images.size() +1) {

/*、如果滑动超出总页面大小*/

                    pageIndex =1;

}

if (pageIndex !=mPosition) {

/*无滑动动画,直接跳转*/

                    vp_Banner.setCurrentItem(pageIndex,false);

return;

}

}

});

/*加载指示器*/

        if (indicatorRes !=null && indicatorRes.length >=2) {

indicatorImgRes = indicatorRes;

}

for (int i =0; i

ImageView imageView =new ImageView(mContext);

if (i ==0) {

imageView.setBackgroundResource(indicatorImgRes[1]);

}else {

imageView.setBackgroundResource(indicatorImgRes[0]);

}

dot_images.add(imageView);

LinearLayout.LayoutParams lp =new LinearLayout.LayoutParams(Utils.dip2px(mContext,5), Utils.dip2px(mContext,5));

int margin_h = (int) (0.016 *mContext.getResources().getDisplayMetrics().widthPixels);

int margin_v = (int) (0.02 *mContext.getResources().getDisplayMetrics().widthPixels);

lp.setMargins(Utils.dip2px(mContext,2), margin_v, Utils.dip2px(mContext,2), margin_v);

if (i == (vp_Views -2)) {

lp.setMargins(Utils.dip2px(mContext,2), margin_v, margin_h, margin_v);

}

ll_indicator.addView(imageView, lp);

}

}

/*

*设置指示器的位置

* @param position 当前banner所在的位置

* */

    private void setIndicator(int position) {

for (int i =0; i

if (position == i +1) {

/*on*/

                dot_images.get(i).setBackgroundResource(indicatorImgRes[1]);

}else {

/*off*/

                dot_images.get(i).setBackgroundResource(indicatorImgRes[0]);

}

}

}

/*、

*

* 开启自动轮播

*@param period banner的轮播周期

* */

    public void startAutoPlay(long period) {

//banner的vp_views大于1时才允许开启轮播

        if (vp_Views >1) {

mTimer =new Timer();

TimerTask timerTask =new TimerTask() {

@Override

                public void run() {

mHandler.sendEmptyMessage(1);

}

};

mTimer.schedule(timerTask,2000, period);

}

}

/*

* 关闭自动轮播

* */

    public void stopAutoPlay() {

if (mTimer !=null) {

mTimer.cancel();

}

}

/*

* 初始化数据

*

* */

    public void initData(List data) {

mData = data;

}

/*

* 更新数据

*

* */

    public void updateData(List data) {

bannerAdapter.setData(data);

bannerAdapter.notifyDataSetChanged();

}

public void setCorner(float angle){

ViewStyleSetter viewStyleSetter =new ViewStyleSetter(this);

viewStyleSetter.setRound(angle);

}

}


adapter

package com.example.his.cloudlibaray.model;

import android.content.Context;

import android.content.Intent;

import android.support.annotation.NonNull;

import android.support.v4.view.PagerAdapter;

import android.util.Log;

import android.view.View;

import android.view.ViewGroup;

import android.widget.ImageView;

import android.widget.Toast;

import com.bumptech.glide.Glide;

import com.example.his.cloudlibaray.R;

import com.example.his.cloudlibaray.activity.BannerDescribe;

import com.example.his.cloudlibaray.model.CloudLibrary.CloudLibraryData.Topic;

import java.util.List;

/*

* 主页面viewpager的adapter

*

* ①利用adapter实现onclickListener接口实现点击事件

* ②values下面创建ids文件 创建id,在adapter里面的imageView添加监听

* */

public class IndexViewPagerAdapterextends PagerAdapterimplements View.OnClickListener{

private final StringTAG = IndexViewPagerAdapter.class.getSimpleName();

private ContextmContext;

private ListmUrlList;

private int[]imageIds={R.id.banner_image_3,R.id.banner_image_1,R.id.banner_image_2,R.id.banner_image_3,R.id.banner_image_1};

public IndexViewPagerAdapter(Context context,List urlList) {

mContext = context;

mUrlList = urlList;

}

@Override

    public int getCount() {

return mUrlList.size();

}

@NonNull

@Override

    public Object instantiateItem(@NonNull ViewGroup container,int position) {

ImageView imageView =new ImageView(mContext);

if (!(position ==0 || position ==4)){

imageView.setId(imageIds[position]);

}

imageView.setOnClickListener(this);

imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);

imageView.setImageResource(R.drawable.home_scroll_default);

Log.d(TAG,"instantiateItem: 图片的路径"+mUrlList.get(position).getImageurl());

Glide.with(mContext)

.load(mUrlList.get(position).getImageurl())

.placeholder(R.drawable.home_scroll_default)

.error(R.drawable.home_scroll_default)

.into(imageView);

container.addView(imageView);

return imageView;

}

@Override

    public void destroyItem(@NonNull ViewGroup container,int position,@NonNull Object object) {

container.removeView((View)object);

}

public void setData(List data ){

this.mUrlList = data;

}

@Override

    public boolean isViewFromObject(@NonNull View view,@NonNull Object o) {

return view == o;

}

@Override

    public void onClick(View v) {

switch (v.getId()){

case R.id.banner_image_1:

Intent intent =new Intent(mContext,BannerDescribe.class);

mContext.startActivity(intent);

break;

case R.id.banner_image_2:

Toast.makeText(mContext,"2",Toast.LENGTH_SHORT).show();

break;

case R.id.banner_image_3:

Toast.makeText(mContext,"3",Toast.LENGTH_SHORT).show();

break;

}

}

}

values下的ids.xml文件

<?xml version="1.0" encoding="utf-8"?>

<resources>

    <item name="banner_image_1" type="id"/>

    <item name="banner_image_2" type="id"/>

    <item name="banner_image_3" type="id"/>

</resources>


使用


/*初始化自定义的banner*/

mBannerView =new BannerView(getContext(),mTopicList);//向里面传递数据

RelativeLayout.LayoutParams banner_rl =new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, Utils.dip2px(getContext(),150));

banner_rl.addRule(RelativeLayout.CENTER_IN_PARENT);

banner_rl.setMargins(Utils.dip2px(getContext(),10),0,Utils.dip2px(getContext(),10),0);

mRl.addView(mBannerView,banner_rl);



写的不好,希望多多指教!!!!!!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容