Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 滑輪組件

Android 滑輪組件

編輯:關於Android編程

今天開源一個時間滑輪組件,在網上有各種開源比如wheel和其它改寫,多多少少不夠實用和缺陷。

該項目地址位於:https://github.com/apple317/displayview。

\

demo實現後效果圖如上<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+CiA8L3A+CjxwPgoxLiC1vMjrRGlzcGxheVZpZXejqLzys8ZTREujqTwvcD4KPHA+CiAgICAgICAgz8LU2Nfu0MKw5nNka7XEemlwsPyjrL3i0bm9q8bk1tC1xGRvd25sb2Fkys23xbW9sb612MS/wryjrEVjbGlwc2XTw7un09K8/MT6tcS5pLPMuPnEv8K8o6zRodTxUHJvcGVydGllcyAtPiBKYXZhIEJ1aWxkIFBhdGggLT4gTGlicmFyaWVzo6wgyLu687Xju/cgQWRkIEV4dGVybmFsIEpBUnMuLi4g0aHU8da4z/Jkb3dubG9hZCC1xMK3vrajrLXju/dPS6OsvLS1vMjrs8m5pqGjPGJyPgrPwtTY1+7QwrDmU0RLtcR6aXCw/KOsvavG5NbQtcRsaWJzIM7EvP680LrPsqK1vbG+tdi5pLPMbGlic9fTxL/CvM/CPGJyPgpFY2xpcHNl08O7p9PSvPy5pLPMuPnEv8K8o6zRodTxUHJvcGVydGllcyAtPiBKYXZhIEJ1aWxkIFBhdGggLT4gTGlicmFyaWVzo6zIu7rzteO790FkZCBFeHRlcm5hbCBKQVJzLi4uINGh1PHWuM/yamFytcTCt762o6y147v3T0ujrLy0tbzI67PJuaahozxicj4K16LS4qGjPC9wPgo8cD4KMi60+sLrvdPI68/qveLKudPDy7XD96O6PC9wPgo8cD4KICAgICAgICAg1NrPwtTYtPrC67rzo6zA78Pm09Cyzr+8tPrC66OstPrC67a809DXosrNus2199PDz+q94qOsz8i9sr3iwP3X09bQUmVtRmFzdLX308PA4Mjnus6x4NC0oaM8L3A+CjxwPgogPHByZSBjbGFzcz0="brush:java;">public class RemFast extends Activity { private LayoutInflater mInflater; private Context mcontext; private boolean wheelScrolled = false; // private DomobAdView mAdview320x50; private WheelView wheel_hours; private WheelView wheel_minute; private String remenderTime; private WheelView wheel_month; private WheelView wheel_day; private int beforeMonth = -1; private LinearLayout interGELinearLayout; public static final String[] HOUR_STRING = { "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23" }; public static final String[] MINTUE_STRING = { "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59" }; public static final String[] DAY_STRING = { "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31" }; public static final String[] MONTH_STRING = { "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12" }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout_wheel); mcontext = this; mInflater = LayoutInflater.from(mcontext); createHead(); } /** * layout_remfast布局文件 * * * * * * */ private void createHead() { LinearLayout laymottom = (LinearLayout) findViewById(R.id.four_mottom); //創建一個滑輪子視圖類 View mottom = mInflater.inflate(R.layout.layout_remfast, null); //初始化一個滑輪視圖對象 wheel_month = (WheelView) mottom.findViewById(R.id.fast_month); //設置滑輪標記 wheel_month.setTag("month"); //設置滑輪數據集 wheel_month.setAdapter(new ArrayWheelAdapter(MONTH_STRING)); //設置滑輪當前所在值 wheel_month.setCurrentItem(wheel_month.getCurrentVal("02")); //設置滑輪是否可以循環滑動 wheel_month.setCyclic(true); //設置滑輪標題 wheel_month.setLabel("月"); //添加滑輪變化監聽事件 wheel_month.addChangingListener(wheelChangeListener); //添加滑輪滾動變化監聽事件 wheel_month.addScrollingListener(wheelScrolledListener, null); wheel_day = (WheelView) mottom.findViewById(R.id.fast_day); wheel_day.setAdapter(new ArrayWheelAdapter(DAY_STRING)); wheel_day.setCurrentItem(3); wheel_day.setLabel("天"); wheel_day.setTag("day"); wheel_day.setCyclic(true); wheel_day.addChangingListener(wheelChangeListener); wheel_day.addScrollingListener(wheelScrolledListener, null); wheel_hours = (WheelView) mottom.findViewById(R.id.fast_hours); wheel_hours.setAdapter(new ArrayWheelAdapter(HOUR_STRING)); wheel_hours.setCyclic(true); wheel_hours.setTag("hours"); wheel_minute = (WheelView) mottom.findViewById(R.id.fast_mintue); wheel_minute.setAdapter(new ArrayWheelAdapter(MINTUE_STRING)); wheel_minute.setCyclic(true); wheel_minute.setTag("minute"); wheel_minute.setLabel("分鐘"); wheel_hours.setLabel("小時"); wheel_hours.setCurrentItem(1); wheel_minute.setCurrentItem(2); wheel_minute.addScrollingListener(wheelScrolledListener, null); wheel_minute.addChangingListener(wheelChangeListener); wheel_minute.addScrollingListener(wheelScrolledListener, null); wheel_hours.addChangingListener(wheelChangeListener); wheel_hours.addScrollingListener(wheelScrolledListener, null); wheel_hours.setleftCheck(true); wheel_minute.setleftCheck(true); wheel_day.setleftCheck(true); laymottom.addView(mottom); } OnWheelScrollListener wheelScrolledListener = new OnWheelScrollListener() { public void onScrollingStarted(WheelView wheel) { wheelScrolled = true; } @Override public void onScrollingFinished(WheelView wheel) { // TODO Auto-generated method stub String tag = wheel.getTag().toString(); wheelScrolled = false; } }; // Wheel changed listener private OnWheelChangedListener wheelChangeListener = new OnWheelChangedListener() { @Override public void onLayChanged(WheelView wheel, int oldValue, int newValue, LinearLayout layout) { // TODO Auto-generated method stub } }; }

4.WheelView組件核心代碼詳解如下:

WheelView實現核心原理就是創建一個視圖View,通過監聽手勢和滑動事件得到滑動距離,並繪畫StaticLayout視圖顯示日期值。


public class WheelView extends View {
	/** Scrolling duration */
	private static final int SCROLLING_DURATION = 500;

	/** 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[] { 0xFFfffbf7,
			0xFFffebda, 0xFFffebd9 };
	private static final int[] HSHADOWS_COLORS = new int[] { 0xFFe6e4e4,
			0xFF7d7c7c, 0x5e5d5d };
	private static final int[] BSHADOWS_COLORS = new int[] { 0x5e5d5d,
			0xFF7d7c7c, 0xFFe6e4e4 };
	/** Additional items height (is added to standard text item height) */
	/** Text size */
	private static float TEXT_SIZE = 24;// 24

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

	// 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 valueLayout;
	private StaticLayout srightLayout;
	private StaticLayout sleftLayout;
	// Label & background
	private String label;
	// Scrolling
	private boolean isScrollingPerformed;
	private int scrollingOffset;

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

	// Cyclic
	boolean isCyclic = true;

	// Listeners
	private List changingListeners = new LinkedList();
	private List scrollingListeners = new LinkedList();

	private Context mcontext;
	private onWheelClickListener wClick;

	private LinearLayout mlayout;
	private LinearLayout leftLayout;
	// type view
	private WheelView wview;
	private boolean single = false;
	private int mWidth;
	private int mHeight;

	private boolean leftCheck = false;

	/**
	 * Constructor
	 */
	public WheelView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		mcontext = context;
		initData(context);
		wview = this;
	}

	/**
	 * Constructor
	 */
	public WheelView(Context context, AttributeSet attrs) {
		super(context, attrs);
		mcontext = context;
		initData(context);
		wview = this;
	}

	/**
	 * Constructor
	 */
	public WheelView(Context context) {
		super(context);
		mcontext = context;
		initData(context);
		wview = this;
	}

	/**
	 * Initializes class data
	 * 
	 * @param context
	 *            the context
	 */
	private void initData(Context context) {
		gestureDetector = new GestureDetector(context, gestureListener);
		gestureDetector.setIsLongpressEnabled(false);
		scroller = new Scroller(context);

	}

	@Override
	protected void onFinishInflate() {
		// TODO Auto-generated method stub
		super.onFinishInflate();
//		Log.i("ZYN", "--->getHeight()"+getHeight());
//		
	}

	/**
	 * Gets wheel adapter
	 * 
	 * @return the adapter
	 */
	public WheelAdapter getAdapter() {
		return adapter;
	}

	/**
	 * Sets wheel adapter
	 * 
	 * @param adapter
	 *            the new wheel adapter
	 */
	public void setAdapter(WheelAdapter adapter) {
		this.adapter = adapter;
		invalidateLayouts();
		invalidate();
	}

	/**
	 * Set the the specified scrolling interpolator
	 * 
	 * @param interpolator
	 *            the interpolator
	 */
	public void setInterpolator(Interpolator interpolator) {
		scroller.forceFinished(true);
		scroller = new Scroller(getContext(), interpolator);
	}

	/**
	 * Gets count of visible items
	 * 
	 * @return the count of visible items
	 */
	public int getVisibleItems() {
		return visibleItems;
	}

	/**
	 * Sets count of visible items
	 * 
	 * @param count
	 *            the new count
	 */
	public void setVisibleItems(int count) {
		visibleItems = count;
		invalidate();
	}

	/**
	 * Gets label
	 * 
	 * @return the label
	 */
	public String getLabel() {
		return label;
	}

	/**
	 * Sets label
	 * 
	 * @param newLabel
	 *            the label to set
	 */
	public void setLabel(String newLabel) {
		label = newLabel;
	}

	/**
	 * Adds wheel changing listener
	 * 
	 * @param listener
	 *            the listener
	 */
	public void addChangingListener(OnWheelChangedListener listener) {
		changingListeners.add(listener);
	}

	/**
	 * Removes wheel changing listener
	 * 
	 * @param listener
	 *            the listener
	 */
	public void removeChangingListener(OnWheelChangedListener listener) {
		changingListeners.remove(listener);
	}

	/**
	 * Notifies changing listeners
	 * 
	 * @param oldValue
	 *            the old wheel value
	 * @param newValue
	 *            the new wheel value
	 */
	protected void notifyChangingListeners(int oldValue, int newValue) {
		for (OnWheelChangedListener listener : changingListeners) {
			listener.onLayChanged(this, oldValue, newValue, mlayout);
		}
	}

	/**
	 * Adds wheel scrolling listener
	 * 
	 * @param listener
	 *            the listener
	 */
	public void addScrollingListener(OnWheelScrollListener listener,
			GestureScrollView gs) {
		if (gs != null)
			gs.setGesture(gestureDetector);
		scrollingListeners.add(listener);
	}

	/**
	 * Removes wheel scrolling listener
	 * 
	 * @param listener
	 *            the listener
	 */
	public void removeScrollingListener(OnWheelScrollListener listener) {
		scrollingListeners.remove(listener);
	}

	/**
	 * Notifies listeners about starting scrolling
	 */
	protected void notifyScrollingListenersAboutStart() {
		for (OnWheelScrollListener listener : scrollingListeners) {
			listener.onScrollingStarted(this);
		}
	}

	/**
	 * Notifies listeners about ending scrolling
	 */
	protected void notifyScrollingListenersAboutEnd() {
		for (OnWheelScrollListener listener : scrollingListeners) {
			listener.onScrollingFinished(this);
		}
	}

	/**
	 * Gets current value
	 * 
	 * @return the current value
	 */
	public int getCurrentItem() {
		return currentItem;
	}

	/**
	 * Sets the current item. Does nothing when index is wrong.
	 * 
	 * @param index
	 *            the item index
	 * @param animated
	 *            the animation flag
	 */
	public void setCurrentItem(int index, boolean animated) {
		if (adapter == null || adapter.getItemsCount() == 0) {
			return; // throw?
		}
		if (index < 0 || index >= adapter.getItemsCount()) {
			if (isCyclic) {
				while (index < 0) {
					index += adapter.getItemsCount();
				}
				index %= adapter.getItemsCount();
			} else {
				return; // throw?
			}
		}
		if (index != currentItem) {
			if (animated) {
				scroll(index - currentItem, SCROLLING_DURATION);
			} else {
				invalidateLayouts();
				int old = currentItem;
				currentItem = index;
				notifyChangingListeners(old, currentItem);
				invalidate();
			}
		}
	}

	/**
	 * Sets the current item w/o animation. Does nothing when index is wrong.
	 * 
	 * @param index
	 *            the item index
	 */
	public void setCurrentItem(int index) {
		setCurrentItem(index, false);
	}

	/**
	 * Tests if wheel is cyclic. That means before the 1st item there is shown
	 * the last one
	 * 
	 * @return true if wheel is cyclic
	 */
	public boolean isCyclic() {
		return isCyclic;
	}

	/**
	 * Set wheel cyclic flag
	 * 
	 * @param isCyclic
	 *            the flag to set
	 */
	public void setCyclic(boolean isCyclic) {
		this.isCyclic = isCyclic;
		invalidate();
		invalidateLayouts();
	}

	/**
	 * Invalidates layouts
	 */
	private void invalidateLayouts() {
		valueLayout = null;
		valueLayout = null;
		scrollingOffset = 0;
	}

	/**
	 * Initializes resources
	 */
	private void initResourcesIfNecessary() {
		if (itemsPaint == null) {
			itemsPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG
					| Paint.FAKE_BOLD_TEXT_FLAG);
			itemsPaint.setTextSize(TEXT_SIZE);
			itemsPaint.setTextAlign(Align.CENTER);
		}

		if (valuePaint == null) {
			valuePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG
					| Paint.FAKE_BOLD_TEXT_FLAG | Paint.DITHER_FLAG);
			valuePaint.setTextSize(TEXT_SIZE);
			valuePaint.setShadowLayer(0.1f, 0, 0.1f, 0xFFC0C0C0);
			valuePaint.setTextAlign(Align.CENTER);
		}
		// setBackgroundResource(R.color.font_white);
	}

	/**
	 * Returns text item by index
	 * 
	 * @param index
	 *            the item index
	 * @return the item or null
	 */
	private String getTextItem(int index) {
		if (adapter == null || adapter.getItemsCount() == 0) {
			return null;
		}
		int count = adapter.getItemsCount();
		if ((index < 0 || index >= count) && !isCyclic) {
			return null;
		} else {
			while (index < 0) {
				index = count + index;
			}
		}
		index %= count;
		return adapter.getItem(index);
	}

	/**
	 * Builds text depending on current value
	 * 
	 * @param useCurrentValue
	 * @return the text
	 */
	private String buildText(boolean useCurrentValue) {
		StringBuilder itemsText = new StringBuilder();
		int addItems = visibleItems / 2 + 1;
		for (int i = currentItem - addItems; i <= currentItem + addItems; i++) {
			String text = getTextItem(i);
			if (text != null) {
				itemsText.append(text);
			}
			if (i < currentItem + addItems) {
				itemsText.append("\n");
			}
		}
		return itemsText.toString();
	}

	/**
	 * Returns height of wheel item
	 * 
	 * @return the item height
	 */
	private int getItemHeight() {
		if (itemHeight != 0) {
			return itemHeight;
		} else if (valueLayout != null && valueLayout.getLineCount() > 2) {
			itemHeight = valueLayout.getLineTop(2) - valueLayout.getLineTop(1);
			return itemHeight;
		}
		return getHeight() / visibleItems;
	}

	public int getCurrentVal(String itemVal) {
		int current = 0;
		for (int i = 0; i < adapter.getItemsCount(); i++) {
			if (getTextItem(i).equals(itemVal))
				current = i;
		}
		return current;
	}

	/**
	 * Creates layouts
	 * 
	 * @param widthItems
	 *            width of items layout
	 * @param widthLabel
	 *            width of label layout
	 */
	private void createLayouts() {
		String text = getAdapter() != null ? getAdapter().getItem(currentItem)
				: null;
		int itemHeight = (int) (mHeight / DEF_VISIBLE_ITEMS / 2 - TEXT_SIZE / 2);
		if (single) {
			sleftLayout = new StaticLayout("", valuePaint, 0,
					Layout.Alignment.ALIGN_CENTER, 1, 0.0F, false);
			valueLayout = new StaticLayout(buildText(isScrollingPerformed),
					valuePaint, this.getWidth() * 2 / 3,
					Layout.Alignment.ALIGN_NORMAL, 1, itemHeight * 2 - 4, false);
			srightLayout = new StaticLayout(label == null ? "" : label,
					valuePaint, this.getWidth() / 3,
					Layout.Alignment.ALIGN_CENTER, 1, itemHeight * 2 - 4, false);
		} else {
			sleftLayout = new StaticLayout("", valuePaint, this.getWidth() / 3,
					Layout.Alignment.ALIGN_CENTER, 1, 0.0F, false);
			valueLayout = new StaticLayout(buildText(isScrollingPerformed),
					valuePaint, this.getWidth() / 3,
					Layout.Alignment.ALIGN_NORMAL, 1, itemHeight * 2 - 4, false);
			srightLayout = new StaticLayout(label == null ? "" : label,
					valuePaint, this.getWidth() / 3,
					Layout.Alignment.ALIGN_CENTER, 1, itemHeight * 2 - 4, false);
		}
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		initResourcesIfNecessary();
		createLayouts();
		drawValue(canvas);
		canvas.restore();
		Rect r = new Rect();
		Shader mShader = new LinearGradient(0, 0, 100, 100, SHADOWS_COLORS,
				new float[] { 0, 0.5f, 1.0f }, Shader.TileMode.CLAMP);
		Shader hCheckShader = new LinearGradient(0, 0, 100, 100,
				HSHADOWS_COLORS, new float[] { 0, 0.5f, 1.0f },
				Shader.TileMode.CLAMP);
		Shader bCheckShader = new LinearGradient(0, 0, 100, 100,
				BSHADOWS_COLORS, new float[] { 0, 0.5f, 1.0f },
				Shader.TileMode.CLAMP);
		Paint p = new Paint();
		p.setAntiAlias(true);
		p.setShader(mShader);
		p.setAlpha(127);
		r.left = 0;
		r.top = mHeight / 3;
		r.right = r.left + this.getWidth();
		r.bottom = mHeight / 3 + r.top;
		canvas.drawRect(r, p);
		if (leftCheck) {
			p.setShader(hCheckShader);
			p.setStyle(Paint.Style.FILL);
			Rect rCheck = new Rect();
			rCheck.left = 0;
			rCheck.top = 0;
			rCheck.right = 1;
			rCheck.bottom = (r.bottom + mHeight / 3) / 2;
			canvas.drawRect(rCheck, p);
			p.setShader(bCheckShader);
			Rect bCheck = new Rect();
			bCheck.left = 0;
			bCheck.top = (r.bottom + mHeight / 3) / 2;
			bCheck.right = 1;
			bCheck.bottom = r.bottom + mHeight / 3;
			canvas.drawRect(bCheck, p);
			// Paint rline = new Paint();
			// rline.setStyle(Paint.Style.STROKE);
			// rline.setTextSkewX((float) 3.0);
			// rline.setColor(0xFFffd5b0);
			// canvas.drawLine(0,0,0,r.bottom+mHeight/3, rline);//
		}
		Paint pline = new Paint();
		pline.setColor(0xFFffd5b0);
		pline.setStyle(Paint.Style.FILL);
		pline.setTextSkewX((float) 3.0);
		canvas.drawLine(0, r.top, r.right, r.top, pline);
		canvas.drawLine(0, r.bottom, r.right, r.bottom, pline);//
		canvas.drawLine(0, r.top, 0, r.bottom, pline);//
		canvas.drawLine(r.right, r.top, r.right, r.bottom, pline);//
	}

	/**
	 * Draws value and label layout
	 * 
	 * @param canvas
	 *            the canvas for drawing
	 */
	private void drawValue(Canvas canvas) {
		canvas.save();
		valuePaint.setColor(VALUE_TEXT_COLOR);
		valuePaint.drawableState = getDrawableState();
		int itemHeight = (int) (mHeight / DEF_VISIBLE_ITEMS / 2 - TEXT_SIZE / 2);
		Rect bounds = new Rect();
		if (single) {
			if (sleftLayout != null) {
				canvas.save();
				canvas.translate(0, bounds.top);
				sleftLayout.draw(canvas);
				canvas.restore();
			}
			// // draw label
			if (srightLayout != null) {
				canvas.save();
				canvas.translate((this.getWidth() / 3) * 2, itemHeight * 3
						+ TEXT_SIZE);
				srightLayout.draw(canvas);
				canvas.restore();
			}
			// draw current value
			if (valueLayout != null) {
				canvas.save();
				int top = valueLayout.getLineTop(1);
				//通過游標平移高度
				//其實每次滑動後都會通過View重新繪畫走到這裡。
				canvas.translate(this.getWidth() / 3
						+ (valueLayout.getWidth() / 11) * 2, -top
						+ scrollingOffset + itemHeight);
				itemsPaint.setColor(ITEMS_TEXT_COLOR);
				itemsPaint.drawableState = getDrawableState();
				valueLayout.draw(canvas);
				canvas.restore();
			}
		} else {
			if (sleftLayout != null) {
				canvas.save();
				canvas.translate(this.getWidth() / 4, bounds.top);
				sleftLayout.draw(canvas);
				canvas.restore();
			}
			// draw label
			if (srightLayout != null) {
				canvas.save();
				canvas.translate((this.getWidth() / 3) * 2, itemHeight * 3
						+ TEXT_SIZE);
				srightLayout.draw(canvas);
				canvas.restore();
			}
			// draw current value
			if (valueLayout != null) {
				canvas.save();
				int top = valueLayout.getLineTop(1);
				canvas.translate(this.getWidth() / 3
						+ (valueLayout.getWidth() / 11) * 5, -top
						+ scrollingOffset + itemHeight);
				itemsPaint.setColor(ITEMS_TEXT_COLOR);
				itemsPaint.drawableState = getDrawableState();
				valueLayout.draw(canvas);
				canvas.restore();
			}
		}

	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		WheelAdapter adapter = getAdapter();
		if (adapter == null) {
			return true;
		}
		if (!gestureDetector.onTouchEvent(event)
				&& event.getAction() == MotionEvent.ACTION_UP)
			justify();
		return true;
	}

	/**
	 * Scrolls the wheel
	 * 
	 * @param delta
	 *            the scrolling value
	 */
	private void doScroll(int delta) {
		scrollingOffset += delta;
		int count = scrollingOffset / getItemHeight();
		int pos = currentItem - count;
		if (isCyclic && adapter.getItemsCount() > 0) {
			// fix position by rotating
			while (pos < 0) {
				pos += adapter.getItemsCount();
			}
			pos %= adapter.getItemsCount();
		} else if (isScrollingPerformed) {
			//
			if (pos < 0) {
				count = currentItem;
				pos = 0;
			} else if (pos >= adapter.getItemsCount()) {
				count = currentItem - adapter.getItemsCount() + 1;
				pos = adapter.getItemsCount() - 1;
			}
		} else {
			// fix position
			pos = Math.max(pos, 0);
			pos = Math.min(pos, adapter.getItemsCount() - 1);
		}

		int offset = scrollingOffset;
		if (pos != currentItem) {
			setCurrentItem(pos, false);
		} else {
			invalidate();
		}

		// update offset
		scrollingOffset = offset - count * getItemHeight();
		if (scrollingOffset > getHeight()) {
			scrollingOffset = scrollingOffset % getHeight() + getHeight();
		}
	}

	// gesture listener
	private SimpleOnGestureListener gestureListener = new SimpleOnGestureListener() {
		public boolean onDown(MotionEvent e) {
			if (wview.getTag() != null && wClick != null)
				wClick.onClick(wview.getTag());
			if (isScrollingPerformed) {
				scroller.forceFinished(true);
				clearMessages();
				return true;
			}
			return false;
		}

		public boolean onScroll(MotionEvent e1, MotionEvent e2,
				float distanceX, float distanceY) {
			startScrolling();
			doScroll((int) -distanceY);
			return true;
		}

		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
				float velocityY) {
			lastScrollY = currentItem * getItemHeight() + scrollingOffset;
			int maxY = isCyclic ? 0x7FFFFFFF : adapter.getItemsCount()
					* getItemHeight();
			int minY = isCyclic ? -maxY : 0;
			scroller.fling(0, lastScrollY, 0, (int) -velocityY / 2, 0, 0, minY,
					maxY);
			setNextMessage(MESSAGE_SCROLL);
			return true;
		}

		@Override
		public boolean onSingleTapUp(MotionEvent e) {
			// TODO Auto-generated method stub
			return super.onSingleTapUp(e);
		}

	};

	// Messages
	private final int MESSAGE_SCROLL = 0;
	private final int MESSAGE_JUSTIFY = 1;

	/**
	 * Set next message to queue. Clears queue before.
	 * 
	 * @param message
	 *            the message to set
	 */
	private void setNextMessage(int message) {
		clearMessages();
		animationHandler.sendEmptyMessage(message);
	}

	/**
	 * Clears messages from queue
	 */
	private void clearMessages() {
		animationHandler.removeMessages(MESSAGE_SCROLL);
		animationHandler.removeMessages(MESSAGE_JUSTIFY);
	}

	// animation handler
	private Handler animationHandler = new Handler() {
		public void handleMessage(Message msg) {
			scroller.computeScrollOffset();
			int currY = scroller.getCurrY();
			int delta = lastScrollY - currY;
			lastScrollY = currY;
			if (delta != 0) {
				doScroll(delta);
			}

			// scrolling is not finished when it comes to final Y
			// so, finish it manually
			if (Math.abs(currY - scroller.getFinalY()) < MIN_DELTA_FOR_SCROLLING) {
				currY = scroller.getFinalY();
				scroller.forceFinished(true);
			}
			if (!scroller.isFinished()) {
				animationHandler.sendEmptyMessage(msg.what);
			} else if (msg.what == MESSAGE_SCROLL) {
				justify();
			} else {
				finishScrolling();
			}
		}
	};

	/**
	 * Justifies wheel
	 */
	private void justify() {
		if (adapter == null) {
			return;
		}
		lastScrollY = 0;
		int offset = scrollingOffset;
		int itemHeight = getItemHeight();
		boolean needToIncrease = offset > 0 ? currentItem < adapter
				.getItemsCount() : currentItem > 0;
		if ((isCyclic || needToIncrease)
				&& Math.abs((float) offset) > (float) itemHeight / 2) {
			if (offset < 0)
				offset += itemHeight + MIN_DELTA_FOR_SCROLLING;
			else
				offset -= itemHeight + MIN_DELTA_FOR_SCROLLING;
		}
		if (Math.abs(offset) > MIN_DELTA_FOR_SCROLLING) {
			scroller.startScroll(0, 0, 0, offset, SCROLLING_DURATION);
			setNextMessage(MESSAGE_JUSTIFY);
		} else {
			finishScrolling();
		}
	}

	/**
	 * Starts scrolling
	 */
	private void startScrolling() {
		if (!isScrollingPerformed) {
			isScrollingPerformed = true;
			notifyScrollingListenersAboutStart();
		}
	}

	/**
	 * Finishes scrolling
	 */
	void finishScrolling() {
		if (isScrollingPerformed) {
			notifyScrollingListenersAboutEnd();
			isScrollingPerformed = false;
		}
		invalidateLayouts();
		invalidate();
	}

	/**
	 * 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();
	}

	public void setWheelClick(onWheelClickListener l) {
		wClick = l;
	}

	public void setSingle() {
		single = true;
	}

	public void setViewHeight(int height) {
		mHeight = height;
	}

	public void setleftCheck(boolean mleftCheck) {
		leftCheck = mleftCheck;
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// TODO Auto-generated method stub
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
		final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
		mHeight =heightSize;
		setMeasuredDimension(widthSize, heightSize);
	}
}



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