Android仿正點鬧鐘時間齒輪滑動效果
看到正點鬧鐘上的設(shè)置時間的滑動效果非常好看,自己就想做一個那樣的,在網(wǎng)上就開始搜資料了,看到網(wǎng)上有的齒輪效果的代碼非常多,也非常難懂,我就決定自己研究一下,現(xiàn)在我就把我的研究成果分享給大家。我研究的這個效果出來了,而且代碼也非常簡單,通俗易懂。效果圖如下:
首先是MainActivity的布局文件,這個布局文件非常簡單,就是一個Button:activity_main.xml文件,代碼如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/ll_timeset" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#ffffff" android:orientation="vertical" > <Button android:id="@+id/btn" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" android:text="時間設(shè)置" android:textSize="24sp" /> </LinearLayout>
緊接著就是MainActivity的代碼,代碼如下:
package net.loonggg.test; import net.loonggg.view.CustomerDateDialog; import net.loonggg.view.CustomerDateDialog.DateDialogListener; import android.app.Activity; import android.os.Bundle; import android.text.format.DateFormat; import android.view.View; import android.view.Window; import android.widget.Button; import android.widget.Toast; public class MainActivity extends Activity { private int h, m; private CustomerDateDialog dialog; private Button btn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); btn = (Button) findViewById(R.id.btn); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String datetime = DateFormat.format("kk:mm", System.currentTimeMillis()).toString(); String[] strs = datetime.split(":"); h = Integer.parseInt(strs[0]); m = Integer.parseInt(strs[1]); dialog = new CustomerDateDialog(MainActivity.this, h, m); dialog.show(); dialog.setOnDateDialogListener(new DateDialogListener() { @Override public void getDate() { Toast.makeText( MainActivity.this, "時間是:" + dialog.getSettingHour() + "點" + dialog.getSettingMinute() + "分", Toast.LENGTH_LONG).show(); } }); } }); } }
再就是我自定義了一個時鐘的Dialog,自定義Dialog也非常簡單,自己可以學一下,這方面網(wǎng)上的資料非常多。現(xiàn)在我把我自定義時鐘的Dialog的代碼分享一下,代碼如下:
package net.loonggg.view; import net.loonggg.test.R; import android.annotation.SuppressLint; import android.app.Dialog; import android.content.Context; import android.os.Bundle; import android.os.Handler; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.widget.Button; import android.widget.LinearLayout; import android.widget.ScrollView; import android.widget.TextView; @SuppressLint("HandlerLeak") public class CustomerDateDialog extends Dialog { private View customView; private Button setBtn; private Button cancleBtn; private TextView arrow_up; private TextView tv01, tv02; private ScrollView sv01, sv02; private LinearLayout llTimeWheel; private DateDialogListener listener; private int lastY; private int flag;// 標記時分 private int itemHeight;// 每一行的高度 private int pHour, pMinute;// 初始化時顯示的時分時間 private int setHour, setMinute; public CustomerDateDialog(Context context, int hour, int minute) { super(context, R.style.CustomerDateDialog); customView = LayoutInflater.from(context).inflate(R.layout.time_wheel, null); init(context, hour, minute); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(customView); } private void init(Context context, final int hour, final int minute) { tv01 = (TextView) customView.findViewById(R.id.tv01); tv02 = (TextView) customView.findViewById(R.id.tv02); sv01 = (ScrollView) customView.findViewById(R.id.sv01); sv02 = (ScrollView) customView.findViewById(R.id.sv02); setBtn = (Button) customView.findViewById(R.id.setBtn); cancleBtn = (Button) customView.findViewById(R.id.cancleBtn); arrow_up = (TextView) customView.findViewById(R.id.arrow_up); this.pHour = hour; this.pMinute = minute; setHour = pHour; setMinute = pMinute; llTimeWheel = (LinearLayout) customView .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() { @SuppressWarnings("deprecation") public void onGlobalLayout() { int tvHeight = tv02.getHeight(); itemHeight = tvHeight / 180; if (sv01.getViewTreeObserver().isAlive()) { sv01.getViewTreeObserver().removeGlobalOnLayoutListener( this); } LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.FILL_PARENT, (itemHeight * 3) + arrow_up.getHeight() * 2); llTimeWheel.setLayoutParams(params); sv01.setLayoutParams(new LinearLayout.LayoutParams(tv02 .getWidth(), (itemHeight * 3))); sv02.setLayoutParams(new LinearLayout.LayoutParams(tv02 .getWidth(), (itemHeight * 3))); sv01.scrollTo(0, (pHour + 23) * itemHeight); sv02.scrollTo(0, (pMinute + 59) * itemHeight); } }); setBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { getSettingDate(); CustomerDateDialog.this.cancel(); } }); cancleBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { CustomerDateDialog.this.cancel(); } }); } private OnTouchListener tListener = new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { if (v == sv01) { flag = 1; } else { flag = 2; } if (event.getAction() == MotionEvent.ACTION_UP) { final ScrollView sv = (ScrollView) v; lastY = sv.getScrollY(); System.out.println("lastY" + lastY); handler.sendMessageDelayed(handler.obtainMessage(0, v), 50); } return false; } }; private Handler handler = new Handler() { @SuppressLint("HandlerLeak") public void handleMessage(android.os.Message msg) { ScrollView sv = (ScrollView) msg.obj; if (msg.what == 0) { if (lastY == sv.getScrollY()) { int num = lastY / itemHeight; int over = lastY % itemHeight; 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) { switch (flag) { case 1: int mPosition = 0; if (position <= 23 * itemHeight) { mPosition = position + 24 * itemHeight; scrollview.scrollTo(0, mPosition); } else if (position >= 48 * itemHeight) { mPosition = position - 24 * itemHeight; scrollview.scrollTo(0, mPosition); } else { mPosition = position; scrollview.smoothScrollTo(0, position); } setHour = (mPosition / itemHeight - 23) % 24; break; case 2: int hPosition = 0; if (position <= 57 * itemHeight) { hPosition = position + 60 * itemHeight; scrollview.scrollTo(0, hPosition); } else if (position >= 120 * itemHeight) { hPosition = position - 60 * itemHeight; scrollview.scrollTo(0, hPosition); } else { hPosition = position; scrollview.smoothScrollTo(0, position); } setMinute = (hPosition / itemHeight) % 60 + 1; break; } } /** * 設(shè)置分刻度盤 * * @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); } /** * 設(shè)置時刻度盤 * * @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; } public void setOnDateDialogListener(DateDialogListener listener) { this.listener = listener; } public interface DateDialogListener { void getDate(); } public void getSettingDate() { if (listener != null) { listener.getDate(); } } public int getSettingHour() { return setHour; } public int getSettingMinute() { return setMinute; } }
這里光有java代碼還不夠,還有自定義Dialog的布局文件,time_wheel.xml代碼如下:
<?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="wrap_content" android:background="#efefef" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@color/light_black" android:paddingLeft="10dp" android:text="設(shè)置時間" android:textColor="@color/black" android:textSize="24sp" /> <!-- 時間的相關(guān)設(shè)置 --> <LinearLayout android:id="@+id/ll_time_wheel" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="15dp" android:background="#f0f0f0" android:gravity="center_horizontal" android:orientation="horizontal" > <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" > <TextView android:layout_width="30dp" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:background="@drawable/wheel_arrow_up" /> <ScrollView android:id="@+id/sv01" android:layout_width="50dp" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:background="@drawable/time_bg" android:scrollbars="none" > <LinearLayout android:id="@+id/ll01" android:layout_width="50dp" android:layout_height="wrap_content" android:gravity="center" android:orientation="horizontal" android:paddingTop="5dp" > <TextView android:id="@+id/tv01" android:layout_width="50dp" android:layout_height="wrap_content" android:gravity="center" android:lineSpacingExtra="20dp" android:paddingLeft="10dp" android:paddingRight="10dp" android:textSize="26sp" /> </LinearLayout> </ScrollView> <TextView android:layout_width="30dp" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:background="@drawable/wheel_arrow_down" /> </LinearLayout> <TextView android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_gravity="center" android:background="#f0f0f0" android:gravity="center" android:text="時" android:textColor="#000000" android:textSize="25sp" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" > <TextView android:id="@+id/arrow_up" android:layout_width="30dp" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:background="@drawable/wheel_arrow_up" /> <ScrollView android:id="@+id/sv02" android:layout_width="50dp" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:background="@drawable/time_bg" android:scrollbars="none" > <LinearLayout android:id="@+id/ll02" android:layout_width="50dp" android:layout_height="wrap_content" android:gravity="center" android:paddingTop="5dp" > <TextView android:id="@+id/tv02" android:layout_width="50dp" android:layout_height="wrap_content" android:gravity="center" android:lineSpacingExtra="20dp" android:paddingLeft="10dp" android:paddingRight="10dp" android:textSize="26sp" /> </LinearLayout> </ScrollView> <TextView android:id="@+id/arrow_down" android:layout_width="30dp" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:background="@drawable/wheel_arrow_down" /> </LinearLayout> <TextView android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_gravity="center" android:background="#f0f0f0" android:gravity="center" android:text="分" android:textColor="#000000" android:textSize="25sp" /> </LinearLayout> <!-- 設(shè)置時鐘的按鈕 --> <RelativeLayout android:layout_width="fill_parent" android:layout_height="50dp" > <Button android:id="@+id/setBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_gravity="center_horizontal" android:layout_marginLeft="25dp" android:background="@drawable/btn_clock_normal" android:gravity="center" android:paddingLeft="10dp" android:paddingRight="10dp" android:text="確定" android:textColor="#000000" android:textSize="24sp" /> <Button android:id="@+id/cancleBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_gravity="center_horizontal" android:layout_marginRight="25dp" android:background="@drawable/btn_clock_normal" android:gravity="center" android:paddingLeft="10dp" android:paddingRight="10dp" android:text="取消" android:textColor="#000000" android:textSize="24sp" /> </RelativeLayout> </LinearLayout>
為了讓自定義的Dialog的樣式更好看,這里還需要自定義樣式的Style,Style的代碼如下;
<style name="CustomerDateDialog" parent="@android:Theme.Dialog"> <item name="android:windowFrame">@null</item> <item name="android:windowNoTitle">true</item> <item name="android:windowBackground">@color/light_grey</item> <item name="android:windowIsFloating">true</item> <item name="android:windowContentOverlay">@null</item> </style>
到這里基本上就完了。你看懂了嗎?好好研究吧!
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android EditText實現(xiàn)輸入金額類型詳解
EditText是Android中一個非常實用的控件,有很多InputType,可以來達到不同的輸入效果,下面這篇文章主要給大家介紹了關(guān)于Android EditText實現(xiàn)輸入金額類型的相關(guān)資料,需要的朋友可以參考借鑒,下面來一起看看吧。2017-09-09解析Android開發(fā)優(yōu)化之:軟引用與弱引用的應用
Java從JDK1.2版本開始,就把對象的引用分為四種級別,從而使程序能更加靈活的控制對象的生命周期。這四種級別由高到低依次為:強引用、軟引用、弱引用和虛引用,本篇文章重點介紹一下軟引用和弱引用2013-05-05Material Design系列之Behavior實現(xiàn)支付密碼彈窗和商品屬性選擇效果
這篇文章主要為大家詳細介紹了Material Design系列之Behavior實現(xiàn)支付密碼彈窗和商品屬性選擇效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-09-09Android?MaterialButton使用實例詳解(告別shape、selector)
我們平時寫布局,當遇到按鈕需要圓角、或者描邊等,通常的方法是新建一個xml文件,在shape標簽下寫,然后通過android:background或setBackground(drawable)設(shè)置,這篇文章主要給大家介紹了關(guān)于Android?MaterialButton使用詳解的相關(guān)資料,需要的朋友可以參考下2022-09-09Android編程實現(xiàn)泡泡聊天界面實例詳解(附源碼)
這篇文章主要介紹了Android編程實現(xiàn)泡泡聊天界面,結(jié)合實例形式較為詳細的分析了Android泡泡聊天界面的窗體定義與功能實現(xiàn)技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-11-11android使用TextView實現(xiàn)跑馬燈效果
這篇文章主要為大家詳細介紹了android使用TextView實現(xiàn)跑馬燈效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-05-05Android入門之在Activity之間穿梭的Intent
Intent可以用來啟動Activity(startActivity(Intent))、Serveice(startService(Intent))等組件,可以用來綁定Activity和Service以建立它們之間的通信(bindServiceConnaction(Intent,ServiceConnection,int)),可以作為Broadcast Intent發(fā)送給廣播接收器2021-10-10android?studio組件通信:Intend啟動Activity接收返回結(jié)果
這篇文章主要介紹了android?studio組件通信:Intend啟動Activity接收返回結(jié)果,設(shè)計一個主Activity和一個子Activity(Sub-Activity),使用主Activity上的按鈕啟動子Activity,并將子Activity的一些信息返回給主Activity,并顯示在主Activity上,需要的朋友可以參考一下2021-12-12