Android自定义仪表盘

前几天项目中用到一个上阵指数大盘指数仪表图效果如下:这里写图片描述
一开始觉得用自定义View来写这个界面,而且仪表盘的图片也给好了,本来想这会非常简单,结果因为指针也是一张图片,指针的圆心不好控制,在给数值的时候总是会有略微的偏差看,尤其是在转着转着的时候就看出来,这是因为指针本身有宽度的问题,代码如下:
public class DashboardCustom extends View {

private Paint paint;
private Paint textPaint;

int speed = 0;
float radius;
private Bitmap back;
private Bitmap center;
private Bitmap arrow;

public DashboardCustom(Context context) {
    this(context, null, 0);
}

public DashboardCustom(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public DashboardCustom(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    /**
     * 获得我们所定义的自定义样式属性
     */
    TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.DashboardCustom, defStyleAttr, 0);

    speed = a.getInt(R.styleable.DashboardCustom_speed, 0);

    paint = new Paint();
    textPaint = new Paint();

    radius = a.getDimension(R.styleable.DashboardCustom_radius, 200);
    back = BitmapFactory.decodeResource(getResources(), R.drawable.dash);
    arrow = BitmapFactory.decodeResource(getResources(), R.drawable.arrow);
    a.recycle();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int width;
    int height;
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);

    if (widthMode == MeasureSpec.EXACTLY) {
        width = widthSize;
    } else {
        float needWidth = back.getWidth();
        int desired = (int) (getPaddingLeft() + needWidth + getPaddingRight());
        width = desired;
    }

    if (heightMode == MeasureSpec.EXACTLY) {
        height = heightSize;
    } else {
        float needWidth = back.getHeight();
        int desired = (int) (getPaddingTop() + needWidth + getPaddingBottom());
        height = desired;
    }
    setMeasuredDimension(width, height);
}

@Override
protected void onDraw(Canvas canvas) {
    int backWidth = back.getWidth();
    int backHeight = back.getHeight();
    //绘制表盘
    canvas.drawBitmap(back, 0, 0, paint);
    //绘制指针
    float arc = (speed % 100) * 240 / 200;
    Matrix matrix = new Matrix();
    matrix.postRotate(arc);


    Bitmap dstbmp = Bitmap.createBitmap(arrow, 0, 0, arrow.getWidth(),
            arrow.getHeight(), matrix, true);

    if (arc >= 0)
        canvas.drawBitmap(dstbmp, backWidth / 2 - arrow.getWidth() / 2 + (int) (arrow.getWidth() * Math.sin(arc * Math.PI / 180)), (int) (backWidth / 2 - arrow.getWidth() / 4 - arrow.getHeight() * Math.cos(arc * Math.PI / 180)), null);
    else {
        canvas.drawBitmap(dstbmp, backWidth / 2 - arrow.getWidth() / 2 + (int) (arrow.getHeight() * Math.sin(arc * Math.PI / 180)), (int) (backWidth / 2 - arrow.getWidth() / 4 - arrow.getHeight() * Math.cos(arc * Math.PI / 180)), null);
    }

    //中心数字
    paint.setStrokeWidth(4);
    paint.setColor(Color.WHITE);
    paint.setTextSize(30);
    //抗锯齿
    paint.setAntiAlias(true);

    paint.setTextAlign(Paint.Align.CENTER);
    canvas.drawText(speed % 100 + "", backWidth / 2, backHeight, paint);

}

public void setSpeed(int speed) {
    this.speed = speed;
    invalidate();
}

}
搞了一天也没有调整好角度,于是退而求其次,好好的分析了一下思路,既然是指针是一张图片,那我就把它固定一个点,然后写个动画让其旋转不就好了么 ,于是有了下面的一种思路,把布局写好,然后写一个动画,完美解决,因为比较简单就不一一讲代码了.
public class DashboardLayout extends RelativeLayout {
private ImageView img_dashboard;
private ImageView img_arrow;
private TextView tv_num;
private float mIndex_num;
private Context context;

public DashboardLayout(Context context) {
    this(context, null, 0);
}

public DashboardLayout(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public DashboardLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    this.context = context;
    initView(context);
}

public void initView(Context context) {
    View.inflate(context, R.layout.dashboar_view, DashboardLayout.this);
    img_dashboard = (ImageView) this.findViewById(R.id.img_dashboard);
    img_arrow = (ImageView) this.findViewById(R.id.img_arrow);
    tv_num = (TextView) this.findViewById(R.id.tv_num);
}

float mFromDegrees = 0;
float mToDegrees = 0;

public void setIndexNum(float index_num) {
    this.mIndex_num = index_num;
    if (mIndex_num > 100f) {
        mIndex_num = 100f;
    }
    if (mIndex_num < -100f) {
        mIndex_num = -100f;
    }

    mToDegrees = (index_num) * 240 / 200;
    RotateAnimation rotateAnimation = new RotateAnimation(mFromDegrees, mToDegrees, 27, 82);
    rotateAnimation.setDuration(500);
    rotateAnimation.setFillAfter(true);
    img_arrow.startAnimation(rotateAnimation);
    mFromDegrees = mToDegrees;
    setText();
}

public void setText() {
    tv_num.setText(mIndex_num + "");

}

}
布局代码:

         <?xml version="1.0" encoding="utf-8"?>
        <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">

            <ImageView
                android:id="@+id/img_dashboard"
                android:layout_width="101dp"
                android:layout_height="76dp"
                android:src="@drawable/dash" />

            <ImageView
                android:id="@+id/img_arrow"
                android:layout_width="27.5dp"
                android:layout_height="41dp"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="9.5dp"
                android:src="@drawable/zhizhen_black" />

            <TextView
                android:id="@+id/tv_num"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="60dp"
                android:text="00"
                android:textSize="15sp" />
        </RelativeLayout>

项目源码地址:https://github.com/gexiangjie/DashboardView

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值