android ViewPager實(shí)現(xiàn)自動(dòng)無(wú)限輪播和下方向?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)聽(tīng)器 */ 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); } }; // 開(kāi)始 輪播 mHandler.postDelayed(mRunnable, 3 * 1000); } /** * 當(dāng)頁(yè)面在滑動(dòng)了調(diào)用 * * @param position 當(dāng)前頁(yè)面,即點(diǎn)擊滑動(dòng)的頁(yè)面 * @param positionOffset 當(dāng)前頁(yè)面偏移的百分比 * @param positionOffsetPixels 當(dāng)前頁(yè)面偏移的像素位置 */ @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 說(shuō)明正在從第一個(gè)圖片想最后一個(gè)滑動(dòng),那么保持 向?qū)У臓顟B(tài)為不動(dòng) if (position == 0) { params.leftMargin = 0; // 如果滑動(dòng)距離超過(guò)了 最大邊距,那么將最大邊距賦值給 紅點(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://什么都沒(méi)做 空閑狀態(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è)的第一頁(yè)開(kāi)始播放。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Kotlin協(xié)程Channel特點(diǎn)及使用細(xì)節(jié)詳解
這篇文章主要為大家介紹了Kotlin協(xié)程Channel特點(diǎn)及使用細(xì)節(jié)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12Android編程實(shí)現(xiàn)簡(jiǎn)單文件瀏覽器功能
這篇文章主要介紹了Android編程實(shí)現(xiàn)簡(jiǎn)單文件瀏覽器功能,結(jié)合實(shí)例形式分析了Android文件管理器的布局、文件與目錄的遍歷、權(quán)限控制等相關(guān)操作技巧,需要的朋友可以參考下2018-01-01Android使用PowerImageView實(shí)現(xiàn)播放強(qiáng)大的ImageView動(dòng)畫(huà)效果
今天我們就來(lái)編寫(xiě)一個(gè)PowerImageView控件,讓它既能支持ImageView控件原生的所有功能,同時(shí)還可以播放GIF圖片2018-05-05Android Studio安裝配置、環(huán)境搭建詳細(xì)步驟及基本使用的詳細(xì)教程
這篇文章主要介紹了Android Studio安裝配置、環(huán)境搭建詳細(xì)步驟及基本使用的詳細(xì)教程,需要的朋友可以參考下2020-03-03Android Material Design 陰影實(shí)現(xiàn)示例
這篇文章主要介紹了Android Material Design 陰影實(shí)現(xiàn)示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-04-04Android基于OkHttpUtils網(wǎng)絡(luò)請(qǐng)求的二次封裝
這篇文章主要介紹了Android基于OkHttpUtils網(wǎng)絡(luò)請(qǐng)求的二次封裝,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03Android使用ViewFlipper實(shí)現(xiàn)圖片上下自動(dòng)輪播的示例代碼
這篇文章主要介紹了Android使用ViewFlipper實(shí)現(xiàn)圖片上下自動(dòng)輪播的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-05-05