1.需求分析
略
这种纯图形的罗盘,首先考虑的是用继承View的方式,画圆 画刻度 画方向 画度数
2.代码实现
a.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
tools:context="com.yuncai.menjin.compassdemo.MainActivity">
<com.yuncai.menjin.compassdemo.CompassView
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
b.java
package com.yuncai.menjin.compassdemo;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
/**
* Function:
* Created by TianMing.Xiong on 18-10-26.
*/
public class CompassView extends View {
private Paint circlePaint;
private Paint textPaint;
private int textHeight;
private Paint markerPaint;
public CompassView(Context context) {
super(context);
initCompass();
}
public CompassView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initCompass();
}
private void initCompass() {
setFocusable(true);
circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
circlePaint.setColor(Color.RED);
circlePaint.setStrokeWidth(1);
circlePaint.setStyle(Paint.Style.FILL_AND_STROKE);
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setColor(Color.BLUE);
textHeight = (int) textPaint.measureText("yY");
markerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
markerPaint.setColor(Color.GREEN);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int measuredWidth = measureSize(widthMeasureSpec);
int measuredHeight = measureSize(heightMeasureSpec);
int radius = Math.min(measuredWidth,measuredHeight);
setMeasuredDimension(radius,radius);
}
private int measureSize(int measureSpec) {
int result ;
int mode = MeasureSpec.getMode(measureSpec);
int size = MeasureSpec.getSize(measureSpec);
if(mode == MeasureSpec.UNSPECIFIED){
result = 200;
}else {
result = size;
}
return result;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// view中心点
int px = getMeasuredWidth() / 2;
int py = getMeasuredHeight() / 2;
// 圆半径
int radius = Math.min(px,py);
// 画圆
canvas.drawCircle(px,py,radius,circlePaint);
// 保存图形
canvas.save();// save -->restore成对出现
// 旋转画布,从顶部开始画起
canvas.rotate(0,px,py);
//
int textWidth = (int) textPaint.measureText("W");
// 文字中心点,为什么要这样计算?因为直接在x=textWidth处画文字会导致这个文字在该点的右边,要使文字刚好中心点在该点就需要设置为textWidth/2
int cardinalX = px - textWidth / 2;
int cardinalY = py - radius + textHeight;
// 每15度绘制一个短线刻度(360/15=24)
for (int i = 0; i < 24; i++) {
// 画刻度,坐标(px,0)->(px,10)即从上往下画,刻度长为10
canvas.drawLine(px,py-radius,px,py-radius+10,markerPaint);
canvas.save();// 保存之前的画布状态
// 把画布的原点移动到(0,10),相当于原点坐标下移10,则原来的纵坐标值就相对变大了10(实际坐标值大小不变)
canvas.translate(0,10);
// 绘制四个方向文字(N E S W),坐标(cardinalX,cardinalY),每隔90度即15*6
if(i % 6==0){
String dirString = "";
switch (i){
case 0:
dirString = "N";
break;
case 6:
dirString = "E";
break;
case 12:
dirString = "S";
break;
case 18:
dirString = "W";
break;
}
canvas.drawText(dirString,cardinalX,cardinalY,textPaint);
}else if(i % 3 ==0){// 在非标注方向的刻度上每隔45度画上度数
String angle = String.valueOf(i * 15);
float angleTextWidth = textPaint.measureText(angle);
float angleTextX = px - angleTextWidth / 2;
float angleTextY = py - radius+textHeight;// 为何不是0而是textHeight?文字是从下往上画的,所以减去文字高度刚好使文字在该点下方
canvas.drawText(angle,angleTextX,angleTextY,textPaint);
}
canvas.restore();//把当前画布返回(调整)到上一个save()状态之前
// 旋转画布为正即逆时针旋转,画文字就相当于顺时针画
canvas.rotate(15,px,py);
}
canvas.restore();
}
}