最近開發中須要作一個相似京東首頁那樣的廣告輪播效果,因而採用ViewPager本身自定義了一個輪播圖效果的View。java
主要原理就是利用定時任務器定時切換ViewPager的頁面。android
效果圖以下:ide
主頁面佈局實現以下:佈局
<?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="match_parent"> <android.support.v4.view.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="match_parent" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:padding="5dp" android:gravity="center" android:orientation="horizontal"> <View android:id="@+id/v_dot1" android:layout_width="8dp" android:layout_height="8dp" android:background="@drawable/dot_black" /> <View android:id="@+id/v_dot2" android:layout_width="8dp" android:layout_height="8dp" android:layout_marginLeft="5dp" android:background="@drawable/dot_white" /> <View android:id="@+id/v_dot3" android:layout_width="8dp" android:layout_height="8dp" android:layout_marginLeft="5dp" android:background="@drawable/dot_white" /> <View android:id="@+id/v_dot4" android:layout_width="8dp" android:layout_height="8dp" android:layout_marginLeft="5dp" android:background="@drawable/dot_white" /> <View android:id="@+id/v_dot5" android:layout_width="8dp" android:layout_height="8dp" android:layout_marginLeft="5dp" android:background="@drawable/dot_white" /> </LinearLayout> </RelativeLayout>
輪播效果視圖類代碼實現以下:this
package com.czm.customview; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import android.content.Context; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.Message; import android.os.Parcelable; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.ImageView.ScaleType; /** * ViewPager實現的輪播圖廣告自定義視圖,如京東首頁的廣告輪播圖效果; * 既支持自動輪播頁面也支持手勢滑動切換頁面 * @author caizhiming * */ public class SlideShowView extends FrameLayout { //輪播圖圖片數量 private final static int IMAGE_COUNT = 5; //自動輪播的時間間隔 private final static int TIME_INTERVAL = 5; //自動輪播啓用開關 private final static boolean isAutoPlay = true; //自定義輪播圖的資源ID private int[] imagesResIds; //放輪播圖片的ImageView 的list private List<ImageView> imageViewsList; //放圓點的View的list private List<View> dotViewsList; private ViewPager viewPager; //當前輪播頁 private int currentItem = 0; //定時任務 private ScheduledExecutorService scheduledExecutorService; //Handler private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super.handleMessage(msg); viewPager.setCurrentItem(currentItem); } }; public SlideShowView(Context context) { this(context,null); // TODO Auto-generated constructor stub } public SlideShowView(Context context, AttributeSet attrs) { this(context, attrs, 0); // TODO Auto-generated constructor stub } public SlideShowView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // TODO Auto-generated constructor stub initData(); initUI(context); if(isAutoPlay){ startPlay(); } } /** * 開始輪播圖切換 */ private void startPlay(){ scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); scheduledExecutorService.scheduleAtFixedRate(new SlideShowTask(), 1, 4, TimeUnit.SECONDS); } /** * 中止輪播圖切換 */ private void stopPlay(){ scheduledExecutorService.shutdown(); } /** * 初始化相關Data */ private void initData(){ imagesResIds = new int[]{ R.drawable.pic1, R.drawable.pic2, R.drawable.pic3, R.drawable.pic4, R.drawable.pic5, }; imageViewsList = new ArrayList<ImageView>(); dotViewsList = new ArrayList<View>(); } /** * 初始化Views等UI */ private void initUI(Context context){ LayoutInflater.from(context).inflate(R.layout.layout_slideshow, this, true); for(int imageID : imagesResIds){ ImageView view = new ImageView(context); view.setImageResource(imageID); view.setScaleType(ScaleType.FIT_XY); imageViewsList.add(view); } dotViewsList.add(findViewById(R.id.v_dot1)); dotViewsList.add(findViewById(R.id.v_dot2)); dotViewsList.add(findViewById(R.id.v_dot3)); dotViewsList.add(findViewById(R.id.v_dot4)); dotViewsList.add(findViewById(R.id.v_dot5)); viewPager = (ViewPager) findViewById(R.id.viewPager); viewPager.setFocusable(true); viewPager.setAdapter(new MyPagerAdapter()); viewPager.setOnPageChangeListener(new MyPageChangeListener()); } /** * 填充ViewPager的頁面適配器 * @author caizhiming */ private class MyPagerAdapter extends PagerAdapter{ @Override public void destroyItem(View container, int position, Object object) { // TODO Auto-generated method stub //((ViewPag.er)container).removeView((View)object); ((ViewPager)container).removeView(imageViewsList.get(position)); } @Override public Object instantiateItem(View container, int position) { // TODO Auto-generated method stub ((ViewPager)container).addView(imageViewsList.get(position)); return imageViewsList.get(position); } @Override public int getCount() { // TODO Auto-generated method stub return imageViewsList.size(); } @Override public boolean isViewFromObject(View arg0, Object arg1) { // TODO Auto-generated method stub return arg0 == arg1; } @Override public void restoreState(Parcelable arg0, ClassLoader arg1) { // TODO Auto-generated method stub } @Override public Parcelable saveState() { // TODO Auto-generated method stub return null; } @Override public void startUpdate(View arg0) { // TODO Auto-generated method stub } @Override public void finishUpdate(View arg0) { // TODO Auto-generated method stub } } /** * ViewPager的監聽器 * 當ViewPager中頁面的狀態發生改變時調用 * @author caizhiming */ private class MyPageChangeListener implements OnPageChangeListener{ boolean isAutoPlay = false; @Override public void onPageScrollStateChanged(int arg0) { // TODO Auto-generated method stub switch (arg0) { case 1:// 手勢滑動,空閒中 isAutoPlay = false; break; case 2:// 界面切換中 isAutoPlay = true; break; case 0:// 滑動結束,即切換完畢或者加載完畢 // 當前爲最後一張,此時從右向左滑,則切換到第一張 if (viewPager.getCurrentItem() == viewPager.getAdapter().getCount() - 1 && !isAutoPlay) { viewPager.setCurrentItem(0); } // 當前爲第一張,此時從左向右滑,則切換到最後一張 else if (viewPager.getCurrentItem() == 0 && !isAutoPlay) { viewPager.setCurrentItem(viewPager.getAdapter().getCount() - 1); } break; } } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { // TODO Auto-generated method stub } @Override public void onPageSelected(int pos) { // TODO Auto-generated method stub currentItem = pos; for(int i=0;i < dotViewsList.size();i++){ if(i == pos){ ((View)dotViewsList.get(pos)).setBackgroundResource(R.drawable.dot_black); }else { ((View)dotViewsList.get(i)).setBackgroundResource(R.drawable.dot_white); } } } } /** *執行輪播圖切換任務 *@author caizhiming */ private class SlideShowTask implements Runnable{ @Override public void run() { // TODO Auto-generated method stub synchronized (viewPager) { currentItem = (currentItem+1)%imageViewsList.size(); handler.obtainMessage().sendToTarget(); } } } /** * 銷燬ImageView資源,回收內存 * @author caizhiming */ private void destoryBitmaps() { for (int i = 0; i < IMAGE_COUNT; i++) { ImageView imageView = imageViewsList.get(i); Drawable drawable = imageView.getDrawable(); if (drawable != null) { //解除drawable對view的引用 drawable.setCallback(null); } } } }
如何引用上面自定義的輪播圖效果視圖View呢?其實很引用普通的View相似,實現以下:spa
<com.czm.customview.SlideShowView android:id="@+id/slideshowView" android:layout_width="335dp" android:layout_height="120dp" android:layout_centerHorizontal="true" />