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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章