Android ViewPager無(wú)限循環(huán)滑動(dòng)并可自動(dòng)滾動(dòng)完整實(shí)例
對(duì)于ViewPager 廣告頁(yè)這個(gè)功能很多APP都有這個(gè)功能在網(wǎng)上也看過(guò)一些資料,我就在這把我自己完整的實(shí)現(xiàn)方法寫(xiě)出來(lái)吧
基礎(chǔ)的ViewPager:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/top_item" android:orientation="vertical"> <android.support.v4.view.ViewPager android:layout_width="match_parent" android:layout_height="180dp" android:id="@+id/top_vp" ></android.support.v4.view.ViewPager> </LinearLayout>
很簡(jiǎn)單 僅僅是一個(gè)ViewPager
接下來(lái)簡(jiǎn)單的設(shè)置一下ViewPager的Adapter 添加ImageView
public class MainActivity extends AppCompatActivity { private ViewPager topVp; private int[]images = new int[]{R.mipmap.ad0, R.mipmap.ad1, R.mipmap.ad3}; //模擬存放要展示的圖片 private List<ImageView> imageViews ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initImageViews(); initVp(); } /** * 初始化圖片資源 */ private void initImageViews() { imageViews = new ArrayList<>(); for(int i = 0;i<images.length;i++){ ImageView imageView = new ImageView(this); imageView.setScaleType(ImageView.ScaleType.FIT_XY); imageView.setImageResource(images[i]); imageViews.add(imageView); } } private void initVp() { topVp = (ViewPager) findViewById(R.id.top_vp); topVp.setAdapter(new PagerAdapter() { @Override public int getCount() { return imageViews.size(); } @Override public boolean isViewFromObject(View view, Object object) { return view==object; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView(imageViews.get(position)); } @Override public Object instantiateItem(ViewGroup container, int position) { container.addView(imageViews.get(position)); return imageViews.get(position); } }); } }
上述是最基礎(chǔ)的一個(gè)ViewPager 下面我們就在這個(gè)基礎(chǔ)上改造就可以了
實(shí)現(xiàn)無(wú)限循環(huán)滑動(dòng):
這里我事先循環(huán)滑動(dòng)的方式很簡(jiǎn)單 就是把 adapter的count 設(shè)置為一個(gè)很大的值 這樣 讓它滑不到頭 然后切換圖片 就可以實(shí)現(xiàn) 雖然方法比較LOW 但是效果還是可以的
代碼在基礎(chǔ)的ViewPager下修改如下 :
public class MainActivity extends AppCompatActivity { private ViewPager topVp; private int[]images = new int[]{R.mipmap.ad0, R.mipmap.ad1, R.mipmap.ad3}; //模擬存放要展示的圖片 private List<ImageView> imageViews ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initImageViews(); initVp(); } /** * 初始化圖片資源 */ private void initImageViews() { imageViews = new ArrayList<>(); for(int i = 0;i<images.length;i++){ ImageView imageView = new ImageView(this); imageView.setScaleType(ImageView.ScaleType.FIT_XY); imageView.setImageResource(images[i]); imageViews.add(imageView); } } private void initVp() { topVp = (ViewPager) findViewById(R.id.top_vp); topVp.setAdapter(new PagerAdapter() { @Override public int getCount() { // return imageViews.size(); 修改如下 return 10000; } @Override public boolean isViewFromObject(View view, Object object) { return view==object; } @Override public void destroyItem(ViewGroup container, int position, Object object) { // container.removeView(imageViews.get(position%imageViews.size())); 刪除此句 此句不刪除 會(huì)出現(xiàn) 滑動(dòng)中 布局消失的情況 因?yàn)楸灰瞥?此處這樣修改會(huì)影響一些性能。。。。。 } @Override public Object instantiateItem(ViewGroup container, int position) { // container.addView(imageViews.get(position)); // return imageViews.get(position); 修改如下 try { container.addView(imageViews.get(position%imageViews.size())); }catch (Exception e){ } return imageViews.get(position%imageViews.size()); } }); } }
這樣 之后就可以實(shí)現(xiàn)無(wú)限循環(huán)右滑了 但是在程序剛啟動(dòng) 是 無(wú)法向左滑動(dòng)的 要解決 很簡(jiǎn)單 只需要在開(kāi)始的時(shí)候
viewPager.setCurrentItem(1000*imageViews.size());
即可 這樣 就可以 實(shí)現(xiàn) 無(wú)限左右滑了
自動(dòng)定時(shí)循環(huán)滑動(dòng):
下面增加自動(dòng)定時(shí)左右滑動(dòng)的功能
要實(shí)現(xiàn)自動(dòng)滑動(dòng) 最主要的是 實(shí)現(xiàn)定時(shí)器功能我這里使用 Handler+Runnable的方法在上述代碼的基礎(chǔ)上 修改 如下:
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initImageViews(); initVp(); handler = new Handler(); handler.postDelayed(new TimerRunnable(),5000); } class TimerRunnable implements Runnable{ @Override public void run() { int curItem = topVp.getCurrentItem(); topVp.setCurrentItem(curItem+1); if (handler!=null){ handler.postDelayed(this,5000); } } } @Override protected void onDestroy() { super.onDestroy(); handler = null; //此處在Activity退出時(shí)及時(shí) 回收 }
這之后 就可以實(shí)現(xiàn)自動(dòng)滑動(dòng)了
添加左下角圓形小按鈕:
接下來(lái)添加 左下角的導(dǎo)航小原點(diǎn)
首先 修改布局 :
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/top_item" android:orientation="vertical"> <RelativeLayout android:layout_width="match_parent" android:layout_height="180dp"> <android.support.v4.view.ViewPager android:layout_width="match_parent" android:layout_height="180dp" android:id="@+id/top_vp" ></android.support.v4.view.ViewPager> <LinearLayout android:id="@+id/lin_points" android:layout_marginBottom="10dp" android:layout_marginLeft="10dp" android:layout_alignParentBottom="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" > </LinearLayout> </RelativeLayout> </LinearLayout>
我們需要的原點(diǎn) 要放在 LinearLayout布局中
主要原理 就是向這個(gè)LinearLayout中動(dòng)態(tài)添加 小圓點(diǎn) 即可
public class MainActivity extends AppCompatActivity { private ViewPager topVp; private int[]images = new int[]{R.mipmap.ad0, R.mipmap.ad1, R.mipmap.ad3}; //模擬存放要展示的圖片 private List<ImageView> imageViews ; private List<TextView> txtPoints; private LinearLayout lin_points; private Handler handler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); lin_points = (LinearLayout) findViewById(R.id.lin_points); initImageViews(); initVp(); initCircle(); /* * 計(jì)時(shí)器 */ handler = new Handler(); handler.postDelayed(new TimerRunnable(),5000); } /** * 初始化小圓點(diǎn) */ private void initCircle() { txtPoints = new ArrayList<>(); int d = 20; int m = 7; for (int i = 0; i < imageViews.size(); i++) { TextView txt = new TextView(this); if (i == 0) { txt.setBackgroundResource(R.drawable.point_pink); } else { txt.setBackgroundResource(R.drawable.point_grey); } LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(d, d); params.setMargins(m, m, m, m); txt.setLayoutParams(params); txtPoints.add(txt); lin_points.addView(txt); } } class TimerRunnable implements Runnable{ @Override public void run() { int curItem = topVp.getCurrentItem(); topVp.setCurrentItem(curItem+1); changePoints((curItem+1)%imageViews.size()); if (handler!=null){ handler.postDelayed(this,5000); } } } @Override protected void onDestroy() { super.onDestroy(); handler = null; } /** * 初始化圖片資源 */ private void initImageViews() { imageViews = new ArrayList<>(); for(int i = 0;i<images.length;i++){ ImageView imageView = new ImageView(this); imageView.setScaleType(ImageView.ScaleType.FIT_XY); imageView.setImageResource(images[i]); imageViews.add(imageView); } } private void initVp() { topVp = (ViewPager) findViewById(R.id.top_vp); topVp.setAdapter(new PagerAdapter() { @Override public int getCount() { // return imageViews.size(); 修改如下 return 10000; } @Override public boolean isViewFromObject(View view, Object object) { return view==object; } @Override public void destroyItem(ViewGroup container, int position, Object object) { // container.removeView(imageViews.get(position%imageViews.size())); 刪除此句 } @Override public Object instantiateItem(ViewGroup container, int position) { // container.addView(imageViews.get(position)); // return imageViews.get(position); 修改如下 try { container.addView(imageViews.get(position%imageViews.size())); }catch (Exception e){ } return imageViews.get(position%imageViews.size()); } }); topVp.setCurrentItem(imageViews.size()*1000); topVp.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { changePoints((position)%imageViews.size()); } @Override public void onPageScrollStateChanged(int state) { } }); } public void changePoints(int pos) { if (txtPoints != null) { for (int i = 0; i < txtPoints.size(); i++) { if (pos == i) { txtPoints.get(i).setBackgroundResource(R.drawable.point_pink); } else { txtPoints.get(i).setBackgroundResource(R.drawable.point_grey); } } } } }
給ViewPager添加切換動(dòng)畫(huà):
topVp.setPageTransformer(true,new CubeOutTransformer());
調(diào)用 此行代碼 可以添加 后面的TransFormer類(lèi) 是自定義的過(guò)渡效果類(lèi)
控制ViewPager 自動(dòng)切換的速度
ViewPager自身的切換速度是寫(xiě)死的,我們無(wú)法修改,但是我們可以通過(guò)源碼看到,ViewPager的切換速度是通過(guò) Scroller類(lèi) 控制的,而Scroller類(lèi)中是可以設(shè)置過(guò)渡的時(shí)間的,因此 我們可以通過(guò)自己創(chuàng)建一個(gè)Scroller類(lèi) 繼承 Scroller 然后 通過(guò)反射 把ViewPager中的mScroller屬性 設(shè)置成我們自己的可以設(shè)置時(shí)間的Scroller類(lèi)即可
下面是代碼:
public class FixedSpeedScroller extends Scroller { private int mDuration = 1500; public FixedSpeedScroller(Context context) { super(context); } public FixedSpeedScroller(Context context, Interpolator interpolator) { super(context, interpolator); } @Override public void startScroll(int startX, int startY, int dx, int dy, int duration) { // Ignore received duration, use fixed one instead super.startScroll(startX, startY, dx, dy, mDuration); } @Override public void startScroll(int startX, int startY, int dx, int dy) { // Ignore received duration, use fixed one instead super.startScroll(startX, startY, dx, dy, mDuration); } public void setmDuration(int time) { mDuration = time; } public int getmDuration() { return mDuration; } }
反射修改ViewPager屬性:
try { Field field = ViewPager.class.getDeclaredField("mScroller"); field.setAccessible(true); scroller = new FixedSpeedScroller(getActivity()); scroller.setmDuration(1000); field.set(topVp, scroller); } catch (Exception e) { // e.printStackTrace(); System.out.println("aaaaaa錯(cuò)誤啦"); }
這樣就可以控制速度了
好了,Android ViewPager廣告頁(yè)可無(wú)限循環(huán)滑動(dòng)并可自動(dòng)滾動(dòng)帶有小圓點(diǎn)的功能基本就實(shí)現(xiàn)了,具體參數(shù)大家可以自行設(shè)定
- Android 使用viewpager實(shí)現(xiàn)無(wú)限循環(huán)(定時(shí)+手動(dòng))
- Android viewpager中動(dòng)態(tài)添加view并實(shí)現(xiàn)偽無(wú)限循環(huán)的方法
- Android ViewPager無(wú)限循環(huán)實(shí)現(xiàn)底部小圓點(diǎn)動(dòng)態(tài)滑動(dòng)
- Android無(wú)限循環(huán)RecyclerView的完美實(shí)現(xiàn)方案
- Android ViewPager實(shí)現(xiàn)無(wú)限循環(huán)效果
- Android實(shí)現(xiàn)ViewPager無(wú)限循環(huán)效果(一)
- Android實(shí)現(xiàn)帶指示點(diǎn)的自動(dòng)輪播無(wú)限循環(huán)效果
- Android實(shí)現(xiàn)基于ViewPager的無(wú)限循環(huán)自動(dòng)播放帶指示器的輪播圖CarouselFigureView控件
- Android實(shí)戰(zhàn)打飛機(jī)游戲之無(wú)限循環(huán)的背景圖(2)
- Android TV 3D卡片無(wú)限循環(huán)效果
相關(guān)文章
Flutter使用AnimationController實(shí)現(xiàn)控制動(dòng)畫(huà)
這篇文章主要想帶大家來(lái)嘗試一下Flutter如何使用AnimationController實(shí)現(xiàn)一個(gè)拖拽圖片,然后返回原點(diǎn)的動(dòng)畫(huà),感興趣的可以了解一下2023-05-05android 自定義圓角button效果的實(shí)例代碼(自定義view Demo)
這篇文章主要介紹了android 自定義圓角button(自定義View Demo),本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-12-12Android實(shí)現(xiàn)梯形TextView效果
TextView(文本框),用于顯示文本的一個(gè)控件,Android開(kāi)發(fā)中經(jīng)常使用,本文講述如何實(shí)現(xiàn)一個(gè)梯形的TextView2021-05-05Android樹(shù)形控件的實(shí)現(xiàn)方法
這篇文章主要為大家詳細(xì)介紹了Android樹(shù)形控件的實(shí)現(xiàn)方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11Android中Fragment子類(lèi)及其PreferenceFragment的創(chuàng)建過(guò)程演示
這篇文章主要介紹了Android中Fragment子類(lèi)及其PreferenceFragment的創(chuàng)建過(guò)程演示,PreferenceFragment用來(lái)保存Fragment的選項(xiàng)設(shè)置,需要的朋友可以參考下2016-05-05android 實(shí)現(xiàn)APP中改變頭像圖片的實(shí)例代碼
這篇文章主要介紹了android 實(shí)現(xiàn)APP中改變頭像圖片的實(shí)例代碼,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-07-07簡(jiǎn)單實(shí)現(xiàn)Android讀取網(wǎng)絡(luò)圖片到本地
這篇文章主要為大家詳細(xì)介紹了如何簡(jiǎn)單實(shí)現(xiàn)Android讀取網(wǎng)絡(luò)圖片到本地的方法,感興趣的小伙伴們可以參考一下2016-08-08Android Studio實(shí)現(xiàn)簡(jiǎn)易計(jì)算器
這篇文章主要為大家詳細(xì)介紹了Android Studio實(shí)現(xiàn)簡(jiǎn)易計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07