android ViewPager實(shí)現(xiàn)自動(dòng)無限輪播和下方向?qū)A點(diǎn)
一、布局
小圓點(diǎn)形狀的生成shape.xml文件
使用空心還是實(shí)心的把對(duì)應(yīng)的注釋去掉就可以了.
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" android:useLevel="false"> <!-- 實(shí)心圓 <solid android:color="#F00"/> --> <!-- 空心圓 <stroke android:width="1dp" android:color="@android:color/black"/> --> <size android:width="8dp" android:height="8dp"/> </shape>
輪播的ViewPager和向?qū)A點(diǎn)的 布局文件XML
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="200dp">
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/hometab_vp"
android:layout_width="match_parent"
android:layout_height="200dp">
</android.support.v4.view.ViewPager>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="20dp"
>
<LinearLayout
android:id="@+id/ll_dot"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/shape_guide_dot_default"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:src="@drawable/shape_guide_dot_default"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:src="@drawable/shape_guide_dot_default"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:src="@drawable/shape_guide_dot_default"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:src="@drawable/shape_guide_dot_default"/>
</LinearLayout>
<ImageView
android:id="@+id/dot_red"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/shape_guide_dot_solid"/>
</RelativeLayout>
</RelativeLayout>
二,代碼
左右輪播的ViewPager的Adapter
/**
* 輪播 viewpager的adapter
*/
class MyLoopPagerAdapter extends PagerAdapter {
private int[] welcomes;
private Context mContext;
public MyLoopPagerAdapter(int[] welcomes, Context context) {
this.welcomes = welcomes;
mContext = context;
}
// //返回實(shí)際要顯示的圖片數(shù)+2
@Override
public int getCount() {
return welcomes.length + 2;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView iv = new ImageView(mContext);
int realPosition = (position - 1 + welcomes.length) % welcomes.length;
// 設(shè)置背景圖片
iv.setBackgroundResource(welcomes[realPosition]);
container.addView(iv);
return iv;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
//注意不要remove 否則容易閃屏
// container.removeView((ImageView) object);
}
}
添加viewpager的addOnPageChangeListener
/**
* 循環(huán)輪播界面change的 監(jiān)聽器
*/
class MyLoopPageChangeListener implements ViewPager.OnPageChangeListener {
private ViewPager mViewPager;
private LinearLayout mLlDot;
private ImageView dotRed;
private Handler mHandler;
private Runnable mRunnable;
/**
* 初始化 控件 和 handler
*
* @param viewPager
* @param llDot
* @param dotRed
*/
public MyLoopPageChangeListener(ViewPager viewPager, LinearLayout llDot, ImageView dotRed) {
mViewPager = viewPager;
this.mLlDot = llDot;
this.dotRed = dotRed;
initAutoLoop();
}
/**
* 初始化 自動(dòng)輪播 handler 和 runnable
*/
private void initAutoLoop() {
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// LogUtils.e("have received a msg");
int curindex = (mViewPager.getCurrentItem() + 1) % (welcomes.length + 2);
mViewPager.setCurrentItem(curindex, true);
}
};
mRunnable = new Runnable() {
@Override
public void run() {
Message message = new Message();
mHandler.sendMessage(message);
}
};
// 開始 輪播
mHandler.postDelayed(mRunnable, 3 * 1000);
}
/**
* 當(dāng)頁面在滑動(dòng)了調(diào)用
*
* @param position 當(dāng)前頁面,即點(diǎn)擊滑動(dòng)的頁面
* @param positionOffset 當(dāng)前頁面偏移的百分比
* @param positionOffsetPixels 當(dāng)前頁面偏移的像素位置
*/
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// 獲取到 真正圖片所在的位置.
int realPosition = (position - 1 + welcomes.length) % welcomes.length;
// 獲取到紅點(diǎn) 的 layout 參數(shù)
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) dotRed.getLayoutParams();
// 計(jì)算兩個(gè)點(diǎn)之間的距離
int dotDis = mLlDot.getChildAt(1).getLeft() - mLlDot.getChildAt(0).getLeft();
// 計(jì)算總共的左邊距
int totalLeftMargin = (welcomes.length - 1) * dotDis;
// 計(jì)算滑動(dòng)的距離
float dis = realPosition * dotDis + positionOffset * dotDis;
// 設(shè)置 margin_left 的值,
// 如果 position 等于 0 說明正在從第一個(gè)圖片想最后一個(gè)滑動(dòng),那么保持 向?qū)У臓顟B(tài)為不動(dòng)
if (position == 0) {
params.leftMargin = 0;
// 如果滑動(dòng)距離超過了 最大邊距,那么將最大邊距賦值給 紅點(diǎn)的參數(shù)左邊距
} else if (dis > totalLeftMargin) {
params.leftMargin = totalLeftMargin;
// 正常情況 就將滑動(dòng)的距離 直接賦值
} else {
params.leftMargin = (int) dis;
}
// 設(shè)置紅點(diǎn)的 參數(shù)
dotRed.setLayoutParams(params);
// 在position4左滑且左滑positionOffset百分比接近1時(shí),偷偷替換為position1(原本會(huì)滑到position5)
if (position == welcomes.length && positionOffset > 0.99) {
mViewPager.setCurrentItem(1, false);
// 在position1右滑且右滑百分比接近0時(shí),偷偷替換為position4(原本會(huì)滑到position0)
} else if (position == 0 && positionOffset < 0.01) {
mViewPager.setCurrentItem(welcomes.length, false);
}
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
switch (state) {
case 0://什么都沒做 空閑狀態(tài)
break;
case 1://正在滑動(dòng):
// 手動(dòng)滑動(dòng) 取消自動(dòng)滑動(dòng)
mHandler.removeCallbacks(mRunnable);
break;
case 2://滑動(dòng)完畢:
// 繼續(xù) 自動(dòng)滑動(dòng)
mHandler.postDelayed(mRunnable, 3 * 1000);
break;
}
}
}
// 主要的算法參考下圖 int realPosition = (position - 1 + welcomes.length) % welcomes.length;
由下圖可以發(fā)現(xiàn),應(yīng)該初始化ViewPager.setCurrentItem(1);才能從預(yù)設(shè)的第一頁開始播放。

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android Studio使用ButterKnife和Zelezny的方法
這篇文章主要為大家詳細(xì)介紹了Android Studio使用ButterKnife和Zelezny的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04
Android開發(fā)實(shí)現(xiàn)圖片切換APP
這篇文章主要介紹了Android開發(fā)實(shí)現(xiàn)圖片切換APP,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-12-12
基于Flutter實(shí)現(xiàn)圖片選擇和圖片上傳
Flutter?的圖片選擇插件很多,包括了官方的?image_picker,multi_image_picker(基于2.0出了?multi_image_picker2)等等。本文將利用這些插件實(shí)現(xiàn)圖片選擇和圖片上傳,需要的可以參考一下2022-03-03
Kotlin擴(kuò)展函數(shù)及實(shí)現(xiàn)機(jī)制的深入探索
擴(kuò)展函數(shù)與擴(kuò)展屬性的神奇之處在于,可以在不修改原來類的條件下,使用函數(shù)和屬性,表現(xiàn)得就像是屬于這個(gè)類的一樣。下面這篇文章主要給大家介紹了關(guān)于Kotlin擴(kuò)展函數(shù)及實(shí)現(xiàn)機(jī)制的相關(guān)資料,需要的朋友可以參考下2018-06-06
Android Jetpack導(dǎo)航組件Navigation創(chuàng)建使用詳解
這篇文章主要為大家介紹了Android Jetpack導(dǎo)航組件Navigation創(chuàng)建及使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
Android使用Spinner控件實(shí)現(xiàn)下拉列表的案例
今天小編就為大家分享一篇關(guān)于Android使用Spinner控件實(shí)現(xiàn)下拉列表的案例,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-03-03
Android獲取SDcard目錄及創(chuàng)建文件夾的方法
今天小編就為大家分享一篇Android獲取SDcard目錄及創(chuàng)建文件夾的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-08-08
深入學(xué)習(xí)Android?ANR?的原理分析及解決辦法
Android系統(tǒng)中,AMS和WMS會(huì)檢測(cè)App的響應(yīng)時(shí)間,如果App在特定時(shí)間無法相應(yīng)屏幕觸摸或鍵盤輸入時(shí)間,或者特定事件沒有處理完畢,就會(huì)出現(xiàn)ANR。本文將帶領(lǐng)大學(xué)深入學(xué)習(xí)一下ANR的原理及解決辦法,感興趣的同學(xué)可以學(xué)習(xí)一下2021-11-11

