android自定义view--指南针背景

本文介绍如何在Android中创建一个自定义View,实现指南针背景的效果。通过提供的代码示例,展示了自定义View的具体实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

直接上代码:


/**
 * Created by 不告诉你 on 15/8/1.
 */
public class ComPassView extends View {

    private Paint markerPaint,textPaint,cirlcePaint;
    private String northString,eastString,westString,southString;
    private int textHeight;
    public ComPassView(Context context) {
        super(context);
        initCompassView();
    }

    public ComPassView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initCompassView();
    }

    public ComPassView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initCompassView();
    }

    private void initCompassView(){
        setFocusable(true);
        cirlcePaint=new Paint(Paint.ANTI_ALIAS_FLAG);
        cirlcePaint.setColor(getResources().getColor(R.color.background_color));


        cirlcePaint.setStrokeWidth(1);
        cirlcePaint.setStyle(Paint.Style.FILL_AND_STROKE);

        Resources resources=this.getResources();
        northString=resources.getString(R.string.north);
        westString=resources.getString(R.string.west);
        eastString=resources.getString(R.string.east);
        southString=resources.getString(R.string.south);

        textPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
        textPaint.setColor(getResources().getColor(R.color.text_color));

        textHeight= (int) textPaint.measureText("yY");

        markerPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
        markerPaint.setColor(getResources().getColor(R.color.marker_color));



    }

    private float bearing;

    public float getBearing() {
        return bearing;
    }

    public void setBearing(float bearing) {
        this.bearing = bearing;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //指南针是一个填充尽可能多的空间的圆
        //通过计算最短的边界高度或者宽度来设置测量的尺寸
        int measuredWidth=measure(widthMeasureSpec);
        int measuredHeight=measure(heightMeasureSpec);
        //得到最小的屏幕宽度作为直径
        int radius=Math.min(measuredHeight,measuredWidth);
        setMeasuredDimension(widthMeasureSpec,heightMeasureSpec);
    }

    private int measure(int measureSpec) {
        int result=0;

        //对测量进行解码
        int specMode=MeasureSpec.getMode(measureSpec);
        int specSize=MeasureSpec.getSize(measureSpec);
        if (specMode==MeasureSpec.UNSPECIFIED){
            //没有指定界限就返回默认的大小200
            result=200;
        }else {
            //由于你希望填充可用的空间,所以总是返回整个可用的边界
            result=specSize;
        }
        return result;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //找到空间中心,并将最小长度作为指南针半径存储起来
        int px=getMeasuredWidth()/2;
        int py=getMeasuredHeight()/2;
        int radius=Math.min(px,py);

        //绘制背景
        canvas.drawCircle(px,py,radius,cirlcePaint);


        canvas.save();
        //旋转视图,上方对着当前方向
        canvas.rotate(-bearing,px,py);

        //做标记
        int textWidth= (int) textPaint.measureText("W");
        int cardinalX=px-textWidth/2;
        int cardinalY=py-radius+textHeight;

        //每15度绘制一个标记,每45度绘制一个文本。

        for (int i=0;i<24;i++){
            canvas.drawLine(px, py - radius, px, py - radius + 10, markerPaint);

            canvas.save();
            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){
                //每45度绘制文本
                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();
            canvas.rotate(15,px,py);

        }
        canvas.restore();

    }
}

主代码:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ComPassView comPassView=new ComPassView(this);
        setContentView(comPassView);
        comPassView.setBearing(45);

    }

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值