編輯:關於Android編程
Demo實現的效果圖如下:
工程目錄如下圖:
一個Application,一個實體類,一個Activity,另一個是自定義的AutoPlayingViewPager繼承FrameLayout。
首先看一下自定義的AutoPlayingViewPager,功能都在這裡實現。采用了第三方圖片加載框架:universal_image_loader;
package com.skycracks.autoplayingviewpager; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import com.nostra13.universalimageloader.core.ImageLoader; import android.content.Context; import android.os.Handler; import android.os.Message; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.animation.Interpolator; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.Scroller; import android.widget.TextView; /** * 創建時間: 2016年1月10日 下午3:43:22 * 版本: [v1.0] * 類描述: 實現ViewPager輪播圖 * 使用了ImageLoader 對圖片進行加載,所以使用前必須初始化ImageLoader * stopPlaying() 當輪播所在頁面不在頂棧時,有必要停止定時並且釋放資源 * startPlaying() 當再次恢復時調用 * */ public class AutoPlayingViewPager extends FrameLayout { private final static String TAG = "AutoPlayingViewPager"; /** * 輪播圖圖片數量 */ private int IMAGE_COUNT; /** * 自動輪播的時間間隔 */ private final static int TIME_INTERVAL = 5; /** * 切換圖片過度時間 */ private int swapDuration = 1000; /** * 默認圖片資源(本地圖片資源Id) */ private int [] defaultIds = new int[] { R.drawable.image01,R.drawable.image02, R.drawable.image03,R.drawable.image04,R.drawable.image05}; /** * 默認圖片資源(圖片URL地址) */ private String [] defaultUrl = new String[] { "http://g.hiphotos.baidu.com/imgad/pic/item/a8773912b31bb051be533b24317adab44aede043.jpg", "http://g.hiphotos.baidu.com/imgad/pic/item/c75c10385343fbf22c362d2fb77eca8065388fa0.jpg", "http://liaoning.sinaimg.cn/2014/1111/U10435P1195DT20141111220802.jpg", "http://photocdn.sohu.com/20151124/mp43786429_1448294862260_4.jpeg", "http://h.hiphotos.baidu.com/image/pic/item/faedab64034f78f0b00507c97e310a55b3191cf9.jpg" }; private String [] defaultTitle = new String [] { "今晚打老虎","今晚打松鼠","今晚打LOL","今晚打DOTA1","今晚打DOTA2"}; /** * 自定義輪播圖資源 */ private List mAutoPlayInfoList; /** * 放圓點的View的list */ private ListdotViewsList; /** * 輪播容器 */ private ViewPager mViewPager; /** * 當前輪播頁 */ private int currentItem = 0; /** * 定時器對象 */ private ScheduledExecutorService scheduledExecutorService; private Context mContext; private LayoutInflater mInflate; /** * ViewPageItem點擊回調接口 */ private OnPageItemClickListener onPageItemClickListener; public void setOnPageItemClickListener(OnPageItemClickListener onPageItemClickListener){ this.onPageItemClickListener = onPageItemClickListener; } public interface OnPageItemClickListener{ /** * ViewPageItem點擊事件回調 */ void onPageItemClick(int position, String adLink); } /** * 消息處理器、設置當前顯示頁 */ private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); mViewPager.setCurrentItem(currentItem); } }; public AutoPlayingViewPager(Context context) { this(context, null); } public AutoPlayingViewPager(Context context, AttributeSet attrs) { this(context, attrs, 0); } public AutoPlayingViewPager(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.mContext = context; initData(); } /** * 通過本地圖片資源Id獲得默認的數據 */ private List getImageIdAutoPlayInfoList(int [] imageIds){ List autoPlayInfoList = new ArrayList(); for(int i = 0 ; i < imageIds.length ; i ++){ AutoPlayInfo autoPlayInfo = new AutoPlayInfo(); autoPlayInfo.setImageId(imageIds[i]); autoPlayInfoList.add(autoPlayInfo); } return autoPlayInfoList; } /** * 通過圖片URL地址獲得默認的數據 */ private List getDefaultUrlAutoPlayInfoList(){ List autoPlayInfoList = new ArrayList(); for(int i = 0 ; i < defaultUrl.length ; i ++){ AutoPlayInfo autoPlayInfo = new AutoPlayInfo(); autoPlayInfo.setImageUrl(defaultUrl[i]); autoPlayInfo.setAdLinks("http://m.baidu.com"); autoPlayInfo.setTitle(defaultTitle[i]); autoPlayInfoList.add(autoPlayInfo); } return autoPlayInfoList; } /** * 初始化 * @param imageIds 需要加載的圖片Id,根據傳入數量動態創建容器。 * @return */ public AutoPlayingViewPager initialize(int [] imageIds) { if (imageIds != null && imageIds.length != 0) { mAutoPlayInfoList = getImageIdAutoPlayInfoList(imageIds); } else {//沒有數據使用默認的圖片資源 mAutoPlayInfoList = getImageIdAutoPlayInfoList(defaultIds); } IMAGE_COUNT = mAutoPlayInfoList.size(); return this; } /** * 初始化 * * @param imageUrls 需要加載的圖片地址,根據傳入數量動態創建容器。 * @return */ public AutoPlayingViewPager initialize(List autoPlayInfoList) { if (autoPlayInfoList != null && !autoPlayInfoList.isEmpty()) { mAutoPlayInfoList = autoPlayInfoList; } else {//沒有數據使用默認的圖片資源 mAutoPlayInfoList = getDefaultUrlAutoPlayInfoList(); } IMAGE_COUNT = mAutoPlayInfoList.size(); return this; } /** * 設置圖片之間自動切換時間 * * @param duration * 切換時間 * @return */ public AutoPlayingViewPager setSwapDuration(int duration) { this.swapDuration = duration; return this; } /** * 開始輪播圖切換 輪播之前必須調initialize()及build() */ public void startPlaying() { scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); scheduledExecutorService.scheduleAtFixedRate(new SlideShowTask(), 1, TIME_INTERVAL, TimeUnit.SECONDS); } /** * 停止輪播釋放資源 */ public void stopPlaying() { scheduledExecutorService.shutdown(); } /** * 初始化相關Data */ private void initData() { dotViewsList = new ArrayList (); } /** * 初始化Views 及組件UI */ public void build() { if (mAutoPlayInfoList == null || mAutoPlayInfoList.isEmpty()) { Log.d(TAG, "init image fail "); return; } mInflate = LayoutInflater.from(mContext); mInflate.inflate(R.layout.view_layout_slideshow,this, true); LinearLayout dotLayout = (LinearLayout) findViewById(R.id.dotLayout); dotLayout.removeAllViews();// 清除布局中的子視圖,下面使用代碼動態添加與圖片對應的圓點 // 熱點個數與圖片數量相等 for (int i = 0; i < IMAGE_COUNT; i++) { ImageView dotView = new ImageView(mContext); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); params.leftMargin = 4; params.rightMargin = 4; dotLayout.addView(dotView, params); dotViewsList.add(dotView); } mViewPager = (ViewPager) findViewById(R.id.viewPager); setViewPagerScrollSpeed(); mViewPager.setFocusable(true); mViewPager.setOffscreenPageLimit(2);// 設置緩存頁面,當前頁面的相鄰N各頁面都會被緩存 mViewPager.setAdapter(new AutoPlayingPagerAdapter()); AutoPlayingPageChangeListener mPageChangeListener = new AutoPlayingPageChangeListener(); mViewPager.addOnPageChangeListener(mPageChangeListener); } /** * 填充ViewPager的頁面適配器 */ private class AutoPlayingPagerAdapter extends PagerAdapter { @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } @Override public Object instantiateItem(ViewGroup container, final int position) { final AutoPlayInfo autoPlayInfo = mAutoPlayInfoList.get(position % IMAGE_COUNT); View view = mInflate.inflate(R.layout.item_label_auto_play_viewpager, null); ImageView imageView = (ImageView) view.findViewById(R.id.img_item_auto_play); TextView labelTitle = (TextView) view.findViewById(R.id.tv_item_label_title); /* if(!TextUtils.isEmpty(autoPlayInfo.getAdLinks())){//有鏈接時才添加監聽 }*/ view.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onPageItemClickListener.onPageItemClick(position % IMAGE_COUNT,autoPlayInfo.getAdLinks()); } }); if(!TextUtils.isEmpty(autoPlayInfo.getImageUrl())){//通過URL時使用ImageLoader加載圖片 ImageLoader.getInstance().displayImage(autoPlayInfo.getImageUrl(),imageView); }else if(autoPlayInfo.getImageId() != 0){//本地圖片時直接設置 imageView.setImageResource(autoPlayInfo.getImageId()); } if(!TextUtils.isEmpty(autoPlayInfo.getTitle())){//有標題數據才顯示 labelTitle.setText(autoPlayInfo.getTitle()); }else{//沒有標題數據不顯示文本透明背景 labelTitle.setBackgroundDrawable(null); } container.addView(view); return view; } @Override public int getCount() { return Integer.MAX_VALUE; } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; } } /** * ViewPager的監聽器 當ViewPager中頁面的狀態發生改變時調用 * */ private class AutoPlayingPageChangeListener implements OnPageChangeListener { // boolean isChange = false; @Override public void onPageScrollStateChanged(int arg0) { switch (arg0) { case 1:// 手勢滑動,空閒中 // isChange = false; break; case 2:// 界面切換中 // isChange = true; break; case 0:// 滑動結束,即切換完畢或者加載完畢 break; } } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageSelected(int pos) { currentItem = pos; int p = pos % IMAGE_COUNT; for (int i = 0; i < dotViewsList.size(); i++) { if (i == p) { dotViewsList.get(p).setBackgroundResource( R.drawable.icon_cricle_check); } else { dotViewsList.get(i).setBackgroundResource( R.drawable.icon_cricle_uncheck); } } } } /** * 執行輪播圖切換任務 * */ boolean isLR = false; private class SlideShowTask implements Runnable { @Override public void run() { synchronized (mViewPager) { currentItem++; handler.obtainMessage().sendToTarget(); } } } /** * 使用反射往ViewPager中設置新的Scroller對象 覆蓋默認的setCurrentItem切換時間 */ private void setViewPagerScrollSpeed() { try { Field mScroller = null; mScroller = ViewPager.class.getDeclaredField("mScroller"); mScroller.setAccessible(true); FixedSpeedScroller scroller = new FixedSpeedScroller( mViewPager.getContext()); mScroller.set(mViewPager, scroller); } catch (NoSuchFieldException e) { } catch (IllegalArgumentException e) { } catch (IllegalAccessException e) { } } class FixedSpeedScroller extends Scroller { public FixedSpeedScroller(Context context) { super(context); } public FixedSpeedScroller(Context context, Interpolator interpolator) { super(context, interpolator); } public FixedSpeedScroller(Context context, Interpolator interpolator, boolean flywheel) { super(context, interpolator, flywheel); } @Override public void startScroll(int startX, int startY, int dx, int dy, int duration) { super.startScroll(startX, startY, dx, dy, swapDuration); } @Override public void startScroll(int startX, int startY, int dx, int dy) { super.startScroll(startX, startY, dx, dy, swapDuration); } } }
當然想用上ImageLoad而必須在Application裡面注冊一下:
@Override public void onCreate() { super.onCreate(); initImageLoader(); } /** * 初始化UIL,這裡初始化以後,就不在初始化了 */ public void initImageLoader() { DisplayImageOptions.Builder options = new DisplayImageOptions.Builder() .cacheInMemory(true)// 內存緩存 .cacheOnDisk(true)// 磁盤緩存 .showImageOnFail(R.drawable.ic_faile)//加載失敗顯示的圖片 .considerExifParams(true)// 是否考慮EXIF信息,比如拍照方向 .displayer(new FadeInBitmapDisplayer(300));//淡入動畫 ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(getApplicationContext()); // 取消緩存多張尺寸不同的同一張圖片 config.denyCacheImageMultipleSizesInMemory(); // 設置顯示選項 config.defaultDisplayImageOptions(options.build()); // 生成緩存文件的生成器,保證唯一的文件名,可以不設置,默認使用hash算法,也是可以保證不重名的 config.diskCacheFileNameGenerator(new Md5FileNameGenerator()); // 磁盤緩存大小 config.diskCacheSize(100 * 1024 * 1024); // 100 MB // 內存緩存大小 config.memoryCacheSize((int) (Runtime.getRuntime().freeMemory() / 4)); // 任務處理順序,默認是FIFO 先進先出, LIFO 後進先出 config.tasksProcessingOrder(QueueProcessingType.LIFO); // 打印調試日志 config.writeDebugLogs(); // Remove for release app ImageLoader.getInstance().init(config.build()); }
最關鍵的就是調用:
布局直接調用自定義的ViewPager:
主方法中運用很簡單,只需把接收的對象集合傳到自定義的AutoPlayingViewPager。
看代碼:
package com.skycracks.autoplayingviewpager; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.widget.Toast; import com.skycracks.autoplayingviewpager.AutoPlayingViewPager.OnPageItemClickListener; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { private AutoPlayingViewPager mAutoPlayingViewPager; /** * 模擬網絡請求獲取的圖片URL */ private String [] imageUrl = new String[] { "http://g.hiphotos.baidu.com/image/pic/item/d0c8a786c9177f3e117088eb75cf3bc79e3d568b.jpg", "http://upload.cebnet.com.cn/2014/1217/1418776413348.jpg", "http://n.sinaimg.cn/transform/20150917/7DDk-fxhytwp5363222.jpg", "http://n.sinaimg.cn/transform/20151019/YtA_-fxivsce6931363.jpg" }; private String [] imageTitle = new String [] { "趙麗穎","高圓圓","王鷗","唐嫣"}; private List mAutoPlayInfoList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mAutoPlayingViewPager = (AutoPlayingViewPager) findViewById(R.id.auto_play_viewpager); mAutoPlayInfoList=new ArrayList<>(); for(int i = 0 ; i < imageUrl.length ; i ++){ //把模擬的數據添加到集合裡面 AutoPlayInfo autoPlayInfo = new AutoPlayInfo(); autoPlayInfo.setImageUrl(imageUrl[i]); autoPlayInfo.setAdLinks(""); autoPlayInfo.setTitle(imageTitle[i]); mAutoPlayInfoList.add(autoPlayInfo); } //通過這個方法把集合傳進去,並設置圖片的點擊事件,可以做跳轉 mAutoPlayingViewPager.initialize(mAutoPlayInfoList).build(); mAutoPlayingViewPager.setOnPageItemClickListener(onPageItemClickListener); } private OnPageItemClickListener onPageItemClickListener = new OnPageItemClickListener() { @Override public void onPageItemClick(int position, String adLink) { Toast.makeText(MainActivity.this,"第"+position,Toast.LENGTH_LONG).show(); } }; @Override public void onStart() { //當Activity onRestart();還要執行, //沒有數據時不執行startPlaying,避免執行幾次導致輪播混亂 if(mAutoPlayInfoList != null && !mAutoPlayInfoList.isEmpty()){ mAutoPlayingViewPager.startPlaying(); } super.onResume(); } @Override public void onPause() { mAutoPlayingViewPager.stopPlaying(); super.onPause(); } }
最後幾個就是實體類:
public class AutoPlayInfo { //輪播圖片URL private String imageUrl; //輪播本地圖片資源Id private int imageId; //鏈接 private String adLinks; //圖片對應的標題 private String title; public String getImageUrl() { return imageUrl; } public void setImageUrl(String imageUrl) { this.imageUrl = imageUrl; } public int getImageId() { return imageId; } public void setImageId(int imageId) { this.imageId = imageId; } public String getAdLinks() { return adLinks; } public void setAdLinks(String adLinks) { this.adLinks = adLinks; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } }
另外,還有一種通過自定義ViewPager實現和本博文相同效果的廣告界面Demo,這裡就不再貼代碼。
在Andoird使用Android自帶的那些組件,像SlidingDrawer和DrawerLayout都是抽屜效果的菜單,但是在項目很多要實現的功能都收到Android
1.下面示例是一個簡單的定位,來自官網,對這些源碼加了一些注釋,這樣看起來可能會更容易理解一點。2.直接上源碼androidManifest.xml
騰訊Wifi管家app這是騰訊旗下的一款類似Wifi萬能鑰匙。一款騰訊WiFi管家在手,讓你一鍵連接WiFi,很多朋友都在問騰訊WiFi管家怎麼破解密碼?快
Android手機同時使用Wi-Fi和數據流量大家都知道,當手機成功連接到Wi-Fi熱點以後,手機所產生的上網流量都是通過Wi-Fi來傳輸的,而手機的移動流量會被禁用。但