最近要做一个闹钟的应用,感觉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>