Android自定义view之余额不同状态显示

请尊重个人劳动成果,转载注明出处,谢谢!
http://blog.csdn.net/xiaxiazaizai01

前段时间我的好基友遇到这样一个需求,根据用户的余额使用情况来动态的显示在矩形图上,让用户能更加直观的知道自己的余额使用情况。
这里写图片描述
问我好不好实现,咱能说不好实现吗,,毕竟是学习了一段时间的自定义view,于是下面就开启了装逼之旅。老规矩,效果图走起
这里写图片描述

首先我们先来实现这样的一种需求,假如后端只给我们传过来俩参数,一个是标志位、一个是所占的百分比。这种需求还是比较容易的,主要是动态计算三角形各点的Y轴座标变化。我们先来看张图,画的比较粗糙,大家将就着看吧

这里写图片描述

代码中注释的比较及详细,直接看代码

public class CustomBalanceView extends View{

    private int rectWidth = 200;
    private int rectHeight = 245;
    private int textSize = sp2px(14);
    //矩形画笔
    private Paint rectPaint;
    private Paint linePaint;
    private Paint textPaint;

    private Paint trianglePaint;
    private Path path;
    private int triangleStrokeWidth = dp2px(2);
    private int triangleLength = dp2px(10);
    //余额正常的范围,其中数值上y2大于y1,座标系中y2座标小于y1
    private float y1;
    private float y2;
    //传进来的比较数值
    private float data;
    private String flag;//传进来的标志位

    float textWidth;//文字的宽
    float textHeight;//文字的高
    String text;//文字内容

    private int mLeft = 200;

    //颜色数组
    private int[] colors = new int[]{Color.parseColor("#F75850"),Color.parseColor("#F7D62D"),
            Color.parseColor("#19E6BB")};


    public CustomBalanceView(Context context) {
        this(context,null);
    }

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

    public CustomBalanceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //设置画笔
        setPaint();
        path = new Path();
    }

    private void setPaint() {
        rectPaint = new Paint();
        rectPaint.setAntiAlias(true);
        rectPaint.setDither(true);
        rectPaint.setStyle(Paint.Style.FILL);

        trianglePaint = new Paint();
        trianglePaint.setAntiAlias(true);
        trianglePaint.setDither(true);
        trianglePaint.setStyle(Paint.Style.FILL);
        trianglePaint.setStrokeWidth(triangleStrokeWidth);

        linePaint = new Paint();
        linePaint.setAntiAlias(true);
        linePaint.setDither(true);
        linePaint.setStyle(Paint.Style.FILL);
        linePaint.setStrokeWidth(triangleStrokeWidth);
        linePaint.setColor(Color.parseColor("#275D9D"));

        textPaint = new Paint();
        textPaint.setAntiAlias(true);
        textPaint.setDither(true);
        textPaint.setStyle(Paint.Style.FILL);
        textPaint.setColor(Color.parseColor("#F76E6B"));
        textPaint.setTextSize(textSize);
    }

    @Override
    protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int mWidthSize = MeasureSpec.getSize(widthMeasureSpec);
        int mHeightSize = MeasureSpec.getSize(heightMeasureSpec);
        int widthSize;
        int heightSize;
        int mRectWidth = Math.abs(rectWidth);
        if(widthMode != MeasureSpec.EXACTLY){
            widthSize = getPaddingLeft() + mRectWidth + getPaddingRight();
            widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize,MeasureSpec.EXACTLY);
        }
        if(heightMode != MeasureSpec.EXACTLY){
            heightSize = getPaddingTop() + dp2px(rectHeight) + dp2px(15) + getPaddingBottom();
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize,MeasureSpec.EXACTLY);
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected synchronized void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.save();
        canvas.translate(getPaddingLeft(),getPaddingTop());
        Rect rect = new Rect(200,0,300,dp2px(rectHeight));
        rect.centerY();
        LinearGradient linearGradient = new LinearGradient(200,dp2px(rectHeight),300,0,colors,null, Shader.TileMode.MIRROR);
        rectPaint.setShader(linearGradient);
        canvas.drawRect(rect,rectPaint);
        //绘制三角形
        trianglePaint.setColor(Color.parseColor("#FF0000"));
        int m = String.valueOf(Math.round(y2)).length();
        int n = triangleLength*triangleLength - (triangleLength/2)*(triangleLength/2);
        float firstX = (float) (mLeft - Math.sqrt(n));
        float firstY;

        if(flag.equals("1")){//余额不足
            firstY = (1-data / 100)*dp2px(rectHeight);
            //画文字
            text = "余额不足";
        }else if(flag.equals("2")){//余额正常
            firstY = (1-data / 100)*dp2px(rectHeight);
            //画文字
            text = "余额正常";
        }else{//余额充足
            firstY = (1-data / 100)*dp2px(rectHeight);
            //画文字
            text = "余额充足";
        }
        path.moveTo(firstX,firstY-triangleLength/2);
        path.lineTo(firstX,firstY+triangleLength/2);
        path.lineTo(mLeft,firstY);
        path.close();

        //画三角形
        canvas.drawPath(path,trianglePaint);
        //画线
        linePaint.setColor(Color.parseColor("#FFFFFF"));
        canvas.drawLine(200,firstY,300,firstY,linePaint);
        //画文字
        textWidth = textPaint.measureText(text);
        textHeight = (textPaint.descent() + textPaint.ascent()) / 2;
        canvas.drawText(text,200-textWidth-triangleLength,firstY-textHeight/2+7,textPaint);

        canvas.restore();
    }

    public void setCurrentData(float data){
        this.data = data;
    }
    public void setFlag(String flag){
        this.flag = flag;
    }

    /**
     * dp 2 px
     *
     * @param dpVal
     */
    protected int dp2px(int dpVal)
    {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dpVal, getResources().getDisplayMetrics());
    }

    /**
     * sp 2 px
     *
     * @param spVal
     * @return
     */
    protected int sp2px(int spVal)
    {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                spVal, getResources().getDisplayMetrics());

    }
}

布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:background="#F2F2F2"
    tools:context="com.example.custombalance.MainActivity">

    <RelativeLayout
        android:id="@+id/rl"
        android:layout_width="match_parent"
        android:layout_height="260dp"
        android:layout_marginTop="30dp"
        android:background="#FFFFFF">
        <com.example.custombalance.CustomBalanceView
            android:id="@+id/customBalanceView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingLeft="20dp"
            android:paddingRight="20dp"
            android:paddingTop="15dp"
            android:layout_centerVertical="true"
            android:layout_alignParentRight="true"
            />
    </RelativeLayout>
</RelativeLayout>

MainActivity中的代码

public class MainActivity extends AppCompatActivity{

    private CustomBalanceView balanceView;
    private Button btn1,btn2,btn3;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        balanceView = (CustomBalanceView) findViewById(R.id.customBalanceView);

        balanceView.setCurrentData(50);
        balanceView.setFlag("2");
    }
}

如果现在需求变了,后台给我们传的是一个表示余额正常的区间值,以及一个当前的百分比,根据这个当前值与正常区间值做比较,但是有个问题就是,这个区间值范围是不确定的,也是不规则的,比如[100,500]或者[300,1000],所以,目前想到的思路是这样的,整个矩形按三种渐变颜色平分三等份,每一份有可能是不规则的,所以每一份又看做一个单独的整体,我们需要根据区间值的最大值的长度来确定这个单独个体为多少份,即:10的最大区间值.length次方。代码主要改动的地方就在onDraw方法,同时需要开放出来供外界传入的表示余额正常的区间值以及当前的余额数,直接看代码

@Override
    protected synchronized void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.save();
        canvas.translate(getPaddingLeft(),getPaddingTop());
        Rect rect = new Rect(200,0,300,dp2px(rectHeight));
        rect.centerY();
        LinearGradient linearGradient = new LinearGradient(200,dp2px(rectHeight),300,0,colors,null, Shader.TileMode.MIRROR);
        rectPaint.setShader(linearGradient);
        canvas.drawRect(rect,rectPaint);
        //绘制三角形
        trianglePaint.setColor(Color.parseColor("#FF0000"));
        int m = String.valueOf(Math.round(y2)).length();
        int n = triangleLength*triangleLength - (triangleLength/2)*(triangleLength/2);
        float firstX = (float) (mLeft - Math.sqrt(n));
        float firstY;

        if(data >= y2){
            float cha = 1-(data-y2) / (Math.pow(10,m) - y2)<0 ? 0 : (float) (1 - (data - y2) / (Math.pow(10, m) - y2));
            firstY = cha*mRight;
            path.moveTo(firstX,firstY-triangleLength/2);
            path.lineTo(firstX,firstY+triangleLength/2);
            path.lineTo(mLeft,firstY);
            path.close();
            //画文字
            text = "余额充足";
        }else if(data>y1 && data<y2){
            firstY = (1-(data-y1) / (y2 - y1))*mRight + 300;
            path.moveTo(firstX,firstY-triangleLength/2);
            path.lineTo(firstX,firstY+triangleLength/2);
            path.lineTo(mLeft,firstY);
            path.close();
            //画文字
            text = "余额正常";
        }else{
            firstY =((y1-data) / y1)*mRight + 600;
            path.moveTo(firstX,firstY-triangleLength/2);
            path.lineTo(firstX,firstY+triangleLength/2);
            path.lineTo(mLeft,firstY);
            path.close();
            //画文字
            text = "余额不足";
        }
        //画三角形
        canvas.drawPath(path,trianglePaint);
        //画线
        linePaint.setColor(Color.parseColor("#FFFFFF"));
        canvas.drawLine(200,firstY,300,firstY,linePaint);
        //画文字
        textWidth = textPaint.measureText(text);
        textHeight = (textPaint.descent() + textPaint.ascent()) / 2;
        canvas.drawText(text,200-textWidth-triangleLength,firstY-textHeight/2+7,textPaint);

        /*canvas.drawLine(0,300,300,300,linePaint);
        canvas.drawLine(0,600,300,600,linePaint);*/

        canvas.restore();
    }

马上就要放国庆长假了,终于可以好好出去玩了,有点小激动,时间仓促写的相对随意了一些,有不足的地方欢迎指出。祝大家玩得嗨皮

发布了29 篇原创文章 · 获赞 60 · 访问量 10万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章