Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android自定義控件——仿淘寶、網易、彩票等廣告條、Banner的制作

Android自定義控件——仿淘寶、網易、彩票等廣告條、Banner的制作

編輯:關於Android編程

 


最近翻看以前的某項目時,發現了一個極其常用的效果——廣告條,或者也稱不上自定義組件,但是使用頻率還是相當普遍的。

打開市面上各大App主界面,或多或少會出現這樣的東西,甚至一個應用中出現N多個,這種展示廣告的效果,不僅動態效果好,而且眾所周知的“不占屏”,想想在手機設備這麼小的屏幕尺寸下,能放下幾頁甚至十幾頁的廣告循環播放,就知道這種廣告的使用頻率之大了。以下是我收集的部分APP中使用的效果截圖:

height=320height=320height=320

這些“千萬億”級別的APP都在使用的效果,為什麼我們不能效仿追隨一下呢,那下面我就開始動手做一個自己的廣告條;

要求如下:1,實現多圖展示

2,實現手勢切換

3,廣告圖片與廣告標語同時切換

4,循環切換,定時循環播放

以下是我的項目結構:

height=300

廣告條實際上用的是ViewPager來做的,布局中僅僅放了一個ViewPager而已,其它的圖片切換都是用ViewPager來展示的,布局如下:

 



    

    

        

        
        
    


上面的ViewPager用來顯示廣告圖片,下面的LinearLayout嵌在ViewPager底部,實現陰影效果。裡面包括TextView來顯示廣告標語,和一個LinearLayout來顯示廣告切換狀態指示點。寫完布局,就可以為這個ViewPager加載數據,增加動態效果了,主要代碼如下,注釋清晰:

 

 

package com.example.banner;

import java.util.ArrayList;
import java.util.List;

import android.os.Bundle;
import android.os.SystemClock;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.LinearLayout.LayoutParams;
import android.app.Activity;

public class MainActivity extends Activity {

	private List mImageList;
	/** 廣告條正下方的標語 */
	private String[] imageDescriptionArray = { //
	鞏俐不低俗,我就不能低俗, //
			撲樹又回來啦!再唱經典老歌引萬人大合唱, //
			揭秘北京電影如何升級, //
			樂視網TV版大派送, //
			熱血屌絲的反殺 };
	/** 記錄上一次點的位置,默認為0 */
	private int previousPointEnale = 0;
	private ViewPager mViewPager;
	private LinearLayout llPointGroup;
	private TextView tvDescription;
	/** 記錄是否停止循環播放 */
	private boolean isStop = false;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		init();
		// 開啟子線程,讓廣告條以2秒的頻率循環播放
		new Thread(new Runnable() {

			@Override
			public void run() {

				while (!isStop) {
					SystemClock.sleep(2000);
					runOnUiThread(new Runnable() {
						public void run() {
							mViewPager.setCurrentItem(mViewPager.getCurrentItem() + 1);
						}
					});
				}
			}
		}).start();
	}

	private void init() {
		llPointGroup = (LinearLayout) findViewById(R.id.ll_point_group);
		tvDescription = (TextView) findViewById(R.id.tv_image_description);
		mImageList = new ArrayList();
		int[] imageIds = new int[] { R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d, R.drawable.e };
		ImageView mImageView;
		LayoutParams params;
		// 初始化廣告條資源
		for (int id : imageIds) {
			mImageView = new ImageView(this);
			mImageView.setBackgroundResource(id);
			mImageList.add(mImageView);

			// 初始化廣告條正下方的點
			View dot = new View(this);
			dot.setBackgroundResource(R.drawable.point_background);
			params = new LayoutParams(5, 5);
			params.leftMargin = 10;
			dot.setLayoutParams(params);
			dot.setEnabled(false);
			llPointGroup.addView(dot);
		}
		mViewPager = (ViewPager) findViewById(R.id.viewpager);
		mViewPager.setAdapter(new MyAdapter());

		// 設置廣告條跳轉時,廣告語和狀態語的變化
		mViewPager.setOnPageChangeListener(new MyListener());

		// 初始化廣告條,當前索引Integer.MAX_VALUE的一半
		int index = (Integer.MAX_VALUE / 2) - (Integer.MAX_VALUE / 2 % mImageList.size());
		mViewPager.setCurrentItem(index); // 設置當前選中的Page,會觸發onPageChangListener.onPageSelected方法
	}

	private class MyListener implements OnPageChangeListener {

		@Override
		public void onPageScrollStateChanged(int arg0) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onPageScrolled(int arg0, float arg1, int arg2) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onPageSelected(int arg0) {
			// 獲取新的位置
			int newPosition = arg0 % imageDescriptionArray.length;
			// 設置廣告標語
			tvDescription.setText(imageDescriptionArray[newPosition]);
			// 消除上一次的狀態點
			llPointGroup.getChildAt(previousPointEnale).setEnabled(false);
			// 設置當前的狀態點“點”
			llPointGroup.getChildAt(newPosition).setEnabled(true);
			// 記錄位置
			previousPointEnale = newPosition;
		}

	}

	/**
	 * ViewPager數據適配器
	 */
	private class MyAdapter extends PagerAdapter {

		@Override
		public int getCount() {
			// 將viewpager頁數設置成Integer.MAX_VALUE,可以模擬無限循環
			return Integer.MAX_VALUE;
		}

		/**
		 * 復用對象 true 復用view false 復用的是Object
		 */
		@Override
		public boolean isViewFromObject(View arg0, Object arg1) {
			// TODO Auto-generated method stub
			return arg0 == arg1;
		}

		/**
		 * 銷毀對象
		 * 
		 * @param position
		 *            被銷毀對象的索引位置
		 */
		@Override
		public void destroyItem(ViewGroup container, int position, Object object) {
			container.removeView(mImageList.get(position % mImageList.size()));
		}

		/**
		 * 初始化一個對象
		 * 
		 * @param position
		 *            初始化對象的索引位置
		 */
		@Override
		public Object instantiateItem(ViewGroup container, int position) {
			container.addView(mImageList.get(position % mImageList.size()));
			return mImageList.get(position % mImageList.size());
		}

	}

	@Override
	protected void onDestroy() {
		// activity銷毀時候,關閉循環播放
		isStop = true;
		super.onDestroy();
	}

}

需要注意的是,為了達到廣告條循環播放的效果,故不能將ViewPager所展示的總數設置較小的定值,這樣若ViewPager劃過這個定值的時候,頁面會定住,用戶體驗就不太理想化了,為了能達到這個循環的效果,只能將ViewPager展示總數設置成一個很大的值,以便來給用戶造成無限循環的假象。那麼這個值該取多大合適呢?思前想後,覺得在PagerAdapter的getCount方法中,返回Integer.MAX_VALUE這個值,這個值2147483647,無論如何用戶也不可以拿手機沒事劃上個好幾億次吧。

 

到此還要注意的地方就是,因為getCount中返回Integer.MAX_VALUE這麼大數值,為了達到有圖循環的效果,避免Bug,所以其後每次涉及到position索引的地方都得用position和資源尺度取余的結果。

此外,在“點”的初始化的時候,應當設置“點”的索引為int index = (Integer.MAX_VALUE / 2) - (Integer.MAX_VALUE / 2 % mImageList.size());

而不能簡單設置成0,若是設置成0,就無法制造出循環播放的“假象”,不信試試設置0,往左滑動。

關於“點”的資源,沒有用到圖片,下面是資源代碼,貼出來:

廣告條獲得焦點:point_bg_enable.xml

 




    

    


廣告條普通樣式:point_bg_normal.xml

 

 




    

    


廣告條的狀態選擇器:point_background.xml

 

 




    
    

以下是效果圖:

 

height=320height=320

最後,還需要實現廣告的自動循環播放,這個很簡單,只要開啟一個新線程,在線程中每隔2000ms循環更新一下ViewPager就行。就是在ViewPager中獲取當前展示的Item的索引,加上1之後,設置展示這個值即可。還得注意程序的嚴謹性啊,當activity銷毀的時候,這個新線程裡負責循環播放的代碼是徐璈停止執行的。故設置一個boolean的變量isStop,在while循環的時候,判斷是否開啟/關閉,在activity的onDestory方法中,設置其為true,即停止循環播放!

 

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved