Android学习笔记(一)之仿正点闹钟时间齿轮滑动的效果

看到正点闹钟上的设置时间的滑动效果非常好看,自己就想做一个那样的,在网上就开始搜资料了,看到网上有的齿轮效果的代码非常多,也非常难懂,我就决定自己研究一下,现在我就把我的研究成果分享给大家。我研究的这个效果出来了,而且代码也非常简单,通俗易懂。效果图如下:

Android学习笔记(一)之仿正点闹钟时间齿轮滑动的效果

首先是MainActivity的布局文件,这个布局文件非常简单,就是一个Button:activity_main.xml文件,代码如下:

[html] view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:id="@+id/ll_timeset"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     android:background="#ffffff"  
  7.     android:orientation="vertical" >  
  8.   
  9.     <Button  
  10.         android:id="@+id/btn"  
  11.         android:layout_width="fill_parent"  
  12.         android:layout_height="wrap_content"  
  13.         android:gravity="center"  
  14.         android:text="时间设置"  
  15.         android:textSize="24sp" />  
  16.   
  17. </LinearLayout>  

紧接着就是MainActivity的代码,代码如下:
[java] view plain copy
  1. package net.loonggg.test;  
  2.   
  3. import net.loonggg.view.CustomerDateDialog;  
  4. import net.loonggg.view.CustomerDateDialog.DateDialogListener;  
  5. import android.app.Activity;  
  6. import android.os.Bundle;  
  7. import android.text.format.DateFormat;  
  8. import android.view.View;  
  9. import android.view.Window;  
  10. import android.widget.Button;  
  11. import android.widget.Toast;  
  12.   
  13. public class MainActivity extends Activity {  
  14.     private int h, m;  
  15.     private CustomerDateDialog dialog;  
  16.     private Button btn;  
  17.   
  18.     @Override  
  19.     protected void onCreate(Bundle savedInstanceState) {  
  20.         super.onCreate(savedInstanceState);  
  21.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  22.         setContentView(R.layout.activity_main);  
  23.         btn = (Button) findViewById(R.id.btn);  
  24.         btn.setOnClickListener(new View.OnClickListener() {  
  25.   
  26.             @Override  
  27.             public void onClick(View v) {  
  28.                 String datetime = DateFormat.format("kk:mm",  
  29.                         System.currentTimeMillis()).toString();  
  30.                 String[] strs = datetime.split(":");  
  31.                 h = Integer.parseInt(strs[0]);  
  32.                 m = Integer.parseInt(strs[1]);  
  33.                 dialog = new CustomerDateDialog(MainActivity.this, h, m);  
  34.                 dialog.show();  
  35.                 dialog.setOnDateDialogListener(new DateDialogListener() {  
  36.                     @Override  
  37.                     public void getDate() {  
  38.                         Toast.makeText(  
  39.                                 MainActivity.this,  
  40.                                 "时间是:" + dialog.getSettingHour() + "点"  
  41.                                         + dialog.getSettingMinute() + "分",  
  42.                                 Toast.LENGTH_LONG).show();  
  43.                     }  
  44.                 });  
  45.   
  46.             }  
  47.         });  
  48.   
  49.     }  
  50.   
  51. }  

再就是我自定义了一个时钟的Dialog,自定义Dialog也非常简单,自己可以学一下,这方面网上的资料非常多。现在我把我自定义时钟的Dialog的代码分享一下,代码如下:
[java] view plain copy
  1. package net.loonggg.view;  
  2.   
  3. import net.loonggg.test.R;  
  4. import android.annotation.SuppressLint;  
  5. import android.app.Dialog;  
  6. import android.content.Context;  
  7. import android.os.Bundle;  
  8. import android.os.Handler;  
  9. import android.view.LayoutInflater;  
  10. import android.view.MotionEvent;  
  11. import android.view.View;  
  12. import android.view.View.OnTouchListener;  
  13. import android.view.ViewTreeObserver;  
  14. import android.view.ViewTreeObserver.OnGlobalLayoutListener;  
  15. import android.widget.Button;  
  16. import android.widget.LinearLayout;  
  17. import android.widget.ScrollView;  
  18. import android.widget.TextView;  
  19.   
  20. @SuppressLint("HandlerLeak")  
  21. public class CustomerDateDialog extends Dialog {  
  22.     private View customView;  
  23.     private Button setBtn;  
  24.     private Button cancleBtn;  
  25.     private TextView arrow_up;  
  26.     private TextView tv01, tv02;  
  27.     private ScrollView sv01, sv02;  
  28.     private LinearLayout llTimeWheel;  
  29.     private DateDialogListener listener;  
  30.     private int lastY;  
  31.     private int flag;// 标记时分  
  32.     private int itemHeight;// 每一行的高度  
  33.     private int pHour, pMinute;// 初始化时显示的时分时间  
  34.     private int setHour, setMinute;  
  35.   
  36.     public CustomerDateDialog(Context context, int hour, int minute) {  
  37.         super(context, R.style.CustomerDateDialog);  
  38.         customView = LayoutInflater.from(context).inflate(R.layout.time_wheel,  
  39.                 null);  
  40.         init(context, hour, minute);  
  41.     }  
  42.   
  43.     @Override  
  44.     protected void onCreate(Bundle savedInstanceState) {  
  45.         super.onCreate(savedInstanceState);  
  46.         this.setContentView(customView);  
  47.     }  
  48.   
  49.     private void init(Context context, final int hour, final int minute) {  
  50.         tv01 = (TextView) customView.findViewById(R.id.tv01);  
  51.         tv02 = (TextView) customView.findViewById(R.id.tv02);  
  52.         sv01 = (ScrollView) customView.findViewById(R.id.sv01);  
  53.         sv02 = (ScrollView) customView.findViewById(R.id.sv02);  
  54.         setBtn = (Button) customView.findViewById(R.id.setBtn);  
  55.         cancleBtn = (Button) customView.findViewById(R.id.cancleBtn);  
  56.         arrow_up = (TextView) customView.findViewById(R.id.arrow_up);  
  57.         this.pHour = hour;  
  58.         this.pMinute = minute;  
  59.         setHour = pHour;  
  60.         setMinute = pMinute;  
  61.   
  62.         llTimeWheel = (LinearLayout) customView  
  63.                 .findViewById(R.id.ll_time_wheel);  
  64.         setHourDial(tv01);  
  65.         setMinuteDial(tv02);  
  66.   
  67.         sv01.setOnTouchListener(tListener);  
  68.         sv02.setOnTouchListener(tListener);  
  69.   
  70.         final ViewTreeObserver observer = sv01.getViewTreeObserver();// observer  
  71.                                                                         // 作用当视图完全加载进来的时候再取控件的高度,否则取得值是0  
  72.         observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {  
  73.   
  74.             @SuppressWarnings("deprecation")  
  75.             public void onGlobalLayout() {  
  76.                 int tvHeight = tv02.getHeight();  
  77.                 itemHeight = tvHeight / 180;  
  78.                 if (sv01.getViewTreeObserver().isAlive()) {  
  79.                     sv01.getViewTreeObserver().removeGlobalOnLayoutListener(  
  80.                             this);  
  81.                 }  
  82.                 LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(  
  83.                         LinearLayout.LayoutParams.FILL_PARENT, (itemHeight * 3)  
  84.                                 + arrow_up.getHeight() * 2);  
  85.                 llTimeWheel.setLayoutParams(params);  
  86.                 sv01.setLayoutParams(new LinearLayout.LayoutParams(tv02  
  87.                         .getWidth(), (itemHeight * 3)));  
  88.                 sv02.setLayoutParams(new LinearLayout.LayoutParams(tv02  
  89.                         .getWidth(), (itemHeight * 3)));  
  90.                 sv01.scrollTo(0, (pHour + 23) * itemHeight);  
  91.                 sv02.scrollTo(0, (pMinute + 59) * itemHeight);  
  92.   
  93.             }  
  94.         });  
  95.   
  96.         setBtn.setOnClickListener(new View.OnClickListener() {  
  97.   
  98.             @Override  
  99.             public void onClick(View v) {  
  100.                 getSettingDate();  
  101.                 CustomerDateDialog.this.cancel();  
  102.             }  
  103.         });  
  104.   
  105.         cancleBtn.setOnClickListener(new View.OnClickListener() {  
  106.   
  107.             @Override  
  108.             public void onClick(View v) {  
  109.                 CustomerDateDialog.this.cancel();  
  110.             }  
  111.         });  
  112.     }  
  113.   
  114.     private OnTouchListener tListener = new OnTouchListener() {  
  115.   
  116.         public boolean onTouch(View v, MotionEvent event) {  
  117.             if (v == sv01) {  
  118.                 flag = 1;  
  119.             } else {  
  120.                 flag = 2;  
  121.             }  
  122.             if (event.getAction() == MotionEvent.ACTION_UP) {  
  123.                 final ScrollView sv = (ScrollView) v;  
  124.                 lastY = sv.getScrollY();  
  125.                 System.out.println("lastY" + lastY);  
  126.                 handler.sendMessageDelayed(handler.obtainMessage(0, v), 50);  
  127.             }  
  128.             return false;  
  129.         }  
  130.     };  
  131.   
  132.     private Handler handler = new Handler() {  
  133.         @SuppressLint("HandlerLeak")  
  134.         public void handleMessage(android.os.Message msg) {  
  135.             ScrollView sv = (ScrollView) msg.obj;  
  136.   
  137.             if (msg.what == 0) {  
  138.                 if (lastY == sv.getScrollY()) {  
  139.   
  140.                     int num = lastY / itemHeight;  
  141.                     int over = lastY % itemHeight;  
  142.                     if (over > itemHeight / 2) {// 超过一半滚到下一格  
  143.                         locationTo((num + 1) * itemHeight, sv, flag);  
  144.                     } else {// 不到一半滚回上一格  
  145.                         locationTo(num * itemHeight, sv, flag);  
  146.                     }  
  147.                 } else {  
  148.                     lastY = sv.getScrollY();  
  149.                     handler.sendMessageDelayed(handler.obtainMessage(0, sv), 50);// 滚动还没停止隔50毫秒再判断  
  150.                 }  
  151.             }  
  152.   
  153.         };  
  154.     };  
  155.   
  156.     private void locationTo(int position, ScrollView scrollview, int flag) {  
  157.         switch (flag) {  
  158.         case 1:  
  159.             int mPosition = 0;  
  160.             if (position <= 23 * itemHeight) {  
  161.                 mPosition = position + 24 * itemHeight;  
  162.                 scrollview.scrollTo(0, mPosition);  
  163.             } else if (position >= 48 * itemHeight) {  
  164.                 mPosition = position - 24 * itemHeight;  
  165.                 scrollview.scrollTo(0, mPosition);  
  166.             } else {  
  167.                 mPosition = position;  
  168.                 scrollview.smoothScrollTo(0, position);  
  169.             }  
  170.             setHour = (mPosition / itemHeight - 23) % 24;  
  171.             break;  
  172.   
  173.         case 2:  
  174.             int hPosition = 0;  
  175.             if (position <= 57 * itemHeight) {  
  176.                 hPosition = position + 60 * itemHeight;  
  177.                 scrollview.scrollTo(0, hPosition);  
  178.             } else if (position >= 120 * itemHeight) {  
  179.                 hPosition = position - 60 * itemHeight;  
  180.                 scrollview.scrollTo(0, hPosition);  
  181.             } else {  
  182.                 hPosition = position;  
  183.                 scrollview.smoothScrollTo(0, position);  
  184.             }  
  185.             setMinute = (hPosition / itemHeight) % 60 + 1;  
  186.             break;  
  187.         }  
  188.   
  189.     }  
  190.   
  191.     /** 
  192.      * 设置分刻度盘 
  193.      *  
  194.      * @param tv 
  195.      */  
  196.   
  197.     private void setMinuteDial(TextView tv) {  
  198.         StringBuffer buff = new StringBuffer();  
  199.         for (int i = 0; i < 3; i++) {  
  200.             for (int j = 0; j < 60; j++) {  
  201.                 if (j <= 9) {  
  202.                     buff.append("0" + j);  
  203.                 } else {  
  204.                     buff.append(j + "");  
  205.                 }  
  206.             }  
  207.         }  
  208.   
  209.         tv.setText(buff);  
  210.     }  
  211.   
  212.     /** 
  213.      * 设置时刻度盘 
  214.      *  
  215.      * @param tv 
  216.      */  
  217.     private void setHourDial(TextView tv) {  
  218.         StringBuffer buff = new StringBuffer();  
  219.         for (int i = 0; i < 3; i++) {  
  220.             for (int j = 0; j < 24; j++) {  
  221.                 if (j <= 9) {  
  222.                     buff.append("0" + j);  
  223.                 } else {  
  224.                     buff.append(j + "");  
  225.                 }  
  226.             }  
  227.   
  228.         }  
  229.   
  230.         tv.setText(buff);  
  231.     }  
  232.   
  233.     public void setpHour(int pHour) {  
  234.         this.pHour = pHour;  
  235.     }  
  236.   
  237.     public void setpMinute(int pMinute) {  
  238.         this.pMinute = pMinute;  
  239.     }  
  240.   
  241.     public void setOnDateDialogListener(DateDialogListener listener) {  
  242.         this.listener = listener;  
  243.     }  
  244.   
  245.     public interface DateDialogListener {  
  246.         void getDate();  
  247.     }  
  248.   
  249.     public void getSettingDate() {  
  250.         if (listener != null) {  
  251.             listener.getDate();  
  252.         }  
  253.     }  
  254.   
  255.     public int getSettingHour() {  
  256.         return setHour;  
  257.     }  
  258.   
  259.     public int getSettingMinute() {  
  260.         return setMinute;  
  261.     }  
  262.   
  263. }  

这里光有java代码还不够,还有自定义Dialog的布局文件,time_wheel.xml代码如下:
[html] view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="wrap_content"  
  5.     android:background="#efefef"  
  6.     android:orientation="vertical" >  
  7.   
  8.     <TextView  
  9.         android:layout_width="fill_parent"  
  10.         android:layout_height="wrap_content"  
  11.         android:background="@color/light_black"  
  12.         android:paddingLeft="10dp"  
  13.         android:text="设置时间"  
  14.         android:textColor="@color/black"  
  15.         android:textSize="24sp" />  
  16.   
  17.     <!-- 时间的相关设置 -->  
  18.   
  19.     <LinearLayout  
  20.         android:id="@+id/ll_time_wheel"  
  21.         android:layout_width="fill_parent"  
  22.         android:layout_height="wrap_content"  
  23.         android:layout_marginTop="15dp"  
  24.         android:background="#f0f0f0"  
  25.         android:gravity="center_horizontal"  
  26.         android:orientation="horizontal" >  
  27.   
  28.         <LinearLayout  
  29.             android:layout_width="wrap_content"  
  30.             android:layout_height="wrap_content"  
  31.             android:orientation="vertical" >  
  32.   
  33.             <TextView  
  34.                 android:layout_width="30dp"  
  35.                 android:layout_height="wrap_content"  
  36.                 android:layout_gravity="center_horizontal"  
  37.                 android:background="@drawable/wheel_arrow_up" />  
  38.   
  39.             <ScrollView  
  40.                 android:id="@+id/sv01"  
  41.                 android:layout_width="50dp"  
  42.                 android:layout_height="wrap_content"  
  43.                 android:layout_gravity="center_horizontal"  
  44.                 android:background="@drawable/time_bg"  
  45.                 android:scrollbars="none" >  
  46.   
  47.                 <LinearLayout  
  48.                     android:id="@+id/ll01"  
  49.                     android:layout_width="50dp"  
  50.                     android:layout_height="wrap_content"  
  51.                     android:gravity="center"  
  52.                     android:orientation="horizontal"  
  53.                     android:paddingTop="5dp" >  
  54.   
  55.                     <TextView  
  56.                         android:id="@+id/tv01"  
  57.                         android:layout_width="50dp"  
  58.                         android:layout_height="wrap_content"  
  59.                         android:gravity="center"  
  60.                         android:lineSpacingExtra="20dp"  
  61.                         android:paddingLeft="10dp"  
  62.                         android:paddingRight="10dp"  
  63.                         android:textSize="26sp" />  
  64.                 </LinearLayout>  
  65.             </ScrollView>  
  66.   
  67.             <TextView  
  68.                 android:layout_width="30dp"  
  69.                 android:layout_height="wrap_content"  
  70.                 android:layout_gravity="center_horizontal"  
  71.                 android:background="@drawable/wheel_arrow_down" />  
  72.         </LinearLayout>  
  73.   
  74.         <TextView  
  75.             android:layout_width="wrap_content"  
  76.             android:layout_height="fill_parent"  
  77.             android:layout_gravity="center"  
  78.             android:background="#f0f0f0"  
  79.             android:gravity="center"  
  80.             android:text="时"  
  81.             android:textColor="#000000"  
  82.             android:textSize="25sp" />  
  83.   
  84.         <LinearLayout  
  85.             android:layout_width="wrap_content"  
  86.             android:layout_height="wrap_content"  
  87.             android:orientation="vertical" >  
  88.   
  89.             <TextView  
  90.                 android:id="@+id/arrow_up"  
  91.                 android:layout_width="30dp"  
  92.                 android:layout_height="wrap_content"  
  93.                 android:layout_gravity="center_horizontal"  
  94.                 android:background="@drawable/wheel_arrow_up" />  
  95.   
  96.             <ScrollView  
  97.                 android:id="@+id/sv02"  
  98.                 android:layout_width="50dp"  
  99.                 android:layout_height="wrap_content"  
  100.                 android:layout_gravity="center_horizontal"  
  101.                 android:background="@drawable/time_bg"  
  102.                 android:scrollbars="none" >  
  103.   
  104.                 <LinearLayout  
  105.                     android:id="@+id/ll02"  
  106.                     android:layout_width="50dp"  
  107.                     android:layout_height="wrap_content"  
  108.                     android:gravity="center"  
  109.                     android:paddingTop="5dp" >  
  110.   
  111.                     <TextView  
  112.                         android:id="@+id/tv02"  
  113.                         android:layout_width="50dp"  
  114.                         android:layout_height="wrap_content"  
  115.                         android:gravity="center"  
  116.                         android:lineSpacingExtra="20dp"  
  117.                         android:paddingLeft="10dp"  
  118.                         android:paddingRight="10dp"  
  119.                         android:textSize="26sp" />  
  120.                 </LinearLayout>  
  121.             </ScrollView>  
  122.   
  123.             <TextView  
  124.                 android:id="@+id/arrow_down"  
  125.                 android:layout_width="30dp"  
  126.                 android:layout_height="wrap_content"  
  127.                 android:layout_gravity="center_horizontal"  
  128.                 android:background="@drawable/wheel_arrow_down" />  
  129.         </LinearLayout>  
  130.   
  131.         <TextView  
  132.             android:layout_width="wrap_content"  
  133.             android:layout_height="fill_parent"  
  134.             android:layout_gravity="center"  
  135.             android:background="#f0f0f0"  
  136.             android:gravity="center"  
  137.             android:text="分"  
  138.             android:textColor="#000000"  
  139.             android:textSize="25sp" />  
  140.     </LinearLayout>  
  141.   
  142.     <!-- 设置时钟的按钮 -->  
  143.   
  144.     <RelativeLayout  
  145.         android:layout_width="fill_parent"  
  146.         android:layout_height="50dp" >  
  147.   
  148.         <Button  
  149.             android:id="@+id/setBtn"  
  150.             android:layout_width="wrap_content"  
  151.             android:layout_height="wrap_content"  
  152.             android:layout_alignParentLeft="true"  
  153.             android:layout_gravity="center_horizontal"  
  154.             android:layout_marginLeft="25dp"  
  155.             android:background="@drawable/btn_clock_normal"  
  156.             android:gravity="center"  
  157.             android:paddingLeft="10dp"  
  158.             android:paddingRight="10dp"  
  159.             android:text="确定"  
  160.             android:textColor="#000000"  
  161.             android:textSize="24sp" />  
  162.   
  163.         <Button  
  164.             android:id="@+id/cancleBtn"  
  165.             android:layout_width="wrap_content"  
  166.             android:layout_height="wrap_content"  
  167.             android:layout_alignParentRight="true"  
  168.             android:layout_gravity="center_horizontal"  
  169.             android:layout_marginRight="25dp"  
  170.             android:background="@drawable/btn_clock_normal"  
  171.             android:gravity="center"  
  172.             android:paddingLeft="10dp"  
  173.             android:paddingRight="10dp"  
  174.             android:text="取消"  
  175.             android:textColor="#000000"  
  176.             android:textSize="24sp" />  
  177.     </RelativeLayout>  
  178.   
  179. </LinearLayout>  

为了让自定义的Dialog的样式更好看,这里还需要自定义样式的Style,Style的代码如下;
[html] view plain copy
  1. <style name="CustomerDateDialog" parent="@android:Theme.Dialog">  
  2.         <item name="android:windowFrame">@null</item>  
  3.         <item name="android:windowNoTitle">true</item>  
  4.         <item name="android:windowBackground">@color/light_grey</item>  
  5.         <item name="android:windowIsFloating">true</item>  
  6.         <item name="android:windowContentOverlay">@null</item>  
  7.     </style>  

到这里基本上就完了。你看懂了吗?好好研究吧!


你可能感兴趣的:(Android学习)