Android 自定义UI--指南针

来源:互联网 发布:结构动力特性试验数据 编辑:程序博客网 时间:2024/05/16 00:35

    有了之前的基础,下面开始实现一个简单的指南针。首先来看一下效果图,


    我们可以粗略将这个指南针分为三个部分,一是圆形背景,二是刻度,三是文本。那么在写代码的时候,就可以声明三个Paint画笔来画以上三个物体。代码如下:

package com.example.apptest;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.util.AttributeSet;import android.util.Log;import android.view.View;/** * 指南针 *  */class CompassView extends View {    //刻度画笔private Paint markerPaint;//文本画笔private Paint textPaint;//圆形画笔private Paint circlePaint;//字符串private String northString;//字符串private String eastString;//字符串private String southString;//字符串private String westString;//文本高度private int textHeight;//轴private float bearing;    /**     *      * @param _bearing     */public void setBearing(float _bearing) {bearing = _bearing;}    /**     *      * @return     */public float getBearing() {return bearing;}public CompassView(Context context) {super(context);initCompassView();}public CompassView(Context context, AttributeSet attrs) {super(context, attrs);initCompassView();}public CompassView(Context context, AttributeSet attrs, int defaultStyle) {super(context, attrs, defaultStyle);initCompassView();}protected void initCompassView() {setFocusable(true);// 东西南北northString = "北";eastString = "东";southString = "南";westString = "西";// 设置实心圆画笔circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);circlePaint.setColor(Color.BLACK);circlePaint.setStrokeWidth(1);circlePaint.setStyle(Paint.Style.FILL_AND_STROKE);// 设置线条画笔 刻度markerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);markerPaint.setColor(Color.RED);// 设置坐标画笔 东西南北 度数textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);textPaint.setColor(Color.WHITE);// 设置文字高度textHeight = (int) textPaint.measureText("yY");        Log.i("textHeight", textHeight+"");}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int measuredWidth = measure(widthMeasureSpec);int measuredHeight = measure(heightMeasureSpec);int d = Math.min(measuredWidth, measuredHeight);setMeasuredDimension(d, d);}    /**     * @category      * @param measureSpec     * @return     */private int measure(int measureSpec) {int result = 0;int specMode = MeasureSpec.getMode(measureSpec);int specSize = MeasureSpec.getSize(measureSpec);if (specMode == MeasureSpec.UNSPECIFIED) {result = 200;} else {result = specSize;}return result;}@Overrideprotected void onDraw(Canvas canvas) {// 圆心坐标int px = getMeasuredWidth() / 2;Log.i("px", px+"");int py = getMeasuredHeight() / 2;Log.i("py", py+"");// 半径 取最小值int radius = Math.min(px, py);Log.i("radius", radius+"");// 画圆canvas.drawCircle(px, py, radius, circlePaint);canvas.save();canvas.rotate(-bearing, px, py);// 东西南北 坐标位置int textWidth = (int) textPaint.measureText("W");Log.i("textWidth", textWidth+"");int cardinalX = px - textWidth / 2;Log.i("cardinalX", cardinalX+"");int cardinalY = py - radius + textHeight;Log.i("cardinalY", cardinalY+"");//画24个刻度for (int i = 0; i < 24; i++) {//画刻度canvas.drawLine(px, py - radius, px, py - radius + 10, markerPaint);canvas.save();//移动原点textHeight距离 开始画东西南北以及度数canvas.translate(0, textHeight);//判断如果满足条件画东西南北if (i % 6 == 0) {String dirString = "";switch (i) {case (0): {dirString = northString;// 画指南针int arrowY = 2 * textHeight;canvas.drawLine(px, arrowY, px - 5, 3 * textHeight,markerPaint);canvas.drawLine(px, arrowY, px + 5, 3 * textHeight,markerPaint);break;}case (6):dirString = eastString;break;case (12):dirString = southString;break;case (18):dirString = westString;break;}//画东西南北canvas.drawText(dirString, cardinalX, cardinalY, textPaint);}else if (i % 3 == 0) {//判断如果满足条件画4个度数String angle = String.valueOf(i * 15);float angleTextWidth = textPaint.measureText(angle);int angleTextX = (int) (px - angleTextWidth / 2);int angleTextY = py - radius + textHeight;//画弧度数canvas.drawText(angle, angleTextX, angleTextY, textPaint);}canvas.restore();//每隔15度旋转一下canvas.rotate(15, px, py);}canvas.restore();}}

    这个例子中,多了一个measure过程,重写了OnMeasure()过程,用于计算View的大小。先不细说这个,下面重点说一下如何画图的。背景很简单,不多说,难点还是在于刻度以及文字的实现。我们知道,画文本可以使用drawText()方法,画刻度也就是画直线,可以使用drawLine()方法。那关键问题就是在哪个位置画刻度以及文本。本例子中,圆形的大小取决于屏幕的宽度,可以看到圆形的直接就是屏幕的宽度。画刻度线也是从圆心坐标开始的,直接使用drawLine()方法。还有一个地方需要注意就是东西南北以及刻度的文字是移动了一段距离后开始绘制的,使用的方法就是translate(),在画完14个刻度之后调用这个方法。





3 0
原创粉丝点击