模仿小米计时器
(第一次写博客,有不当之处请见谅,大家如果有什么好的意见,我也会欣然接受的O(∩_∩)O。)
话不多说,我先上一个效果图
(界面有点粗糙哈!)
- 下面咱们直接看代码
- `package com.example.a14409.cookbook.view;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.media.MediaPlayer;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import com.example.a14409.cookbook.constent.Constents;
import com.example.a14409.cookbook.presenter.Interface.ShakeInvoke;
import com.example.a14409.cookbook.service.Clockservice;
import com.example.a14409.cookbook.utils.Utils;
import java.util.Calendar;
/**
* 计时器
*/
public class ClockView extends View {
private Paint circlePaint;//圆盘画笔
private Paint centurePaint;//圆心画笔
private Paint numPaint;//数字画笔
private Paint hourPaint;//时针画笔
private Paint minutePaint;//分针画笔
private Paint secondPaint;//秒针画笔
private Paint ArcPaint;//外圈刻度画笔
private Paint changePaint; //渐变画笔
private float width;//此时钟控件的默认宽度
private float height;//此时钟控件的默认高度
private Calendar calendar; //时间对象
private Path path; //画三角形
private static float schedules = 0;//进度显示格数
private static float second = 0;//秒针的旋转速度
private static int time = 0;//显示的秒数
private static int minute = 0;//显示的分钟数
private static int hour = 0;//显示的小时数
private int seconds;//获取的秒数
private boolean start_stop = false;//开始
private boolean startservice;//开始
private static float ratio = 0;
private static float sss = 0;
private static int sum = 0;
public static float hand = 0;
private float bl;//屏幕比例
private boolean origin = true;//原点
private boolean end;//结束
private Canvas canvas;
private MediaPlayer mediaPlayer;
private static String hours, minutes, times;//时间
private static float TIMES;
private ShakeInvoke invoke;
/**
* 开启线程,是程序退出或者黑屏保存数据不停止
* */
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 0:
if (start_stop) {//每0.1秒更新一次
if (seconds >= 1) {
TIMES -= 0.1;
timeDate();
if (sum < 60 && seconds < 60) {
hand -= (float) 36 / 60;
schedules = hand/3*5;
} else {
hand += (float) 36 / 60;
schedules = hand/3*5;
if (hand >= 360) {
hand = 0;
}
}
if (TIMES < 0.1) {
//结束播放铃声
mediaPlayer.start();
if(!Constents.ISSHAKE){
invoke.Shake();
}
}
}
}
break;
}
}
};
/**
* 时间变化
*/
private void timeDate() {
if (sum <= 60) {
second = (float) (second + 0.1);
time = seconds - (int) (second);
Log.e("TAG", "seconds: "+time );
} else {
second = (float) (second + 0.1);
time = seconds - (int) (second);
}
if (schedules > 600) {
schedules = 0;
origin = !origin;
}
if (hour >= 10) {
hours = "" + hour;
} else if (hour >= 1 && hour < 10) {
hours = "0" + hour;
} else if (hour < 1) {
hours = "00";
}
if (minute >= 10) {
minutes = "" + minute;
} else if (minute >= 1 && minute < 10) {
minutes = "0" + minute;
} else if (minute < 1) {
minutes = "00";
}
if (time >= 10) {
times = "" + time;
} else if (time >= 1 && time < 10) {
times = "0" + time;
} else if (time < 1) {
times = "00";
if (minute < 1 && hour > 1) {
hour--;
if (hour >= 10) {
hours = "" + hour;
} else if (hour >= 1 && hour < 10) {
hours = "0" + hour;
} else if (hour < 1) {
hours = "00";
}
minute = 59;
minutes = "" + minute;
time = 60;
times = "" + time;
} else if (minute >= 1 && hour < 1) {
minute--;
if (minute >= 10) {
minutes = "" + minute;
} else if (minute >= 1 && minute < 10) {
minutes = "0" + minute;
} else if (minute < 1) {
minutes = "00";
}
time = 60;
times = "" + time;
second = (float) 0.0;
seconds = 60;
} else if (minute >= 1 && hour >= 1) {
minute--;
if (minute >= 10) {
minutes = "" + minute;
} else if (minute >= 1 && minute < 10) {
minutes = "0" + minute;
} else if (minute < 1) {
minutes = "00";
}
seconds = 60;
second = (float) 0.0;
time = seconds;
times = "" + seconds;
} else if (minute < 1 && hour >= 1) {
hour--;
if (hour >= 10) {
hours = "" + hour;
} else if (hour >= 1 && hour < 10) {
hours = "0" + hour;
} else if (hour < 1) {
hours = "00";
}
minute = 59;
minutes = "" + 59;
seconds = 60;
second = (float) 0.0;
time = seconds;
times = "" + seconds;
}
}
// Log.e(“TAG”, hours + “:” + minutes + “:” + times);
}
public void MyMediaPlayer(MediaPlayer mediaPlayer) {
this.mediaPlayer = mediaPlayer;
}
public ClockView(Context context) {
this(context, null);
}
public ClockView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ClockView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
bl = Utils.Screen(context);
}
/**
* 回调
* */
public void ShakeInvoke(ShakeInvoke invoke){
this.invoke = invoke;
}
//此方法用作初始化变量
private void initView() {
//初始化各种画笔
circlePaint = new Paint();
centurePaint = new Paint();
ArcPaint = new Paint();
numPaint = new Paint();
hourPaint = new Paint();
minutePaint = new Paint();
secondPaint = new Paint();
changePaint = new Paint();
path = new Path();
//自己定义的长度宽度,方法作用是把参数2的276转换成dp单位,即276dp
width = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 276, getResources().getDisplayMetrics());
height = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 276, getResources().getDisplayMetrics());
//圆盘画笔设置
circlePaint.setAntiAlias(true);//消除锯齿
circlePaint.setColor(Color.WHITE);//设置圆盘画笔的颜色为红色
circlePaint.setStyle(Paint.Style.STROKE);//设置画笔的类型为描边
circlePaint.setStrokeWidth(1);//设置描边宽度
circlePaint.setAlpha(100);//设置画笔透明度,最高值为255
//外圈画笔设置
ArcPaint.setAntiAlias(true);
ArcPaint.setColor(Color.WHITE);
ArcPaint.setStyle(Paint.Style.STROKE);
ArcPaint.setStrokeWidth(1);
//圆心画笔设置
centurePaint.setStyle(Paint.Style.STROKE);//设置画笔的类型为铺满
centurePaint.setColor(Color.WHITE);//设置画笔的颜色为红色
centurePaint.setAntiAlias(true);//设置圆心画笔为无锯齿
centurePaint.setStrokeWidth(5);
//数字画笔设置
numPaint.setAntiAlias(true);
numPaint.setColor(Color.WHITE);
numPaint.setStrokeWidth(1);
numPaint.setTextSize(20);
//时钟画笔设置
hourPaint.setColor(Color.WHITE);
hourPaint.setAntiAlias(true);
hourPaint.setStrokeWidth(6);
hourPaint.setAlpha(100);
//分钟画笔设置
minutePaint.setColor(Color.WHITE);
minutePaint.setAntiAlias(true);
minutePaint.setStrokeWidth(3);
//秒钟画笔设置
secondPaint.setColor(Color.WHITE);
secondPaint.setAntiAlias(true);
//渐变画笔设置
changePaint.setColor(Color.WHITE);
secondPaint.setAntiAlias(true);
}
@Override
protected void onDraw(Canvas canvas) {
this.canvas = canvas;
super.onDraw(canvas);
ratio = (float) seconds / 36;
//首先获取当前时间
calendar = Calendar.getInstance();
//开始画圆盘
float radius = width / 2 - 20;//圆盘的半径
//小于一分钟的话用另外一种展示的格式
if (sum < 60 && seconds < 60) {
sss = sss - ((float) (seconds * 6) / (seconds * 10));
for (float i = 0; i < hand; i = i + ((float) (seconds * 6) / (seconds * 10))) {
circlePaint.setAlpha(255);//设置画笔透明度,最高值为255
//画刻度之前,先把画布的状态保存下来
canvas.save();
//让画布旋转3/5度,参数一是需要旋转的度数,参数2,3是旋转的圆心
canvas.rotate(i, getWidth() / 2, getHeight() / 2);
//旋转后再圆上画上一长10dp的刻度线
canvas.drawLine(width / 2 - 30 / bl, height / 2 + 20 / bl - radius, width / 2 - 30 / bl, height / 2 + 45 / bl - radius, circlePaint);
//恢复画布
canvas.restore();
}
} else {
//启动之后进度随着时间变化
for (float i = 0; i < 600; i++) {
if (i < schedules) {
if (origin) {
circlePaint.setAlpha(255);//设置画笔透明度,最高值为255
} else {
circlePaint.setAlpha(0);//设置画笔透明度,最高值为255
}
} else {
if (origin) {
circlePaint.setAlpha(0);//设置画笔透明度,最高值为255
} else {
circlePaint.setAlpha(255);//设置画笔透明度,最高值为255
}
}
//画刻度之前,先把画布的状态保存下来
canvas.save();
//让画布旋转3/5度,参数一是需要旋转的度数,参数2,3是旋转的圆心
canvas.rotate(i * 36 / 60, getWidth() / 2, getHeight() / 2);
//旋转后再圆上画上一长10dp的刻度线
canvas.drawLine(width / 2 - 30 / bl, height / 2 + 20 / bl - radius, width / 2 - 30 / bl, height / 2 + 45 / bl - radius, circlePaint);
//恢复画布
canvas.restore();
}
}
//原生透明圈
for (int i = 0; i < 360; i++) {
circlePaint.setAlpha(100);//设置画笔透明度,最高值为255
//画刻度之前,先把画布的状态保存下来
canvas.save();
//让画布旋转3/5度,参数一是需要旋转的度数,参数2,3是旋转的圆心
canvas.rotate(i, getWidth() / 2, getHeight() / 2);
//旋转后再圆上画上一长10dp的刻度线
canvas.drawLine(width / 2 - 30 / bl, height / 2 + 20 / bl - radius, width / 2 - 30 / bl, height / 2 + 45 / bl - radius, circlePaint);
//恢复画布
canvas.restore();
}
//画外围四分圈
//画圆弧对象,参数1234分别代表,起始x值,起始y值,终点x值,终点y值
RectF oval = new RectF(5 / bl, 5 / bl, getWidth() - 5 / bl, getHeight() - 5 / bl);
//利用画布进行画弧,参数1是RectF对象,参数2是起始点,参数3是要画的度数(多大),4画笔对象
canvas.drawArc(oval, -88, 90, false, ArcPaint);
canvas.drawArc(oval, 2, 90, false, ArcPaint);
canvas.drawArc(oval, 92, 90, false, ArcPaint);
canvas.drawArc(oval, 182, 90, false, ArcPaint);
Paint paint = new Paint();
paint.setTextSize((float) 90 / bl);//设置字体大小
paint.setColor(Color.WHITE);
String hour_minute_time = hours + ":" + minutes + ":" + times;
canvas.drawText(hour_minute_time, getWidth() / 29 * 8, getHeight() / 2 + 35 / bl, paint);//使用画笔paint
Log.e("TAG", "onDraw: hand"+schedules );
canvas.save();
canvas.rotate((schedules * 36 / 60)+2, getWidth() / 2, getHeight() / 2);
//Path是画自定义图形的对象,在构造方法中实例化
path.moveTo(getWidth() / 2, getHeight() / 2 + 95 / bl - radius);//三角形的顶点
path.lineTo(getWidth() / 2 - 10 / bl, getHeight() / 2 + 110 / bl - radius);//底边左端点
path.lineTo(getWidth() / 2 + 10 / bl, getHeight() / 2 + 110 / bl - radius);//底边右端点
path.close();//让三个点形成封闭的图形
canvas.drawPath(path, secondPaint);//把形成的图形化在画布上
if (time < 1 && minute < 1 && hour < 1) {
start_stop = false;
}
canvas.restore();
if (start_stop) {
if (seconds >= 1) {
postInvalidateDelayed(100);//每0.1秒更新一次
}
}
}
//初始化
public void setImport(int seconds) {
this.seconds = seconds;
this.sum = seconds;
this.TIMES = (float)seconds;
//计算时间
sss = seconds * 6;
if (seconds > 3600) {
hour = seconds / 3600;
minute = seconds % 3600 / 60;
this.seconds = seconds % 3600 % 60;
time = seconds % 3600 % 60;
} else if (seconds >= 60) {
hand = 0;
hour = 0;
minute = seconds / 60;
this.seconds = seconds % 60;
} else if (seconds < 60) {
hand = (float) 6 * sum;
schedules = hand/3*5;
hour = 0;
minute = 0;
second = 0;
this.seconds = seconds;
}
timeDate();
}
//启动
public void Start(boolean start, Context content) {
this.start_stop = start;
postInvalidateDelayed(0);//每0.1秒更新一次
if (!startservice) {
//启动服务
Clockservice clockservice = new Clockservice(content, handler);
Intent startIntent = new Intent(content, Clockservice.class);
content.startService(startIntent);
startservice = true;
}
}
//暂停
public void Stop(boolean stop) {
this.start_stop = stop;
postInvalidateDelayed(0);//每0.1秒更新一次
}
public void End(boolean end) {
this.end = end;
}
}`
(—–这个是计时器的核心布局view,具体的代码功能麻烦看一下注释,这边就不详细讲解了—–)
- 布局代码
`
- * 为了让计时器时刻工作,我们就需要给它开启一个服务,代码如下:*
package com.example.a14409.cookbook.service;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
/**
* 计时器service
*/
public class Clockservice extends Service {
private Context context;
private Handler handler;
public Clockservice(){
}
public Clockservice(Context context, final Handler handler){
this.context = context;
this.handler = handler;
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i<1000000;i++){
try {
Thread.sleep(100);
handler.sendEmptyMessage(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("TAG", "onStartCommand() executed");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("TAG", "onDestroy() executed");
}
}
- 音乐播放和屏幕常亮的方法如下:
/**
* 播放音乐
* */
public static MediaPlayer isPlayOrPause(Context context,String musicpath) {
MediaPlayer mediaPlayer = null;
// final ImageButton imageButton = (ImageButton) view;
if (mediaPlayer == null) {
//播放内存卡中音频文件
mediaPlayer = new MediaPlayer();
//设置类型
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
//设置音源
try {
// mediaPlayer.setDataSource(context, Uri.parse(musicpath));
File file = new File(musicpath);
FileInputStream fis = new FileInputStream(file);
mediaPlayer.setDataSource(fis.getFD());
//准备一下(内存卡)
mediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
// mediaPlayer.start();
//把图标修改为暂停的图标
// imageButton.setImageResource(android.R.drawable.ic_media_pause);
//获取音乐的总时长
int duration = mediaPlayer.getDuration();
//设置进度条的最大值为音乐的总时长
// seekBar.setMax(duration);
// new MyThread().start();
} else if (mediaPlayer.isPlaying()) {
// mediaPlayer.pause();
//把图标修改为播放的图标
// imageButton.setImageResource(android.R.drawable.ic_media_play);
} else {
// mediaPlayer.start();
//把图标修改为暂停的图标
// imageButton.setImageResource(android.R.drawable.ic_media_pause);
}
return mediaPlayer;
}
/**
* 屏幕常亮
* */
public static PowerManager.WakeLock ScreenBrigth(Context context){
PowerManager powerManager = (PowerManager) context
.getSystemService(Context.POWER_SERVICE);
return powerManager.newWakeLock(
PowerManager.FULL_WAKE_LOCK, "My Lock");
}
- -
- 查找手机歌单代码如下:
// 查找sdcard卡上的所有歌曲信息
public static List
// 取得音乐的名字
musicColumnIndex = musicCursor
.getColumnIndex(MediaStore.Audio.AudioColumns.TITLE);
musicName = musicCursor.getString(musicColumnIndex);
musicDataMap.put("musicName", musicName);
// 取得音乐的专辑名称
musicColumnIndex = musicCursor
.getColumnIndex(MediaStore.Audio.AudioColumns.ALBUM);
musicAlbum = musicCursor.getString(musicColumnIndex);
musicDataMap.put("musicAlbum", musicAlbum);
// 取得音乐的演唱者
musicColumnIndex = musicCursor
.getColumnIndex(MediaStore.Audio.AudioColumns.ARTIST);
musicArtist = musicCursor.getString(musicColumnIndex);
musicDataMap.put("musicArtist", musicArtist);
// 取得歌曲对应的专辑对应的Key
musicColumnIndex = musicCursor
.getColumnIndex(MediaStore.Audio.AudioColumns.ALBUM_KEY);
musicAlbumKey = musicCursor.getString(musicColumnIndex);
String[] argArr = {musicAlbumKey};
ContentResolver albumResolver = context.getContentResolver();
Cursor albumCursor = albumResolver.query(
MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, null,
MediaStore.Audio.AudioColumns.ALBUM_KEY + " = ?",
argArr, null);
if (null != albumCursor && albumCursor.getCount() > 0) {
albumCursor.moveToFirst();
int albumArtIndex = albumCursor
.getColumnIndex(MediaStore.Audio.AlbumColumns.ALBUM_ART);
musicAlbumArtPath = albumCursor.getString(albumArtIndex);
if (null != musicAlbumArtPath
&& !"".equals(musicAlbumArtPath)) {
musicDataMap.put("musicAlbumImage", musicAlbumArtPath);
} else {
musicDataMap.put("musicAlbumImage",
"file:///mnt/sdcard/alb.jpg");
}
} else {
// 没有专辑定义,给默认图片
musicDataMap.put(“musicAlbumImage”,
“file:///mnt/sdcard/alb.jpg”);
}
musicList.add(musicDataMap);
}
}
return musicList;
}