Android自定义View 实现闹钟唤起播放闹钟铃声功能_Android

先上图看一下闹钟唤期页面的效果

实现的功能:

1:转动的图片根据天气情况更换

2:转动时间可以设置,转动结束,闹铃声音就结束

3:光圈颜色渐变效果

直接上代码啦:

package com.yuekong.sirius.extension.customview;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.SweepGradient;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.animation.LinearInterpolator;
import com.yuekong.sirius.extension.R;
import com.yuekong.sirius.extension.util.ExtendUtil;
import java.text.SimpleDateFormat;
/**
* Created by Zhongqi.Shao on 2016/12/5.
*/
public class ClockWakeView extends View {
//最外一层圆的颜色
private int mOutCircleColor;
//最外一层圆的半径
private int mOutCircleRadis;
//内圆的颜色
private int mInnerCircleColor;
//内圆的半径
private int mInnerCircleRadis;
private int mWidth;
private int mHeight;
//默认宽度
private final int DEFAULT_WIDTH = dp2px(240);
//默认高度
private final int DEFAULT_HEIGHT = dp2px(240);
//最外圆的默认半径
private int DEFAULT_OUT_RADIS = dp2px(120);
//内圆的默认半径
private int DeFAULT_INNER_RADIS = dp2px(105);
//标题距离顶部的默认距离
private int DEFAULT_TITLE_PADDING_TOP = dp2px(40);
//最外层圆形的Paint
private Paint mOutCirclePaint;
//内圆的Paint
private Paint mInnerCirclePaint;
//标题Paint
private Paint mTitlePaint;
//渐变弧
private Paint mGradientArcPaint;
private SweepGradient mSweepGradient;
//日期时间Paint
private Paint mTimePaint;
private Paint mDatePaint;
//时间分隔的图片
private Bitmap mDividerPic;
//天气图片
private Bitmap mWeatherPic;
//标题
private String mTitle;
//当前时间
private long mCurrentDate = 1481010829605L;
private SimpleDateFormat mFormat;
private Ringtone mRingTone;
//图片在倒计时几分钟内走完一个周期 根据音乐时间来计算
private long mCountDownTime;
//倒计时转过的角度
private float mCurrentAngle;
//倒计时结束回调
private CountdownFinishListener mCountdownListener;
private Context mContext;
public ClockWakeView(Context context) {
this(context, null);
mContext = context;
}
public ClockWakeView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
mContext = context;
}
public ClockWakeView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SiriusClockWakeView);
mOutCircleColor = ta.getColor(R.styleable.SiriusClockWakeView_outColor, context.getResources().getColor(R.color.out_circle_color));
mOutCircleRadis = (int) ta.getDimension(R.styleable.SiriusClockWakeView_outCircleRadis, DEFAULT_OUT_RADIS);
mInnerCircleColor = context.getResources().getColor(R.color.inner_circle_color);
mInnerCircleRadis = DeFAULT_INNER_RADIS;
mTitle = context.getResources().getString(R.string.clock);
ta.recycle();
initPaint();
}
private void initPaint() {
mFormat = new SimpleDateFormat("MM月dd日_HH_mm_EEEE");
//获取分隔图片
mDividerPic = BitmapFactory.decodeResource(getResources(), R.drawable.time_divider);
mWeatherPic = BitmapFactory.decodeResource(getResources(), R.drawable.icon_weather);
//外圆的paint
mOutCirclePaint = new Paint();
mOutCirclePaint.setAntiAlias(true);
mOutCirclePaint.setStyle(Paint.Style.STROKE);
mOutCirclePaint.setStrokeWidth(dp2px(5));
mOutCirclePaint.setColor(mOutCircleColor);
//内圆的Paint
mInnerCirclePaint = new Paint();
mInnerCirclePaint.setAntiAlias(true);
mInnerCirclePaint.setStyle(Paint.Style.STROKE);
mInnerCirclePaint.setStrokeWidth(dp2px(5));
mInnerCirclePaint.setColor(mInnerCircleColor);
//标题的Paint
mTitlePaint = new Paint();
mTitlePaint.setAntiAlias(true);
mTitlePaint.setStyle(Paint.Style.FILL);
mTitlePaint.setColor(mContext.getResources().getColor(R.color.nav_highlighted));
mTitlePaint.setTextSize(sp2px(14));
//时间的Paint
mTimePaint = new Paint();
mTimePaint.setAntiAlias(true);
mTimePaint.setColor(Color.WHITE);
mTimePaint.setStyle(Paint.Style.FILL);
mTimePaint.setTextSize(sp2px(70));
//日期的Paint
mDatePaint = new Paint();
mDatePaint.setAntiAlias(true);
mDatePaint.setColor(Color.WHITE);
mDatePaint.setStyle(Paint.Style.FILL);
mDatePaint.setTextSize(sp2px(14));
//渐变弧的Paint
mGradientArcPaint = new Paint();
mGradientArcPaint.setAntiAlias(true);
mGradientArcPaint.setStyle(Paint.Style.STROKE);
mGradientArcPaint.setStrokeWidth(dp2px(5));
mGradientArcPaint.setStrokeCap(Paint.Cap.BUTT);
mGradientArcPaint.setStrokeJoin(Paint.Join.MITER);
//设置渐变的颜色
int[] colors = {0x00AEA1FF, 0x40AEA1FF, 0xFFAEA1FF, 0xFFAEA1FF};
//渐变色
mSweepGradient = new SweepGradient(0, 0, colors, null);
mGradientArcPaint.setShader(mSweepGradient);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mWidth = startMeasure(widthMeasureSpec);
mHeight = startMeasure(heightMeasureSpec);
setMeasuredDimension(mWidth, mHeight);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//移动画布到中间
canvas.translate(mWidth / 2, mHeight / 2);
//绘制最外层的圆形
drawOutCircle(canvas);
//绘制内圆
drawInnerCircle(canvas);
//绘制中间的分隔图片
drawDividerPic(canvas);
//绘制标题
drawTitle(canvas);
//绘制时间
drawDateTime(canvas);
//绘制旋转图片
drawLightArc(canvas);
}
private void drawOutCircle(Canvas canvas) {
canvas.save();
canvas.drawCircle(0, 0, mOutCircleRadis, mOutCirclePaint);
canvas.restore();
}
private void drawInnerCircle(Canvas canvas) {
canvas.save();
canvas.drawCircle(0, 0, mInnerCircleRadis, mInnerCirclePaint);
canvas.restore();
}
private void drawDividerPic(Canvas canvas) {
canvas.save();
canvas.drawBitmap(mDividerPic, null, new Rect(-dp2px(3), -dp2px(14), dp2px(3), dp2px(14)), null);
canvas.restore();
}
private void drawTitle(Canvas canvas) {
canvas.save();
if (mTitle == null || mTitle.length() <= 0) {
return;
}
float textWidth = mTitlePaint.measureText(mTitle);
float baseLine = DeFAULT_INNER_RADIS - DEFAULT_TITLE_PADDING_TOP;
canvas.drawText(mTitle, -textWidth / 2, -baseLine, mTitlePaint);
canvas.restore();
}
private void drawLightArc(Canvas canvas) {
canvas.save();
canvas.rotate(mCurrentAngle);
RectF rect = new RectF(-mInnerCircleRadis, -mInnerCircleRadis, mInnerCircleRadis, mInnerCircleRadis);
canvas.drawArc(rect, -270, 180, false, mGradientArcPaint);
canvas.drawBitmap(mWeatherPic, null, new Rect(-dp2px(12), -mInnerCircleRadis - dp2px(12), dp2px(12), dp2px(12) - mInnerCircleRadis), null);
canvas.restore();
}
private void drawDateTime(Canvas canvas) {
canvas.save();
String timeStr = ExtendUtil.getAllFormatStr(mFormat, mCurrentDate);
String[] array = timeStr.split("_");
String date = array[0];
String hour = array[1];
String minute = array[2];
String wake = array[3];
float width = mTimePaint.measureText(hour);
RectF targetRect = new RectF(-(width + dp2px(40)), -sp2px(70) / 2, -dp2px(40), sp2px(70) / 2);
Paint.FontMetricsInt fontMetrics = mTimePaint.getFontMetricsInt();
int baseline = (int) (targetRect.top + (targetRect.bottom - targetRect.top - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top);
canvas.drawText(hour, -width - dp2px(15), baseline, mTimePaint);
float minuteWidth = mTimePaint.measureText(minute);
RectF minuteRect = new RectF(dp2px(15), -sp2px(70) / 2, dp2px(15) + minuteWidth, sp2px(70) / 2);
Paint.FontMetricsInt minuteMetrics = mTimePaint.getFontMetricsInt();
int minuteLine = (int) (minuteRect.top + (minuteRect.bottom - minuteRect.top - minuteMetrics.bottom + minuteMetrics.top) / 2 - minuteMetrics.top);
canvas.drawText(minute, dp2px(15), minuteLine, mTimePaint);
String dateStr = date + " " + wake;
float dateWidth = mDatePaint.measureText(dateStr);
RectF dateRect = new RectF(-dateWidth / 2, sp2px(30), dateWidth / 2, sp2px(30) + sp2px(14));
Paint.FontMetricsInt dateMetrics = mTimePaint.getFontMetricsInt();
int dateLine = (int) (dateRect.top + (dateRect.bottom - dateRect.top - dateMetrics.bottom + dateMetrics.top) / 2 - dateMetrics.top);
canvas.drawText(dateStr, -dateWidth / 2, dateLine, mDatePaint);
canvas.restore();
}
private int startMeasure(int whSpec) {
int result = 0;
int size = MeasureSpec.getSize(whSpec);
int mode = MeasureSpec.getMode(whSpec);
if (mode == MeasureSpec.EXACTLY) {
result = size;
} else {
result = DEFAULT_WIDTH;
}
return result;
}
//开始倒计时计算闹钟结束
public void startCountDown() {
ValueAnimator animator = ValueAnimator.ofFloat(0, 1.0f);
animator.setDuration(mCountDownTime);
//匀速
animator.setInterpolator(new LinearInterpolator());
//不循环
animator.setRepeatCount(0);
//监听动画过程中值得实时变化
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
mCurrentAngle = (float) valueAnimator.getAnimatedValue() * 360;
invalidate();
}
});
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
}
@Override
public void onAnimationEnd(Animator animator) {
if (mRingTone != null && mRingTone.isPlaying()) {
mRingTone.stop();
}
if (mCountdownListener != null) {
mCountdownListener.countdownFinished();
}
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});
animator.start();
//播放闹钟铃声
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
mRingTone = RingtoneManager.getRingtone(mContext, notification);
if (mRingTone != null && !mRingTone.isPlaying()) {
mRingTone.play();
}
}
//提供设置倒计时的方法
public void setCountDownTime(long time, CountdownFinishListener listener) {
mCountDownTime = time;
mCountdownListener = listener;
}
//设置当前日期时间
public void setCurrentTime(long currentTime) {
mCurrentDate = currentTime;
invalidate();
}
private int dp2px(int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
}
private int sp2px(int sp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, getResources().getDisplayMetrics());
}
public interface CountdownFinishListener {
//倒计时结束操作
void countdownFinished();
}
}

以上所述是小编给大家介绍的Android自定义View 实现闹钟唤起播放闹钟铃声功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索android
, 自定义view
自定义闹钟
iphone自定义闹钟铃声、win10闹钟铃声自定义、ipad自定义闹钟铃声、苹果自定义闹钟铃声、ios10自定义闹钟铃声,以便于您获取更多的相关知识。

时间: 2024-10-09 21:51:04

Android自定义View 实现闹钟唤起播放闹钟铃声功能_Android的相关文章

Android自定义View之绘制音乐播放器示波器

周末玩的有点嗨,没更新博客了,今天补上,这个示波器是在大学的时候老师教的,但是出来工作一直没有用到过,渐渐的也就忘记了,现在重新学习一下.来看看效果图: 这里是一个自定义的柱状图,然后有一个按钮,点击按钮的时候,这里柱子会不停的运动,类似于音乐播放器里示波器的跳动. 跟前面几个自定义view的方式类似,重写了onSizeChange()方法和onDraw()方法  先列一下我们要用到的变量 Paint mPaint; mWidth; mRectWidth; mRectHeight; mRectC

Android自定义View之酷炫圆环(二)_Android

先看下最终的效果 静态: 动态: 一.开始实现 新建一个DoughnutProgress继承View public class DoughnutProgress extends View { } 先给出一些常量.变量以及公共方法的代码,方便理解后面的代码     private static final int DEFAULT_MIN_WIDTH = 400; //View默认最小宽度 private static final int RED = 230, GREEN = 85, BLUE =

Android 自定义View实现单击和双击事件的方法_Android

自定义View, 1. 自定义一个Runnable线程TouchEventCountThread ,  用来统计500ms内的点击次数 2. 在MyView中的 onTouchEvent 中调用 上面的线程 3. 自定义一个Handler, 在TouchEventHandler 中 处理 统计到的点击事件, 单击, 双击, 三击, 都可以处理 核心代码如下:  public class MyView extends View { ...... // 统计500ms内的点击次数 TouchEven

Android自定义View制作动态炫酷按钮实例解析_Android

普通按钮也就那么几种样式,看着都审美疲劳,先放效果图:   你会不会以为这个按钮是集结了很多动画的产物,我告诉你,并没有.所有的实现都是基于自定义View,采用最底层的onDraw一点一点的画出来的.没有采用一丁点的动画.虽然演示时间很短,但是要完成这么多变化,还是挺吃力. 首先讲解用法:  public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceStat

Android自定义View实现QQ运动积分转盘抽奖功能

因为偶尔关注QQ运动, 看到QQ运动的积分抽奖界面比较有意思,所以就尝试用自定义View实现了下,原本想通过开发者选项查看下界面的一些信息,后来发现积分抽奖界面是在WebView中展示的,应该是在H5页面中用js代码实现的,暂时不去管它了. 这里的自定义View针对的是继承自View的情况,你可以将Canvas想象为画板, Paint为画笔,自定义View的过程和在画板上用画笔作画其实类似,想象在画板上作画的过程,你要画一个多大图形(对应View的测量 onMeasure方法),你要画什么样的图

Android自定义View实现QQ音乐中圆形旋转碟子_Android

QQ音乐中圆形旋转碟子 思路分析: 1.在onMeasure中测量整个View的宽和高后,设置宽高 2.获取我们res的图片资源后,在ondraw方法中进行绘制圆形图片 3.通过Handler发送Runnable来启动旋转线程(如果只想做圆形头像的话,这步可以去掉) 4.在布局中使用我们的View 效果图: 贴出我们的变量信息: //view的宽和高 int mHeight = 0; int mWidth = 0; //圆形图片 Bitmap bitmap = null; //圆形图片的真实半径

Android自定义Chronometer实现短信验证码秒表倒计时功能_Android

本文实例为大家分享了Chronometer实现倒计时功能,Android提供了实现按照秒计时的API,供大家参考,具体内容如下 一.自定义ChronometerView 继续自TextView 主要原理:先设置一个基准倒计时时间mBaseSeconds,内置handler 每隔1s发送一个空消息,mRemainSeconds--,同时刷新界面视图,回调给外部调用者,只到为零.外部调用者可通过start()/pause()/stop()来控制计时器的工作状态. 可以app中发送短信验证码的场景为例

Android自定义view实现阻尼效果的加载动画_Android

效果: 需要知识: 1. 二次贝塞尔曲线 2. 动画知识 3. 基础自定义view知识 先来解释下什么叫阻尼运动 阻尼振动是指,由于振动系统受到摩擦和介质阻力或其他能耗而使振幅随时间逐渐衰减的振动,又称减幅振动.衰减振动.[1] 不论是弹簧振子还是单摆由于外界的摩擦和介质阻力总是存在,在振动过程中要不断克服外界阻力做功,消耗能量,振幅就会逐渐减小,经过一段时间,振动就会完全停下来.这种振幅随时间减小的振动称为阻尼振动.因为振幅与振动的能量有关,阻尼振动也就是能量不断减少的振动.阻尼振动是非简谐运

Android自定义View实现打字机效果_Android

一.先来看看效果演示 二.实现原理: 这个其实不难实现,通过一个定时器不断调用TextView的setText就行了,在setText的时候播放打字的音效. 具体代码如下: import java.util.Timer; import java.util.TimerTask; import android.content.Context; import android.media.MediaPlayer; import android.text.TextUtils; import android