Android仿小米時鐘效果
我在一個[博客] android高仿小米時鐘(使用Camera和Matrix實(shí)現(xiàn)3D效果)上面看到了小米時鐘實(shí)現(xiàn).特別感興趣.就認(rèn)真的看了一遍.并自己敲了一遍.下面說下我自己的理解和我的一些改進(jìn)的地方效果真的特別棒就發(fā)布了自己的時鐘應(yīng)用。
先上圖(電腦沒有g(shù)if截圖軟件.大家湊合看.哪個軟件好也可以給我推薦下)

話不多說,首先自定義控件XimiClockView繼承view 并做一些初始化的操作
看到的漂亮?xí)r鐘圖片我自己畫的效果圖(以后媽媽再也不用擔(dān)心我遲到了)

public XimiClockView(Context context) {
super(context);
init(context, null);
}
public XimiClockView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public XimiClockView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public XimiClockView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
/**
* 進(jìn)行一些初始化的操作
*
* @param context
* @param attrs
*/
private void init(Context context, AttributeSet attrs) {
if (attrs == null) return;
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MyClockView);
backGroundColor = array.getColor(R.styleable.MyClockView_clockBackColor, Color.parseColor("#2078A8"));
drakColor = array.getColor(R.styleable.MyClockView_clockDarkColor, Color.parseColor("#96C2D8"));
lightColor = array.getColor(R.styleable.MyClockView_clockLightColor, Color.parseColor("#ffffff"));
array.recycle();//注意這里別忘了調(diào)用recycle()方法,[原因](http://www.cnblogs.com/kissazi2/p/4049982.html)
//設(shè)置背景色
setBackgroundColor(backGroundColor);
//文本畫筆
textPaint = new Paint();
textPaint.setColor(drakColor);
textPaint.setTextSize(25);
textRect = new Rect();
}
然后在onSizeChange方法中調(diào)用獲取時鐘半徑,和一些其他的計(jì)算
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
//獲取時鐘的半徑
mRadius = Math.min(w - getPaddingLeft() - getPaddingRight(), h - getPaddingTop() - getPaddingBottom()) / 2;
//為了防止時鐘旋轉(zhuǎn)的時候超出了界限,默認(rèn)加一個padding值
defaultPadding = 0.12f * mRadius;
//圓弧的寬度
mCircleWidth = 0.012f * mRadius;
//圓環(huán)的寬度
mCircleRingWidth = 0.12f*mRadius;
paddingLeft = w / 2 - mRadius + getPaddingLeft() + defaultPadding;
paddingTop = h / 2 - mRadius + getPaddingTop() + defaultPadding;
paddingRight = w / 2 - mRadius + getPaddingRight() + defaultPadding;
paddingBottom = h / 2 - mRadius + getPaddingBottom() + defaultPadding;
mSweepGradient = new SweepGradient(w / 2,h / 2 ,new int[]{drakColor,lightColor},new float[]{0.75f,1f});
}
畫Text
@Override
protected void onDraw(Canvas canvas) {
mCanvas = canvas;
drawTimeText();
}
/**
* 畫12 /3 /6 /9時間
*/
private void drawTimeText() {
String str = "12";
textPaint.getTextBounds(str, 0, str.length(), textRect);
int lengthTextWidth = textRect.width();
int textHeight = textRect.height();
int width=getWidth();
int height=getHeight();
mCanvas.save();//保存畫布的狀態(tài)
mCanvas.drawText(str, width / 2-lengthTextWidth/2,paddingTop+textHeight,textPaint);
str="3";
textPaint.getTextBounds(str, 0, str.length(), textRect);
int smallTextWidth = textRect.width();
mCanvas.drawText("3",width-paddingRight-lengthTextWidth/2-smallTextWidth/2,height/2+textHeight/2,textPaint);
mCanvas.drawText("6",width / 2-smallTextWidth/2,height-paddingBottom,textPaint);
mCanvas.drawText("9",paddingLeft,height/2+textHeight/2,textPaint);
mCanvas.restore();//取出畫布的狀態(tài)
}
崩潰寫完了,我發(fā)表時候提示我沒有登錄,然后發(fā)表異常,然后我一刷新沒了,,,又重新寫一遍,
接下來畫圓弧
/**
* 畫圓弧
*/
private void drawCircleArc() {
mCanvas.save();
mCirclePaint.setStyle(Paint.Style.STROKE);//設(shè)置空心模式
mCirclePaint.setStrokeWidth(mCircleWidth);//設(shè)置圓弧寬度
mCircleRectF.set(paddingLeft + textRect.width() / 2, paddingTop + textRect.height() / 2, getWidth() - paddingRight - textRect.width() / 2, getHeight() - paddingBottom - textRect.height() / 2);
for (int x = 0; x < 4; x++) {
//圓弧分四段來畫,一段話80度
mCanvas.drawArc(mCircleRectF, 5 + 90 * x, 80, false, mCirclePaint);
}
mCanvas.restore();
}
畫刻度
/**
* 畫圓環(huán)和刻度
*/
private void drawCircleRing() {
mCanvas.save();
//畫圓環(huán)
mCircleRingRectF.set(paddingLeft+textRect.height()/2+1.5f*mCircleRingWidth,paddingTop+textRect.height()/2+1.5f*mCircleRingWidth,getWidth()-paddingRight-textRect.height()/2-1.5f*mCircleRingWidth,
getHeight()-paddingBottom-textRect.height()/2-1.5f*mCircleRingWidth);
mMatrix.setRotate(mDegreeS-90,getWidth()/2,getHeight()/2);
mSweepGradient.setLocalMatrix(mMatrix);
mCircleRingPaint.setStyle(Paint.Style.STROKE);
mCircleRingPaint.setStrokeWidth(mCircleRingWidth);
mCircleRingPaint.setShader(mSweepGradient);
mCanvas.drawArc(mCircleRingRectF,0,360,false,mCircleRingPaint);
//畫刻度
mScaleLinePaint.setStrokeWidth(0.1f*mCircleRingWidth);//設(shè)置線的寬度
for (int i=0;i<200;i++){
//畫刻度線
mCanvas.drawLine(getWidth()/2,paddingTop+textRect.height()/2+mCircleRingWidth,getWidth()/2,paddingTop+textRect.height()/2+2*mCircleRingWidth,mScaleLinePaint);
mCanvas.rotate(1.8f,getWidth()/2,getHeight()/2);//旋轉(zhuǎn)角度
}
mCanvas.restore();
}
畫秒針
/**
* 畫秒針
* 秒針針是不規(guī)則的圖形
* 就用到了Path這個類
*
*/
private void drawSoundHand() {
mCanvas.save();
path.reset();
mCanvas.rotate(mDegreeS,getWidth()/2,getHeight()/2);//旋轉(zhuǎn)的角度和旋轉(zhuǎn)的圓心
path.moveTo(getWidth()/2,paddingTop+textRect.height()/2+0.27f*mRadius);//開始的點(diǎn)
path.lineTo(getWidth()/2+0.03f*mRadius,paddingTop+textRect.height()/2+0.31f*mRadius);//直線到這個位置
path.lineTo(getWidth()/2-0.03f*mRadius,paddingTop+textRect.height()/2+0.31f*mRadius);//直線到這個位置
path.close();
mCanvas.drawPath(path,mSoundHandPaint);
mCanvas.restore();
}
畫時針
/**
* 畫時針
*/
private void drawHourHand() {
mCanvas.save();
mCanvas.rotate(mDegreeH,getWidth()/2,getHeight()/2);
hourHandPath.reset();
hourHandPath.moveTo(getWidth()/2-0.02f*mRadius,getHeight()/2);
hourHandPath.lineTo(getWidth()/2-0.01f*mRadius,getHeight()/2-0.35f*mRadius);
//貝塞爾曲線
hourHandPath.quadTo(getWidth()/2,getHeight()/2-0.38f*mRadius,getWidth()/2+0.01f*mRadius,getHeight()/2-0.35f*mRadius);
hourHandPath.lineTo(getWidth()/2+0.02f*mRadius,getHeight()/2);
hourHandPath.close();
mCanvas.drawPath(hourHandPath,mHourHandPaint);
mCanvas.restore();
}
畫分針
/**
* 畫分針
*/
private void drawMinnuteHand() {
mCanvas.save();
mCanvas.rotate(mDegreeM,getWidth()/2,getHeight()/2);
mMinutePath.reset();
mMinutePath.moveTo(getWidth()/2-0.012f*mRadius,getHeight()/2);
mMinutePath.lineTo(getWidth()/2-0.006f*mRadius,getHeight()/2-0.40f*mRadius);
mMinutePath.quadTo(getWidth()/2,getHeight()/2-0.43f*mRadius,getWidth()/2+0.006f*mRadius,getHeight()/2-0.40f*mRadius);
mMinutePath.lineTo(getWidth()/2+0.012f*mRadius,getHeight()/2);
mMinutePath.close();
mCanvas.drawPath(mMinutePath,mMinutePaint);
//畫圈圈蓋著時針的尾部
mCanvas.drawCircle(getWidth()/2,getHeight()/2,0.03f*mRadius,mMinutePaint);
mCanvas.drawCircle(getWidth()/2,getHeight()/2,0.015f*mRadius,mCircleMinPaint);
mCanvas.restore();
}
上我的measure的方法
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(getMeasure(widthMeasureSpec), getMeasure(heightMeasureSpec));
}
private int getMeasure(int measureSpec) {
int result;
int mode = MeasureSpec.getMode(measureSpec);
int size = MeasureSpec.getSize(measureSpec);
if (mode == MeasureSpec.EXACTLY) {
result = size;
} else {
result = 800;
if (mode == MeasureSpec.AT_MOST) {
result = Math.min(result, size);
}
}
return result;
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android獲取設(shè)備CPU核數(shù)、時鐘頻率以及內(nèi)存大小的方法
- Android多功能時鐘開發(fā)案例(實(shí)戰(zhàn)篇)
- android實(shí)現(xiàn)widget時鐘示例分享
- Android 仿日歷翻頁、仿htc時鐘翻頁、數(shù)字翻頁切換效果
- Android多功能時鐘開發(fā)案例(基礎(chǔ)篇)
- android高仿小米時鐘(使用Camera和Matrix實(shí)現(xiàn)3D效果)
- Android實(shí)現(xiàn)簡單時鐘View的方法
- Android自定義動態(tài)壁紙開發(fā)(時鐘)
- Android編程基于自定義控件實(shí)現(xiàn)時鐘功能的方法
- Android自定義View實(shí)現(xiàn)時鐘功能
相關(guān)文章
Android仿硅谷商城實(shí)現(xiàn)購物車實(shí)例代碼
這篇文章主要介紹了Android購物車編輯實(shí)現(xiàn),小編覺得挺不錯的,一起跟隨小編過來看看吧2018-05-05
Android自定義EditText實(shí)現(xiàn)登錄界面
這篇文章主要為大家詳細(xì)介紹了Android自定義EditText實(shí)現(xiàn)登錄界面,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-12-12
Android實(shí)現(xiàn)授權(quán)訪問網(wǎng)頁的方法
這篇文章主要介紹了Android實(shí)現(xiàn)授權(quán)訪問網(wǎng)頁的方法,需要的朋友可以參考下2014-07-07
Android Listview滑動時不加載數(shù)據(jù) 停止時加載數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了Android Listview滑動時不加載數(shù)據(jù),停止時加載數(shù)據(jù),具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-03-03
flutter實(shí)現(xiàn)帶刪除動畫的listview功能
最近接了一個新項(xiàng)目,需要開發(fā)帶有刪除動畫效果的listview功能,在實(shí)現(xiàn)過程中列表滾動效果用listview實(shí)現(xiàn)的,本文通過實(shí)例代碼給大家分享實(shí)現(xiàn)過程,感興趣的朋友跟隨小編一起學(xué)習(xí)下吧2021-05-05
Flutter狀態(tài)管理Provider的使用示例詳解
這篇文章主要為大家介紹了Flutter狀態(tài)管理Provider的使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
基于Android AIDL進(jìn)程間通信接口使用介紹
本篇文章小編為大家介紹,基于Android AIDL進(jìn)程間通信接口使用介紹。需要的朋友參考下2013-04-04

