模仿小米计时器

模仿小米计时器

(第一次写博客,有不当之处请见谅,大家如果有什么好的意见,我也会欣然接受的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 getMultiData(Context context) {
String musicPath = null;
String musicName = null;
String musicAlbum = null;
String musicArtist = null;
String musicAlbumKey = null;
String musicAlbumArtPath = null;
ArrayList
musicList = new ArrayList();
// 加入封装音乐信息的代码
// 查询所有歌曲
ContentResolver musicResolver = context.getContentResolver();
Cursor musicCursor = musicResolver.query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null,
null);
int musicColumnIndex;
if (null != musicCursor && musicCursor.getCount() > 0) {
for (musicCursor.moveToFirst(); !musicCursor.isAfterLast(); musicCursor
.moveToNext()) {
Map musicDataMap = new HashMap();
Random random = new Random();
int musicRating = Math.abs(random.nextInt()) % 10;
musicDataMap.put(“musicRating”, musicRating);
// 取得音乐播放路径
musicColumnIndex = musicCursor
.getColumnIndex(MediaStore.Audio.AudioColumns.DATA);
musicPath = musicCursor.getString(musicColumnIndex);
musicDataMap.put(“musicPath”, musicPath);

            // 取得音乐的名字
            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;
}

(到这里计时器的功能就差不多了,只需要细细修改界面就好了,如有bug,希望大家指出!)


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值