Android学习笔记(一)之仿正点闹钟时间齿轮滑动的效果
看到正点闹钟上的设置时间的滑动效果非常好看,自己就想做一个那样的,在网上就开始搜资料了,看到网上有的齿轮效果的代码非常多,也非常难懂,我就决定自己研究一下,现在我就把我的研究成果分享给大家。我研究的这个效果出来了,而且代码也非常简单,通俗易懂。效果图如下:
首先是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="时间设置"
- 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也非常简单,自己可以学一下,这方面网上的资料非常多。现在我把我自定义时钟的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;
- }
- }
- /**
- * 设置分刻度盘
- *
- * @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;
- }
- 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="设置时间"
- android:textColor="@color/black"
- android:textSize="24sp" />
- <!-- 时间的相关设置 -->
- <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>
- <!-- 设置时钟的按钮 -->
- <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>
到这里基本上就完了。你看懂了吗?好好研究吧!
Android学习笔记(一)之仿正点闹钟时间齿轮滑动的效果的更多相关文章
- Android 学习笔记之Volley(七)实现Json数据加载和解析...
学习内容: 1.使用Volley实现异步加载Json数据... Volley的第二大请求就是通过发送请求异步实现Json数据信息的加载,加载Json数据有两种方式,一种是通过获取Json对象,然后 ...
- Android学习笔记进阶之在图片上涂鸦(能清屏)
Android学习笔记进阶之在图片上涂鸦(能清屏) 2013-11-19 10:52 117人阅读 评论(0) 收藏 举报 HandWritingActivity.java package xiaos ...
- android学习笔记36——使用原始XML文件
XML文件 android中使用XML文件,需要开发者手动创建res/xml文件夹. 实例如下: book.xml==> <?xml version="1.0" enc ...
- Android学习笔记之JSON数据解析
转载:Android学习笔记44:JSON数据解析 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,为Web应用开发提供了一种 ...
- udacity android 学习笔记: lesson 4 part b
udacity android 学习笔记: lesson 4 part b 作者:干货店打杂的 /titer1 /Archimedes 出处:https://code.csdn.net/titer1 ...
- Android学习笔记36:使用SQLite方式存储数据
在Android中一共提供了5种数据存储方式,分别为: (1)Files:通过FileInputStream和FileOutputStream对文件进行操作.具体使用方法可以参阅博文<Andro ...
- Android学习笔记之Activity详解
1 理解Activity Activity就是一个包含应用程序界面的窗口,是Android四大组件之一.一个应用程序可以包含零个或多个Activity.一个Activity的生命周期是指从屏幕上显示那 ...
- Pro Android学习笔记 ActionBar(1):Home图标区
Pro Android学习笔记(四八):ActionBar(1):Home图标区 2013年03月10日 ⁄ 综合 ⁄ 共 3256字 ⁄ 字号 小 中 大 ⁄ 评论关闭 ActionBar在A ...
- 【转】Pro Android学习笔记(九八):BroadcastReceiver(2):接收器触发通知
文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.sina.com.cn/flowingflying或作者@恺风Wei-傻瓜与非傻瓜 广播接 ...
随机推荐
- 笨办法学Python(十四)
习题 14:提示和传递 让我们使用 argv 和 raw_input 一起来向用户提一些特别的问题.下一节习题你会学习如何读写文件,这节练习是下节的基础.在这道习题里我们将用略微不同的方法使用 raw ...
- POJ-2456 Aggressive cows---最大化最小值(也就是求最大值)
题目链接: https://vjudge.net/problem/POJ-2456 题目大意: 有n个牛栏,选m个放进牛,相当于一条线段上有 n 个点,选取 m 个点, 使得相邻点之间的最小距离值最大 ...
- vue中动画的封装
<style> .v-enter,.v-leave-to{ opacity: 0; } .v-enter-active,.v-leave-active{ transition:opacit ...
- 【转】Android UI开发第三十一篇——Android的Holo Theme
好长时间没写Android UI方面的文章了,今天就闲扯一下Android的Holo主题.一直做android开发的可能都知道,Android 系统的UI有过两次大的变化,一次是android 3.0 ...
- P1424 小鱼的航程(改进版)
题目背景 原来的题目太简单,现改进让小鱼周末也休息,请已经做过重做该题. 题目描述 有一只小鱼,它上午游泳150公里,下午游泳100公里,晚上和周末都休息(实行双休日),假设从周x(1<=x&l ...
- android build.prop详解
# begin build properties开始设置系统性能 # autogenerated by buildinfo.sh{通过设置形成系统信息} ro.build.id=MIUI(版本ID) ...
- IE问题——列表项图像
等我们实现列表时,经常会遇到一种情况:需要为列表的每一项的前面添加一个列表项图像. 我们在查阅W3C时会发现,在CSS中已经为我们提供了实现方法——“list-style-type”,我们来看看它的实 ...
- Oracle字符编码与汉字存储长度的处理
执行如下语句,查看汉字在数据库中所占的字节: select vsize('汉') from dual; 一般情况下,得到的结果大部分为值:2 或 3 一般linux下安装oracle数据库,默认字符编 ...
- Kettle报表自动化
来自我们牛逼哄哄的东哥的笔记 1. 2. 3. 选择数据库链接 贴报表SQL 4. 文件名:选择路径,excel文件由kettle自动创建,自己只需输入创建文件的名称. 拓展名:后缀写上 5. 此 ...
- orale 10g和11g中的自动统计任务
orale 10g和11g中的自动统计任务 博客分类: 数据库相关/oracle 1) 先来看下oracle 10g中的自动统计任务的问题. 从Oracle Database 10g开始,Or ...