自定义 View 实现钟表效果
来源:互联网 发布:ubuntu镜像下载地址 编辑:程序博客网 时间:2024/05/23 11:53
一个很简单的自定义实例,直接上代码,注释已经写得很清楚了
attrs:
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="MyClockView"> <attr name="wb_radius" format="dimension"/> <!--背景颜色--> <attr name="wb_background_color" format="color"/> <!--0369点刻度颜色--> <attr name="wb_scale_large_long_color" format="color"/> <!--时刻刻度颜色--> <attr name="wb_scale_long_color" format="color"/> <!--非时刻刻度颜色--> <attr name="wb_scale_short_color" format="color"/> <!--时针颜色--> <attr name="wb_hour_pointer_color" format="color"/> <!--分针颜色--> <attr name="wb_minute_pointer_color" format="color"/> <!--秒针颜色--> <attr name="wb_second_pointer_color" format="color"/> <!--主题风格--> <attr name="wb_type" format="integer"/> </declare-styleable></resources>
MyClockView:
public class MyClockView extends View { private float mRadius; //外圆半径 private int mBackground; //背景颜色 private int mColorLong; //长线的颜色 private int mColorShort; //短线的颜色 private int mColorLargeLong; //0369点刻度颜色 private int mHourPointColor; //时针的颜色 private int mMinutePointColor; //分针的颜色 private int mSecondPointColor; //秒针的颜色 private int mType; //风格类型 private Paint mPaint; //画笔 private Calendar calendar; private float angleHour; //时针转过的角度 private int angleMinute, angleSecond; //分针和秒针转过的角度 private Bitmap background; //背景图片 private Rect backgroundRect; // 用于缩放背景图片的矩形 private float oneUnit; // 一个单位的长度,由半径得到 private final static int NORMAL = 1; //普通风格 private final static int FRESH = 2; //清新风格 public MyClockView(Context context) { this(context, null); } public MyClockView(Context context, AttributeSet attrs) { super(context, attrs); initAttrs(context, attrs); initPaint(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// 取计算的长度和宽度的最小值,保证view所占空间为正方形 int specSize = Math.min(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec)); setMeasuredDimension(specSize, specSize); if (mRadius == - 1) //如果未设置半径,把半径设为view的长度的一半 mRadius = specSize / 2; int intRadius = (int) mRadius; backgroundRect = new Rect(-intRadius, -intRadius, intRadius, intRadius); oneUnit = (float) (mRadius / 118.5); } @Override protected void onDraw(Canvas canvas) { calendar = Calendar.getInstance(); int hour = calendar.get(Calendar.HOUR); //时 int minute = calendar.get(Calendar.MINUTE); //分 int second = calendar.get(Calendar.SECOND); //秒 int milliSecond = calendar.get(Calendar.MILLISECOND); angleHour = ((hour + (minute + second * 1.0f / 60) * 1.0f / 60)) * 360 / 12; //时针转过的角度 angleMinute = minute * 360 / 60; //分针转过的角度 angleSecond = second * 360 / 60; //秒针转过的角度 canvas.translate(getMeasuredWidth() / 2, getMeasuredHeight() / 2);// 根据设置的风格进行绘制 if (mType == NORMAL) { drawNormal(canvas); } else if (mType == FRESH) { drawFresh(canvas); }// 每秒绘制一次 postInvalidateDelayed(1000 - milliSecond); } // 初始化attr private void initAttrs(Context context, AttributeSet attrs) { TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyClockView); mBackground = ta.getColor(R.styleable.MyClockView_wb_background_color, Color.WHITE); mColorLong = ta.getColor(R.styleable.MyClockView_wb_scale_long_color, Color.BLACK); mColorLargeLong = ta.getColor(R.styleable.MyClockView_wb_scale_large_long_color, mColorLong); mColorShort = ta.getColor(R.styleable.MyClockView_wb_scale_short_color, Color.BLACK); mHourPointColor = ta.getColor(R.styleable.MyClockView_wb_hour_pointer_color, Color.BLACK); mMinutePointColor = ta.getColor(R.styleable.MyClockView_wb_minute_pointer_color, Color.BLACK); mSecondPointColor = ta.getColor(R.styleable.MyClockView_wb_second_pointer_color, Color.BLACK); mType = ta.getInt(R.styleable.MyClockView_wb_type, NORMAL); mRadius = ta.getDimension(R.styleable.MyClockView_wb_radius, - 1); //如果未设置半径,默认值为-1 if (mType == NORMAL) { background = BitmapFactory.decodeResource(getResources(), R.drawable.clock); } ta.recycle(); } // 初始化画笔 private void initPaint() { mPaint = new Paint(); mPaint.setAntiAlias(true); } // 计算宽度 private int measureWidth(int measureSpec) { int result = 0; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.EXACTLY) { result = specSize; } else { //若长度为wrap_content,如果未设置半径,把长度设为200,否则长度为半径的两倍 if (specMode == MeasureSpec.AT_MOST) { if (mRadius == - 1) { result = 200; } else { result = (int) (mRadius * 2); } } } return result; } // 计算高度 private int measureHeight(int measureSpec) { int result = 0; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.EXACTLY) { return specSize; } else { if (specMode == MeasureSpec.AT_MOST) { if (mRadius == - 1) { result = 200; } else { result = (int) (mRadius * 2); } } } return result; }// 绘制普通风格 private void drawNormal(Canvas canvas) { //绘制背景 canvas.drawBitmap(background, null, backgroundRect, null);// 绘制刻度 canvas.save(); mPaint.setColor(mColorLargeLong); mPaint.setStrokeWidth(oneUnit); mPaint.setStyle(Paint.Style.FILL); for (int i = 0; i <= 12; i++) { canvas.drawLine(0, -oneUnit * 78, 0, -oneUnit * 73, mPaint); canvas.rotate(30); } canvas.restore();// 绘制时针 canvas.save(); float hourWidth = (float) (oneUnit * 1.6); mPaint.setColor(mHourPointColor); mPaint.setStrokeWidth(0); Path path = new Path(); path.moveTo(-hourWidth, oneUnit * 15); path.lineTo(hourWidth, oneUnit * 15); path.lineTo(oneUnit, -oneUnit * 50); path.lineTo(-oneUnit, -oneUnit * 50); path.close(); canvas.rotate(angleHour); canvas.drawPath(path, mPaint); canvas.restore();// 绘制分针 canvas.save(); mPaint.setColor(mMinutePointColor); path.moveTo((float) (-oneUnit * 1.5), oneUnit * 15); path.lineTo((float) (oneUnit * 1.5), oneUnit * 15); path.lineTo((float) (oneUnit * 0.8), -oneUnit * 63); path.lineTo((float) (-oneUnit * 0.8), -oneUnit * 63); path.close(); canvas.rotate(angleMinute); canvas.drawPath(path, mPaint); canvas.restore();// 绘制秒针 canvas.save(); mPaint.setColor(mSecondPointColor); mPaint.setStrokeWidth((float) (oneUnit * 1.6)); canvas.rotate(angleSecond); canvas.drawLine(0, -oneUnit * 72, 0, oneUnit * 15, mPaint); canvas.restore();// 绘制中心点 mPaint.setStrokeWidth(0); canvas.drawCircle(0, 0, oneUnit * 4, mPaint); }// 绘制清新风格 private void drawFresh(Canvas canvas) { canvas.save(); mPaint.setColor(mBackground); mPaint.setStyle(Paint.Style.FILL); canvas.drawCircle(0, 0, mRadius, mPaint); canvas.restore(); canvas.save(); mPaint.setColor(mColorLargeLong); mPaint.setStrokeWidth(0); RectF largeLongRectF = new RectF(-oneUnit, -mRadius, oneUnit, (-mRadius + oneUnit * 20)); for (int i = 0; i <= 4; i++) { canvas.drawRoundRect(largeLongRectF, oneUnit, oneUnit, mPaint); canvas.rotate(90); } mPaint.setColor(mColorLong); RectF longRectF = new RectF(-oneUnit, -mRadius, oneUnit, (-mRadius + oneUnit * 31)); for (int i = 0; i <= 12; i++) { if (i % 3 != 0) { canvas.drawRoundRect(longRectF, oneUnit, oneUnit, mPaint); } canvas.rotate(30); } mPaint.setColor(mColorShort); RectF shortRectF = new RectF(-oneUnit, -mRadius, oneUnit, -mRadius + oneUnit * 6); for (int i = 0; i <= 60; i++) { if (i % 5 != 0) { canvas.drawRoundRect(shortRectF, oneUnit, oneUnit, mPaint); } canvas.rotate(6); } canvas.restore(); canvas.save(); float hourWidth = (float) (oneUnit * 3.5); RectF hourRectF = new RectF(-hourWidth, -oneUnit * 61, hourWidth, 0); mPaint.setColor(mHourPointColor); canvas.rotate(angleHour); canvas.drawRoundRect(hourRectF, hourWidth, hourWidth, mPaint); canvas.restore(); canvas.save(); RectF minRectF = new RectF(-hourWidth, -oneUnit * 78, hourWidth, 0); mPaint.setColor(mMinutePointColor); canvas.rotate(angleMinute); canvas.drawRoundRect(minRectF, hourWidth, hourWidth, mPaint); canvas.restore(); canvas.save(); float secondWidth = (float) (oneUnit * 1.5); RectF secondRectF = new RectF(-secondWidth, -mRadius, secondWidth, oneUnit * 20); mPaint.setColor(mSecondPointColor); canvas.rotate(angleSecond); canvas.drawRoundRect(secondRectF, secondWidth, secondWidth, mPaint); canvas.restore(); mPaint.setColor(mHourPointColor); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth((float) (oneUnit * 2.5)); canvas.drawCircle(0, 0, (float) (oneUnit * 5.25), mPaint); mPaint.setColor(mSecondPointColor); mPaint.setStyle(Paint.Style.FILL); mPaint.setStrokeWidth(0); canvas.drawCircle(0, 0, oneUnit * 4, mPaint); }}
添加到 Activity:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:custom="http://schemas.android.com/apk/res-auto" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.ivy.module.app.MainActivity"> <com.ivy.module.app.MyClockView android:layout_width="220dp" android:layout_height="220dp" android:layout_gravity="center_horizontal" custom:wb_hour_pointer_color="@android:color/black" custom:wb_minute_pointer_color="#A996FF" custom:wb_second_pointer_color="#FF0000" custom:wb_scale_large_long_color="#cec8d8" custom:wb_scale_long_color="#cec8d8" custom:wb_type="1"/> <com.ivy.module.app.MyClockView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" custom:wb_radius="120dp" custom:wb_hour_pointer_color="#413c5a" custom:wb_minute_pointer_color="#BCACEE" custom:wb_second_pointer_color="#FF3B7A" custom:wb_scale_large_long_color="#9888E0" custom:wb_scale_long_color="#D4CBF2" custom:wb_scale_short_color="#CBC5E9" custom:wb_type="2"/></LinearLayout>
效果图:
0 0
- 自定义 View 实现钟表效果
- 安卓自定义View实现钟表
- 安卓自定义View实现钟表
- android自定义view实现一个钟表
- 【Android】自定义View -- 钟表
- Android 自定义view钟表
- 自定义View 钟表
- 自定义View新手实战-一步步实现精美的钟表界面
- 自定义View新手实战-一步步实现精美的钟表界面
- 简单自定义View的实现(电子钟表)
- 简单的实现自定义View画一个钟表
- Wpf实现钟表效果
- JS实现钟表效果
- JS实现钟表效果
- QML实现钟表效果
- android自定义View之钟表
- 自定义View之绘制钟表
- 自定义View仿小米钟表
- Linux--闹钟信号
- faster rcnn可视化(修改demo.py保存网络中间结果)
- 3.POI SXSSF导出大量数据实例
- Android设备开机时间统计
- Android获取MAC地址大全
- 自定义 View 实现钟表效果
- 第14周实践-1 项目1 - 数组大折腾(1)
- String全解析
- PHP的CI框架集成Smarty的最佳方式
- laravel队列
- 百度地图覆盖物
- js中 replace replaceAll 全部替换
- 条款2:最好使用C++转型操作符
- 类间两种关系:继承、 组合