android仿iPhone滾輪控件實現及源碼分析(一)

      敬告:因爲本文代碼較多,因此文章分爲了一二兩篇,若是不便,敬請諒解,能夠先下載文章下方的代碼,打開參考本文查看,效果更好!       


        首先,先看下效果圖: html


        這三張圖分別是使用滾動控件實現城市,隨機數和時間三個簡單的例子,固然,界面有點簡陋,下面咱們就以時間這個爲例,開始解析一下。 java

     首先,先看下佈局文件: android

  1. <?xml version="1.0" encoding="utf-8"?> 
  2.  
  3. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  4.     android:layout_height="wrap_content" 
  5.     android:layout_width="fill_parent" 
  6.     android:layout_marginTop="12dp" 
  7.     android:orientation="vertical" 
  8.     android:background="@drawable/layout_bg"> 
  9.      
  10.     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  11.         android:layout_height="wrap_content" 
  12.         android:layout_width="fill_parent" 
  13.         android:layout_gravity="center_horizontal" 
  14.         android:paddingLeft="12dp" 
  15.         android:paddingRight="12dp" 
  16.         android:paddingTop="10dp"> 
  17.        
  18.         <kankan.wheel.widget.WheelView android:id="@+id/hour" 
  19.             android:layout_height="wrap_content" 
  20.             android:layout_width="fill_parent" 
  21.             android:layout_weight="1"/> 
  22.         <kankan.wheel.widget.WheelView android:id="@+id/mins" 
  23.             android:layout_height="wrap_content" 
  24.             android:layout_width="fill_parent" 
  25.             android:layout_weight="1"/> 
  26.     </LinearLayout> 
  27.      
  28.     <TimePicker android:id="@+id/time" 
  29.         android:layout_marginTop="12dp" 
  30.         android:layout_height="wrap_content" 
  31.         android:layout_width="fill_parent" 
  32.         android:layout_weight="1"/> 
  33.          
  34. </LinearLayout> 

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_height="wrap_content"
	android:layout_width="fill_parent"
	android:layout_marginTop="12dp"
	android:orientation="vertical"
	android:background="@drawable/layout_bg">
	
	<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
		android:layout_height="wrap_content"
		android:layout_width="fill_parent"
		android:layout_gravity="center_horizontal"
		android:paddingLeft="12dp"
		android:paddingRight="12dp"
		android:paddingTop="10dp">
	  
	  	<kankan.wheel.widget.WheelView android:id="@+id/hour"
			android:layout_height="wrap_content"
			android:layout_width="fill_parent"
			android:layout_weight="1"/>
		<kankan.wheel.widget.WheelView android:id="@+id/mins"
			android:layout_height="wrap_content"
			android:layout_width="fill_parent"
			android:layout_weight="1"/>
	</LinearLayout>
	
	<TimePicker android:id="@+id/time"
		android:layout_marginTop="12dp"
		android:layout_height="wrap_content"
		android:layout_width="fill_parent"
		android:layout_weight="1"/>
		
</LinearLayout>


        裏面只有三個控件,兩個自定義的WheelView,還有一個TimePicker,而後進入代碼裏面看一下:

  1. public class TimeActivity extends Activity { 
  2.     // Time changed flag 
  3.     private boolean timeChanged = false
  4.      
  5.     // 
  6.     private boolean timeScrolled = false
  7.      
  8.     @Override 
  9.     public void onCreate(Bundle savedInstanceState) { 
  10.         super.onCreate(savedInstanceState); 
  11.  
  12.         setContentView(R.layout.time_layout); 
  13.      
  14.         final WheelView hours = (WheelView) findViewById(R.id.hour); 
  15.         hours.setAdapter(new NumericWheelAdapter(0, 23)); 
  16.         hours.setLabel("hours"); 
  17.      
  18.         final WheelView mins = (WheelView) findViewById(R.id.mins); 
  19.         mins.setAdapter(new NumericWheelAdapter(0, 59, "%02d")); 
  20.         mins.setLabel("mins"); 
  21.         mins.setCyclic(true); 
  22.      
  23.         final TimePicker picker = (TimePicker) findViewById(R.id.time); 
  24.         picker.setIs24HourView(true); 
  25.      
  26.         // set current time 
  27.         Calendar c = Calendar.getInstance(); 
  28.         int curHours = c.get(Calendar.HOUR_OF_DAY); 
  29.         int curMinutes = c.get(Calendar.MINUTE); 
  30.      
  31.         hours.setCurrentItem(curHours); 
  32.         mins.setCurrentItem(curMinutes); 
  33.      
  34.         picker.setCurrentHour(curHours); 
  35.         picker.setCurrentMinute(curMinutes); 
  36.      
  37.         // add listeners 
  38.         addChangingListener(mins, "min"); 
  39.         addChangingListener(hours, "hour"); 
  40.      
  41.         OnWheelChangedListener wheelListener = new OnWheelChangedListener() { 
  42.             public void onChanged(WheelView wheel, int oldValue, int newValue) { 
  43.                 if (!timeScrolled) { 
  44.                     timeChanged = true
  45.                     picker.setCurrentHour(hours.getCurrentItem()); 
  46.                     picker.setCurrentMinute(mins.getCurrentItem()); 
  47.                     timeChanged = false
  48.                 } 
  49.             } 
  50.         }; 
  51.  
  52.         hours.addChangingListener(wheelListener); 
  53.         mins.addChangingListener(wheelListener); 
  54.  
  55.         OnWheelScrollListener scrollListener = new OnWheelScrollListener() { 
  56.             public void onScrollingStarted(WheelView wheel) { 
  57.                 timeScrolled = true
  58.             } 
  59.             public void onScrollingFinished(WheelView wheel) { 
  60.                 timeScrolled = false
  61.                 timeChanged = true
  62.                 picker.setCurrentHour(hours.getCurrentItem()); 
  63.                 picker.setCurrentMinute(mins.getCurrentItem()); 
  64.                 timeChanged = false
  65.             } 
  66.         }; 
  67.          
  68.         hours.addScrollingListener(scrollListener); 
  69.         mins.addScrollingListener(scrollListener); 
  70.          
  71.         picker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() { 
  72.             public void onTimeChanged(TimePicker  view, int hourOfDay, int minute) { 
  73.                 if (!timeChanged) { 
  74.                     hours.setCurrentItem(hourOfDay, true); 
  75.                     mins.setCurrentItem(minute, true); 
  76.                 } 
  77.             } 
  78.         }); 
  79.     } 
  80.  
  81.     /**
  82.      * Adds changing listener for wheel that updates the wheel label
  83.      * @param wheel the wheel
  84.      * @param label the wheel label
  85.      */ 
  86.     private void addChangingListener(final WheelView wheel, final String label) { 
  87.         wheel.addChangingListener(new OnWheelChangedListener() { 
  88.             public void onChanged(WheelView wheel, int oldValue, int newValue) { 
  89.                 wheel.setLabel(newValue != 1 ? label + "s" : label); 
  90.             } 
  91.         }); 
  92.     } 

public class TimeActivity extends Activity {
	// Time changed flag
	private boolean timeChanged = false;
	
	//
	private boolean timeScrolled = false;
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		setContentView(R.layout.time_layout);
	
		final WheelView hours = (WheelView) findViewById(R.id.hour);
		hours.setAdapter(new NumericWheelAdapter(0, 23));
		hours.setLabel("hours");
	
		final WheelView mins = (WheelView) findViewById(R.id.mins);
		mins.setAdapter(new NumericWheelAdapter(0, 59, "%02d"));
		mins.setLabel("mins");
		mins.setCyclic(true);
	
		final TimePicker picker = (TimePicker) findViewById(R.id.time);
		picker.setIs24HourView(true);
	
		// set current time
		Calendar c = Calendar.getInstance();
		int curHours = c.get(Calendar.HOUR_OF_DAY);
		int curMinutes = c.get(Calendar.MINUTE);
	
		hours.setCurrentItem(curHours);
		mins.setCurrentItem(curMinutes);
	
		picker.setCurrentHour(curHours);
		picker.setCurrentMinute(curMinutes);
	
		// add listeners
		addChangingListener(mins, "min");
		addChangingListener(hours, "hour");
	
		OnWheelChangedListener wheelListener = new OnWheelChangedListener() {
			public void onChanged(WheelView wheel, int oldValue, int newValue) {
				if (!timeScrolled) {
					timeChanged = true;
					picker.setCurrentHour(hours.getCurrentItem());
					picker.setCurrentMinute(mins.getCurrentItem());
					timeChanged = false;
				}
			}
		};

		hours.addChangingListener(wheelListener);
		mins.addChangingListener(wheelListener);

		OnWheelScrollListener scrollListener = new OnWheelScrollListener() {
			public void onScrollingStarted(WheelView wheel) {
				timeScrolled = true;
			}
			public void onScrollingFinished(WheelView wheel) {
				timeScrolled = false;
				timeChanged = true;
				picker.setCurrentHour(hours.getCurrentItem());
				picker.setCurrentMinute(mins.getCurrentItem());
				timeChanged = false;
			}
		};
		
		hours.addScrollingListener(scrollListener);
		mins.addScrollingListener(scrollListener);
		
		picker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {
			public void onTimeChanged(TimePicker  view, int hourOfDay, int minute) {
				if (!timeChanged) {
					hours.setCurrentItem(hourOfDay, true);
					mins.setCurrentItem(minute, true);
				}
			}
		});
	}

	/**
	 * Adds changing listener for wheel that updates the wheel label
	 * @param wheel the wheel
	 * @param label the wheel label
	 */
	private void addChangingListener(final WheelView wheel, final String label) {
		wheel.addChangingListener(new OnWheelChangedListener() {
			public void onChanged(WheelView wheel, int oldValue, int newValue) {
				wheel.setLabel(newValue != 1 ? label + "s" : label);
			}
		});
	}
}


     看一下,裏面調用WheelView的方法有 setAdapter()、 setLabel("mins")、 setCyclic(true)、setCurrentItem()、getCurrentItem()、addChangingListener()、addScrollingListener()這些方法,其中setAapter設置數據適配器,setCyclic()設置是不是循環,setCurrentItem和getCurrentItem分別是設置如今選擇的item和返回如今選擇的item。後面兩個設置監聽的方法中,須要重寫兩個接口:

  1. /**
  2. * Wheel scrolled listener interface.
  3. */ 
  4. public interface OnWheelScrollListener { 
  5.     /**
  6.      * Callback method to be invoked when scrolling started.
  7.      * @param wheel the wheel view whose state has changed.
  8.      */ 
  9.     void onScrollingStarted(WheelView wheel); 
  10.      
  11.     /**
  12.      * Callback method to be invoked when scrolling ended.
  13.      * @param wheel the wheel view whose state has changed.
  14.      */ 
  15.     void onScrollingFinished(WheelView wheel); 

/**
 * Wheel scrolled listener interface.
 */
public interface OnWheelScrollListener {
	/**
	 * Callback method to be invoked when scrolling started.
	 * @param wheel the wheel view whose state has changed.
	 */
	void onScrollingStarted(WheelView wheel);
	
	/**
	 * Callback method to be invoked when scrolling ended.
	 * @param wheel the wheel view whose state has changed.
	 */
	void onScrollingFinished(WheelView wheel);
}


  1. public interface OnWheelChangedListener { 
  2.     /**
  3.      * Callback method to be invoked when current item changed
  4.      * @param wheel the wheel view whose state has changed
  5.      * @param oldValue the old value of current item
  6.      * @param newValue the new value of current item
  7.      */ 
  8.     void onChanged(WheelView wheel, int oldValue, int newValue); 

public interface OnWheelChangedListener {
	/**
	 * Callback method to be invoked when current item changed
	 * @param wheel the wheel view whose state has changed
	 * @param oldValue the old value of current item
	 * @param newValue the new value of current item
	 */
	void onChanged(WheelView wheel, int oldValue, int newValue);
}


在這裏使用的是典型的回調方法模式。

而後如今,咱們進入WheelView類,看一下他是如何構建,首先,WheelView繼承了View類。代碼的22行到45行是導入的所須要的類。從54行到135行是聲明一些變量和類: less

  1. /** Scrolling duration */ 
  2.     private static final int SCROLLING_DURATION = 400
  3.  
  4.     /** Minimum delta for scrolling */ 
  5.     private static final int MIN_DELTA_FOR_SCROLLING = 1
  6.  
  7.     /** Current value & label text color */ 
  8.     private static final int VALUE_TEXT_COLOR = 0xF0000000
  9.  
  10.     /** Items text color */ 
  11.     private static final int ITEMS_TEXT_COLOR = 0xFF000000
  12.  
  13.     /** Top and bottom shadows colors */ 
  14.     private static final int[] SHADOWS_COLORS = new int[] { 0xFF111111
  15.             0x00AAAAAA, 0x00AAAAAA }; 
  16.  
  17.     /** Additional items height (is added to standard text item height) */ 
  18.     private static final int ADDITIONAL_ITEM_HEIGHT = 15
  19.  
  20.     /** Text size */ 
  21.     private static final int TEXT_SIZE = 24
  22.  
  23.     /** Top and bottom items offset (to hide that) */ 
  24.     private static final int ITEM_OFFSET = TEXT_SIZE / 5
  25.  
  26.     /** Additional width for items layout */ 
  27.     private static final int ADDITIONAL_ITEMS_SPACE = 10
  28.  
  29.     /** Label offset */ 
  30.     private static final int LABEL_OFFSET = 8
  31.  
  32.     /** Left and right padding value */ 
  33.     private static final int PADDING = 10
  34.  
  35.     /** Default count of visible items */ 
  36.     private static final int DEF_VISIBLE_ITEMS = 5
  37.  
  38.     // Wheel Values 
  39.     private WheelAdapter adapter = null
  40.     private int currentItem = 0
  41.      
  42.     // Widths 
  43.     private int itemsWidth = 0
  44.     private int labelWidth = 0
  45.  
  46.     // Count of visible items 
  47.     private int visibleItems = DEF_VISIBLE_ITEMS; 
  48.      
  49.     // Item height 
  50.     private int itemHeight = 0
  51.  
  52.     // Text paints 
  53.     private TextPaint itemsPaint; 
  54.     private TextPaint valuePaint; 
  55.  
  56.     // Layouts 
  57.     private StaticLayout itemsLayout; 
  58.     private StaticLayout labelLayout; 
  59.     private StaticLayout valueLayout; 
  60.  
  61.     // Label & background 
  62.     private String label; 
  63.     private Drawable centerDrawable; 
  64.  
  65.     // Shadows drawables 
  66.     private GradientDrawable topShadow; 
  67.     private GradientDrawable bottomShadow; 
  68.  
  69.     // Scrolling 
  70.     private boolean isScrollingPerformed;  
  71.     private int scrollingOffset; 
  72.  
  73.     // Scrolling animation 
  74.     private GestureDetector gestureDetector; 
  75.     private Scroller scroller; 
  76.     private int lastScrollY; 
  77.  
  78.     // Cyclic 
  79.     boolean isCyclic = false
  80.      
  81.     // Listeners 
  82.     private List<OnWheelChangedListener> changingListeners = new LinkedList<OnWheelChangedListener>(); 
  83.     private List<OnWheelScrollListener> scrollingListeners = new LinkedList<OnWheelScrollListener>(); 

/** Scrolling duration */
	private static final int SCROLLING_DURATION = 400;

	/** Minimum delta for scrolling */
	private static final int MIN_DELTA_FOR_SCROLLING = 1;

	/** Current value & label text color */
	private static final int VALUE_TEXT_COLOR = 0xF0000000;

	/** Items text color */
	private static final int ITEMS_TEXT_COLOR = 0xFF000000;

	/** Top and bottom shadows colors */
	private static final int[] SHADOWS_COLORS = new int[] { 0xFF111111,
			0x00AAAAAA, 0x00AAAAAA };

	/** Additional items height (is added to standard text item height) */
	private static final int ADDITIONAL_ITEM_HEIGHT = 15;

	/** Text size */
	private static final int TEXT_SIZE = 24;

	/** Top and bottom items offset (to hide that) */
	private static final int ITEM_OFFSET = TEXT_SIZE / 5;

	/** Additional width for items layout */
	private static final int ADDITIONAL_ITEMS_SPACE = 10;

	/** Label offset */
	private static final int LABEL_OFFSET = 8;

	/** Left and right padding value */
	private static final int PADDING = 10;

	/** Default count of visible items */
	private static final int DEF_VISIBLE_ITEMS = 5;

	// Wheel Values
	private WheelAdapter adapter = null;
	private int currentItem = 0;
	
	// Widths
	private int itemsWidth = 0;
	private int labelWidth = 0;

	// Count of visible items
	private int visibleItems = DEF_VISIBLE_ITEMS;
	
	// Item height
	private int itemHeight = 0;

	// Text paints
	private TextPaint itemsPaint;
	private TextPaint valuePaint;

	// Layouts
	private StaticLayout itemsLayout;
	private StaticLayout labelLayout;
	private StaticLayout valueLayout;

	// Label & background
	private String label;
	private Drawable centerDrawable;

	// Shadows drawables
	private GradientDrawable topShadow;
	private GradientDrawable bottomShadow;

	// Scrolling
	private boolean isScrollingPerformed; 
	private int scrollingOffset;

	// Scrolling animation
	private GestureDetector gestureDetector;
	private Scroller scroller;
	private int lastScrollY;

	// Cyclic
	boolean isCyclic = false;
	
	// Listeners
	private List<OnWheelChangedListener> changingListeners = new LinkedList<OnWheelChangedListener>();
	private List<OnWheelScrollListener> scrollingListeners = new LinkedList<OnWheelScrollListener>();


          在這裏面,使用到了StaticLayout,在開發文檔中找一下這個類:

  1. StaticLayout is a Layout for text that will not be edited after it is laid out. Use DynamicLayout for text that may change. 
  2.  
  3. This is used by widgets to control text layout. You should not need to use this class directly unless you are implementing your own widget or custom display object, or would be tempted to call Canvas.drawText() directly. 

StaticLayout is a Layout for text that will not be edited after it is laid out. Use DynamicLayout for text that may change.

This is used by widgets to control text layout. You should not need to use this class directly unless you are implementing your own widget or custom display object, or would be tempted to call Canvas.drawText() directly.


staticLayout被建立之後就不能被修改了,一般被用於控制文本組件佈局。

    還使用到了Drawable、Text'Paint、GradientDrawable、GestureDetector、Scroller類,在開發文檔中,GradientDrawable的概述: ide

  1. A Drawable with a color gradient for buttons, backgrounds, etc. 
  2.  
  3. It can be defined in an XML file with the <shape> element. For more information, see the guide to Drawable Resources. 

A Drawable with a color gradient for buttons, backgrounds, etc.

It can be defined in an XML file with the <shape> element. For more information, see the guide to Drawable Resources.


就是說這個類能夠爲按鈕或者背景等提供漸變顏色的繪製。

TextPaint的概述: 函數

  1. TextPaint is an extension of Paint that leaves room for some extra data used during text measuring and drawing. 

TextPaint is an extension of Paint that leaves room for some extra data used during text measuring and drawing.

  TextPaint是Paint類的一個擴展,主要是用於文本在繪製的過程當中爲附件的數據留出空間。


GestureDetector:手勢檢測,看下開發文檔中關於該類的概述:
佈局

  1. Detects various gestures and events using the supplied MotionEvents. The GestureDetector.OnGestureListener callback will notify users when a particular motion event has occurred. This class should only be used with MotionEvents reported via touch (don't use for trackball events). 

Detects various gestures and events using the supplied MotionEvents. The GestureDetector.OnGestureListener callback will notify users when a particular motion event has occurred. This class should only be used with MotionEvents reported via touch (don't use for trackball events).


        爲各類手勢和事件提供MotionEvents。當一個具體的事件發生時會調用回調函數GestureDetector.OnGestureListener。這個類應該只適用於MotionEvents經過觸摸觸發的事件(不要使用追蹤事件)。


        140行到156行是構造方法,175到183行是set和getAdapter。在193行,setInterpolator()方法,設置interPolator這個動畫接口,咱們看下這個接口的概述: post

  1. An interpolator defines the rate of change of an animation. This allows the basic animation effects (alpha, scale, translate, rotate) to be accelerated, decelerated, repeated, etc. 

An interpolator defines the rate of change of an animation. This allows the basic animation effects (alpha, scale, translate, rotate) to be accelerated, decelerated, repeated, etc.


定義了一種基於變率的一個動畫。這使得基本的動畫效果( alpha, scale, translate, rotate)是加速,減慢,重複等。這個方法在隨機數這個例子中被使用。

        203行到213行設置顯示的item條數。在setVisibleItems()方法裏面調用了View的invalidate()方法,看下文檔中對該方法的介紹: 動畫

  1. Invalidate the whole view. If the view is visible, onDraw(android.graphics.Canvas) will be called at some point in the future. This must be called from a UI thread. To call from a non-UI thread, call postInvalidate(). 

Invalidate the whole view. If the view is visible, onDraw(android.graphics.Canvas) will be called at some point in the future. This must be called from a UI thread. To call from a non-UI thread, call postInvalidate().


使所有視圖失效,若是View視圖是可見的,會在UI線程裏面重新調用onDraw()方法。

       223行到233行是設置Label,既後面圖片中的hours. ui

       245行到296行是設置監聽,在上面已經簡單的說了一下,這裏不在累述。

       307行到349行是設置正被選中item,就是在那個陰影條框下的那個部分,比較簡單。裏面主要調用了scroll這個方法:

  1. /**
  2.      * Scroll the wheel
  3.      * @param itemsToSkip items to scroll
  4.      * @param time scrolling duration
  5.      */ 
  6.     public void scroll(int itemsToScroll, int time) { 
  7.         scroller.forceFinished(true); 
  8.         lastScrollY = scrollingOffset; 
  9.         int offset = itemsToScroll * getItemHeight();        
  10.         scroller.startScroll(0, lastScrollY, 0, offset - lastScrollY, time); 
  11.         setNextMessage(MESSAGE_SCROLL);      
  12.         startScrolling(); 
  13.     } 

/**
	 * Scroll the wheel
	 * @param itemsToSkip items to scroll
	 * @param time scrolling duration
	 */
	public void scroll(int itemsToScroll, int time) {
		scroller.forceFinished(true);
		lastScrollY = scrollingOffset;
		int offset = itemsToScroll * getItemHeight();		
		scroller.startScroll(0, lastScrollY, 0, offset - lastScrollY, time);
		setNextMessage(MESSAGE_SCROLL);		
		startScrolling();
	}



       357行到365行是設置item數據可否循環使用。

       384行的initResourcesIfNecessary()方法,從字面意思,若是須要的初始化資源。

  1. private void initResourcesIfNecessary() { 
  2.         if (itemsPaint == null) { 
  3.             itemsPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG 
  4.                     | Paint.FAKE_BOLD_TEXT_FLAG); 
  5.             //itemsPaint.density = getResources().getDisplayMetrics().density; 
  6.             itemsPaint.setTextSize(TEXT_SIZE); 
  7.         } 
  8.  
  9.         if (valuePaint == null) { 
  10.             valuePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG 
  11.                     | Paint.FAKE_BOLD_TEXT_FLAG | Paint.DITHER_FLAG); 
  12.             //valuePaint.density = getResources().getDisplayMetrics().density; 
  13.             valuePaint.setTextSize(TEXT_SIZE); 
  14.             valuePaint.setShadowLayer(0.1f, 0, 0.1f, 0xFFC0C0C0); 
  15.         } 
  16.  
  17.         if (centerDrawable == null) { 
  18.             centerDrawable = getContext().getResources().getDrawable(R.drawable.wheel_val); 
  19.         } 
  20.  
  21.         if (topShadow == null) { 
  22.             topShadow = new GradientDrawable(Orientation.TOP_BOTTOM, SHADOWS_COLORS); 
  23.         } 
  24.  
  25.         if (bottomShadow == null) { 
  26.             bottomShadow = new GradientDrawable(Orientation.BOTTOM_TOP, SHADOWS_COLORS); 
  27.         } 
  28.  
  29.         setBackgroundResource(R.drawable.wheel_bg); 
  30.     } 

private void initResourcesIfNecessary() {
		if (itemsPaint == null) {
			itemsPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG
					| Paint.FAKE_BOLD_TEXT_FLAG);
			//itemsPaint.density = getResources().getDisplayMetrics().density;
			itemsPaint.setTextSize(TEXT_SIZE);
		}

		if (valuePaint == null) {
			valuePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG
					| Paint.FAKE_BOLD_TEXT_FLAG | Paint.DITHER_FLAG);
			//valuePaint.density = getResources().getDisplayMetrics().density;
			valuePaint.setTextSize(TEXT_SIZE);
			valuePaint.setShadowLayer(0.1f, 0, 0.1f, 0xFFC0C0C0);
		}

		if (centerDrawable == null) {
			centerDrawable = getContext().getResources().getDrawable(R.drawable.wheel_val);
		}

		if (topShadow == null) {
			topShadow = new GradientDrawable(Orientation.TOP_BOTTOM, SHADOWS_COLORS);
		}

		if (bottomShadow == null) {
			bottomShadow = new GradientDrawable(Orientation.BOTTOM_TOP, SHADOWS_COLORS);
		}

		setBackgroundResource(R.drawable.wheel_bg);
	}



這個方法就是初始化在532行calculateLayoutWidth()方法中調用了這個方法,同時調用了487行的getMaxTextLength()這個方法。

      471行getTextItem(int index)經過一個索引獲取該item的文本。


      這是第一部分,沒有多少有太多意思的地方,重點的地方在之後532行到940行的內容,另起一篇,開始分析,這一篇先到這。

      最後是下載地址:

Android仿iPhone滾動控件源碼

http://download.csdn.net/detail/aomandeshangxiao/4175719
相關文章
相關標籤/搜索