Android 中使用ViewPager制作圓角banner+自動(dòng)輪播+無限滑動(dòng)+點(diǎn)擊事件

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

先來看效果圖


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

思路:無限滑動(dòng)其實(shí)是左右兩邊各多出對應(yīng)序號(hào)的相同頁面,如下有5個(gè)頁面,當(dāng)當(dāng)前頁面為第一個(gè)頁面時(shí)(序號(hào)3)迅速設(shè)置當(dāng)前頁面為第四個(gè)頁面(序號(hào)也是3的相同頁面)ViewPager.setCurrentItem(3,false)設(shè)置無動(dòng)畫切換,同理當(dāng)當(dāng)前頁面為第五頁面時(shí),切換當(dāng)前頁面為第二個(gè)相同頁面(序號(hào)1)ViewPager.setCurrentItem(1,false)

點(diǎn)擊事件在adapter里面


具體的操作:先給ViewPager.addOnPageChangeListener,(如果不了解可以先看看這篇文章https://www.cnblogs.com/Dionexin/p/5727297.html)接著在onPageScrollStateChanged()方法中實(shí)現(xiàn)

當(dāng)監(jiān)聽到當(dāng)前頁面為第一個(gè)或最后一個(gè)時(shí),便會(huì)執(zhí)行切換當(dāng)前頁面操作:/*無滑動(dòng)動(dòng)畫,直接跳轉(zhuǎn)*/? ?vp_Banner.setCurrentItem(pageIndex, false);??


實(shí)現(xiàn)圓角:主要有以下類,可以自定義圓角view 和圓形view ,主要是以下三個(gè)類,

ViewStyleSetter、RoundViewOutlineProvider、OvalViewOutlineProvider。

使用的時(shí)候只需要實(shí)例化ViewStyleSetter對象,調(diào)用里面的setRound(float radius) 和 setOval() 方法實(shí)現(xiàn)圓角或者圓形;

原文:https://blog.csdn.net/zhqw_csdn/article/details/82120451 ,原文寫的很詳細(xì),還有更多實(shí)現(xiàn)的方法,想了解更多可以進(jìn)去加強(qiáng)知識(shí)哦。



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裁剪內(nèi)容區(qū)域

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

}

public void setOval() {

this.mView.setClipToOutline(true);//用outline裁剪內(nèi)容區(qū)域

? ? ? ? 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);

}

/**

* 以矩形的中心點(diǎn)為圓心,較短的邊為直徑畫圓

*

? ? * @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的區(qū)域保存在rect中

? ? ? ? Rect selfRect =new Rect(0,0, rect.right - rect.left, rect.bottom - rect.top);//繪制區(qū)域

? ? ? ? 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輪播無限播放+

* 自動(dòng)播放+

* 圓角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);

/*實(shí)現(xiàn)viewpager自動(dòng)播放效果*/

? ? ? ? ? ? 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代碼創(chuàng)建布局*/

? ? 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設(shè)置布局*/

? ? ? ? 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);

/*設(shè)置初始的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);

}

/*

* 設(shè)置banner展示的view,指示器圖片為默認(rèn)圖片

* @param views banner展示的view

*

* */

? ? private void setView(int views) {

setView(views,indicatorImgRes);

}

/*

* 設(shè)置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) {

/*滑動(dòng)時(shí)*/

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

}

@Override

? ? ? ? ? ? public void onPageSelected(int position) {

/*選中時(shí),指示器跳轉(zhuǎn)*/

? ? ? ? ? ? ? ? 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://靜止?fàn)顟B(tài)

? ? ? ? ? ? ? ? ? ? ? ? startAutoPlay(3000);

break;

case 1://正在滑動(dòng)

? ? ? ? ? ? ? ? ? ? ? ? stopAutoPlay();

break;

case 2://滑動(dòng)完成

? ? ? ? ? ? ? ? ? ? ? ? stopAutoPlay();

break;

}

/*狀態(tài)發(fā)生改變時(shí),viewpager跳轉(zhuǎn)*/

? ? ? ? ? ? ? ? int pageIndex =mPosition;

if (mPosition ==0) {

pageIndex =dot_images.size();

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

/*、如果滑動(dòng)超出總頁面大小*/

? ? ? ? ? ? ? ? ? ? pageIndex =1;

}

if (pageIndex !=mPosition) {

/*無滑動(dòng)動(dòng)畫,直接跳轉(zhuǎn)*/

? ? ? ? ? ? ? ? ? ? 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);

}

}

/*

*設(shè)置指示器的位置

* @param position 當(dāng)前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]);

}

}

}

/*、

*

* 開啟自動(dòng)輪播

*@param period banner的輪播周期

* */

? ? public void startAutoPlay(long period) {

//banner的vp_views大于1時(shí)才允許開啟輪播

? ? ? ? if (vp_Views >1) {

mTimer =new Timer();

TimerTask timerTask =new TimerTask() {

@Override

? ? ? ? ? ? ? ? public void run() {

mHandler.sendEmptyMessage(1);

}

};

mTimer.schedule(timerTask,2000, period);

}

}

/*

* 關(guān)閉自動(dòng)輪播

* */

? ? public void stopAutoPlay() {

if (mTimer !=null) {

mTimer.cancel();

}

}

/*

* 初始化數(shù)據(jù)

*

* */

? ? public void initData(List data) {

mData = data;

}

/*

* 更新數(shù)據(jù)

*

* */

? ? 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實(shí)現(xiàn)onclickListener接口實(shí)現(xiàn)點(diǎn)擊事件

* ②values下面創(chuàng)建ids文件 創(chuàng)建id,在adapter里面的imageView添加監(jiān)聽

* */

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);//向里面?zhèn)鬟f數(shù)據(jù)

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);



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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,001評(píng)論 6 537
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,786評(píng)論 3 423
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,986評(píng)論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,204評(píng)論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,964評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,354評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,410評(píng)論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,554評(píng)論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,106評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,918評(píng)論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,093評(píng)論 1 371
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,648評(píng)論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,342評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,755評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,009評(píng)論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,839評(píng)論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,107評(píng)論 2 375

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,681評(píng)論 25 708
  • 用兩張圖告訴你,為什么你的 App 會(huì)卡頓? - Android - 掘金 Cover 有什么料? 從這篇文章中你...
    hw1212閱讀 12,799評(píng)論 2 59
  • package cn.luxurygroup.mall.common.widget; import android...
    bb930456aae1閱讀 484評(píng)論 0 1
  • 廢話不多說直接上代碼!!!! 一、為View、ListView/GridView綁定長按彈出橫向氣泡菜單,可在it...
    蘇墨白夢覺淚滿青衫濕閱讀 1,209評(píng)論 2 2
  • 夏云已嵯峨 明年躑躅春 楓葉綠未脫 永絕金玉音 遠(yuǎn)驅(qū)愁突兀 守此幽棲地 護(hù)寒添翠幕 寧知后賢心 若為寥落境 夏滿又...
    淺曦諾閱讀 402評(píng)論 0 0