仿正点闹钟的时钟拨轮效果(ScrollView 的无限循环滚动)

      最近要做一个闹钟的应用,感觉android自带的TimePickerDialog不是太好,于是想做一个时钟拨轮效果,在网上搜了很多久也没有看到相应的资料,于是自己动手做一个。

     首先是判断scrollview是否停下来(每隔50毫秒取getScrollY()值是否和上一次取的一样,一样的话就表明已经停止滑动),再调scrollTo(x , y) 让它定位到最近的时间刻度。关键是如何让他能循环的滚动,我是通过取3组相同的刻度如:0~23 ,0~59各取3组,当滑动显示的3格完全超出了中间那组(第2组),再调用scrollTo(x,y)让他返回到中间组的相同位置。

     说的可能有点晕:直接看代码吧:





public class AlarmSetActivity extends Activity {
	private String TAG = "AlarmSetActivity";
	private TimeWheel timeWheel;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_alarm_set);
		timeWheel = new TimeWheel(this, 0, 0);
		LinearLayout foot = (LinearLayout) this.findViewById(R.id.ll_timeset);
		foot.addView(timeWheel);
	}
		


package cn.cowry.android.alarmclock;

import android.content.Context;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.animation.TranslateAnimation;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import cn.cowry.android.activity.R;

public class TimeWheel extends LinearLayout {

	private String TAG = "TimeWheel";
	private TextView tv01 ,tv02;
	private ScrollView sv01 , sv02;
	private LinearLayout ll01 , ll02 ,llTimeWheel;
	private int lastY ;
	private int flag ;//标识时分
	private int itemHeight;//每一行的高度
	private int pHour , pMinute;//初始化时显示的时分时间
	
	public TimeWheel(Context context) {
		super(context);
	}
	
	/**
	 * 
	 * @param context
	 * @param hour  初始化时显示的时
	 * @param minute  初始化时显示的分
	 */
	public TimeWheel(Context context ,final int hour ,final int minute) {
		this(context);
		View.inflate(context, R.layout.time_wheel, this);
		tv01 = (TextView)this.findViewById(R.id.tv01);
		tv02 = (TextView)this.findViewById(R.id.tv02);
		sv01 = (ScrollView)this.findViewById(R.id.sv01);
		sv02 = (ScrollView)this.findViewById(R.id.sv02);
		ll01 = (LinearLayout)this.findViewById(R.id.ll01);
		ll02 = (LinearLayout)this.findViewById(R.id.ll02);
		this.pHour = hour ;
		this.pMinute = minute;
		//tv01.setTextSize(50);
		
		
		llTimeWheel = (LinearLayout)this.findViewById(R.id.ll_time_wheel);
		setHourDial(tv01);
		setMinuteDial(tv02);
		
		sv01.setOnTouchListener(tListener);
		sv02.setOnTouchListener(tListener);
		
		final ViewTreeObserver observer = sv01.getViewTreeObserver();//observer 作用当视图完全加载进来的时候再取控件的高度,否则取得值是0
		observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
			
			public void onGlobalLayout() {
				// TODO Auto-generated method stub
				//test();
				int tvHeight = tv02.getHeight();
				itemHeight = tvHeight/180;
				if(sv01.getViewTreeObserver().isAlive()){
					sv01.getViewTreeObserver().removeGlobalOnLayoutListener(this);
				}
				Log.i(TAG, "**********itemHeight = "+itemHeight + "tvHeight = " + tvHeight);
				LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, (itemHeight*3));
				llTimeWheel.setLayoutParams(params);
				
				sv01.scrollTo(0 , (pHour+24)*itemHeight);
				sv02.scrollTo(0 , (pMinute+60)*itemHeight);
				
				//Log.i(TAG, "tv01---  " + tv01.getWidth() + "  tv02 ---  "+tv02.getWidth() +  "  ----" +(itemHeight*3));
				//Log.i(TAG, "llTimeWheel---  " + llTimeWheel.getHeight() + " ---  "+llTimeWheel.getMeasuredHeight());
			}
		});
		
		
		
	}
	
	private OnTouchListener tListener = new OnTouchListener() {
		
		public boolean onTouch(View v, MotionEvent event) {
			// TODO Auto-generated method stub
			if(v == sv01){
				flag = 1;
			}else{
				flag = 2;
			}
			Log.i(TAG , "aciton ========== " + event.getAction());
			if(event.getAction() == MotionEvent.ACTION_UP){
				final ScrollView sv = (ScrollView)v;
				lastY = sv.getScrollY();
				Log.i(TAG, "-----------lastY---------"+lastY);
				handler.sendMessageDelayed(handler.obtainMessage(0, v), 50);
			}
			return false;
		}
	};
	
	
	
	private Handler handler = new Handler(){
		public void handleMessage(android.os.Message msg) {
			ScrollView sv = (ScrollView)msg.obj;
			
			if(msg.what == 0){
				Log.i(TAG, "lastY = " + lastY + "----sv.getScrollY() = "+sv.getScrollY());
				if(lastY == sv.getScrollY()){
					   
						int num = lastY/itemHeight;
						int over = lastY%itemHeight;
						Log.i(TAG, "num == " + num + "  over == " + over);
						if(over > itemHeight/2){//超过一半滚到下一格
							locationTo((num+1)*itemHeight , sv , flag);
						}else{//不到一半滚回上一格
							locationTo(num*itemHeight , sv , flag);
						}
				}else{
					lastY = sv.getScrollY();
					handler.sendMessageDelayed(handler.obtainMessage(0, sv), 50);//滚动还没停止隔50毫秒再判断 
				}
			}
			
		};
	};
	
	private void locationTo(int position , ScrollView scrollview , int flag){
		Log.i(TAG, "position == " + position);
		switch (flag) {
		case 1:
			if(position <= 23*itemHeight){
				Log.i(TAG, "position =1111= " + (position+24*itemHeight));
				scrollview.scrollTo(0, (position+24*itemHeight));
			}else if(position >= 48*itemHeight){
				Log.i(TAG, "position =2222= " + (position-24*itemHeight));
				scrollview.scrollTo(0, (position-24*itemHeight));
			}else{
				Log.i(TAG, "position =3333= " +  position);
				scrollview.smoothScrollTo(0, position);
			}
			break;

		case 2:
			if(position <= 57*itemHeight){
				Log.i(TAG, "position =1111= " + (position+60*itemHeight));
				scrollview.scrollTo(0, (position+60*itemHeight));
			}else if(position >= 120*itemHeight){
				Log.i(TAG, "position =2222= " + (position-60*itemHeight));
				scrollview.scrollTo(0, (position-60*itemHeight));
			}else{
				Log.i(TAG, "position =3333= " +  position);
				scrollview.smoothScrollTo(0, position);
			}
			
			break;
		}
		
		
		/*if(isdoubleDetect){
			handler.sendMessageDelayed(handler.obtainMessage(0, scrollview), 50);
			scrollview.performClick();
			//tv02.performClick();
			//ll02.performClick();
			isdoubleDetect = false;
			Log.i(TAG, "----------------");
		}*/
		
	}
	
	/**
	 * 设置分刻度盘
	 * @param tv
	 */
	
	private void setMinuteDial(TextView tv){
		StringBuffer buff = new StringBuffer();
		for(int i = 0 ; i < 3 ; i++){
			for(int j = 0 ; j < 60 ; j++){
				if(j <= 9){
					buff.append("0" + j);
				}else{
					buff.append(j+"");
				}
			}
		}
		
		tv.setText(buff);
	}
	
	/**
	 * 设置时刻度盘
	 * @param tv
	 */
	private void setHourDial(TextView tv){
		StringBuffer buff = new StringBuffer();
		for(int i = 0 ; i < 3 ; i++){
			for(int j = 0 ; j < 24 ; j++){
				if(j <= 9){
					buff.append("0" + j);
				}else{
					buff.append(j+"");
				}
			}
		}
		
		tv.setText(buff);
	}
	
	
	public void setpHour(int pHour) {
		this.pHour = pHour;
	}
	
	public void setpMinute(int pMinute) {
		this.pMinute = pMinute;
	}
	
	
	

















}


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="#ffffff" 
        android:id="@+id/ll_timeset"
        android:orientation="vertical">

   
</LinearLayout>


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="100dp"
    android:orientation="horizontal" 
    android:background="@drawable/bg_time_wheel"
    android:id="@+id/ll_time_wheel">
    
    <FrameLayout 
        android:layout_width="0dp"
        android:layout_height="fill_parent"
        android:layout_weight="1.0">
        
         <TextView android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="时"
            android:textSize="40sp"
            android:textColor="#000000"
            android:layout_gravity="right|center_vertical"/>
        
        <ScrollView android:id="@+id/sv01"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        >
        
        <LinearLayout 
            android:id="@+id/ll01"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:orientation="horizontal">
            <TextView android:id="@+id/tv01"
                android:layout_width="50dp"
                android:layout_height="wrap_content"
                android:gravity="center_horizontal"
                android:background="#ff00ff"
                android:paddingLeft="10dp"
                android:paddingRight="10dp"
                android:text="012345678901234567890123456789"
                android:textSize="26dp"
                android:lineSpacingExtra="20dp"
                />
        </LinearLayout>
        
    </ScrollView>
    </FrameLayout>
    
    
    
    
    <FrameLayout 
        android:layout_width="0dp"
        android:layout_height="fill_parent"
        android:layout_weight="1.0">
        
         <TextView android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="分"
            android:textSize="40sp"
            android:textColor="#000000"
            android:layout_gravity="right|center_vertical"/>
         
    <ScrollView android:id="@+id/sv02"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        >
        
        <LinearLayout 
            android:id="@+id/ll02"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal">
            <TextView android:id="@+id/tv02"
                android:layout_width="50dp"
                android:layout_height="wrap_content"
                android:gravity="center_horizontal"
                android:background="#ff00ff"
                android:paddingLeft="10dp"
                android:paddingRight="10dp"
                android:text="012345678901234567890123456789"
                android:textSize="26dp"
                android:lineSpacingExtra="20dp"/>
        </LinearLayout>
        
    </ScrollView>
    </FrameLayout>

</LinearLayout>

 

 



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值