Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android自定義View——實現理財類APP七日年化收益折線圖效果

Android自定義View——實現理財類APP七日年化收益折線圖效果

編輯:關於Android編程

這段時間的自定義View學習,學會了繪制柱狀圖、繪制折線圖、繪制進度控件,那我們今天就來聊聊另外一種自定義的View,這就是我們常見的七日年化收益折線圖效果。先看看長什麼樣。

這裡寫圖片描述

這就是效果圖了,元素相對而言還是比較多的,這裡有線、柱狀圖、文字、折線、點等等。看起來好像很復雜,但是呢,只要一步一步的實現,那還是可以達到這種效果的,之前我們說過的, 自定義View,就像是在photo shop裡面畫圖,想要什麼就畫什麼,我們可以有很多的畫筆工具,也可以有很多的圖層。

先看看我們這一次用到哪些變量。

    private Paint mTextPaint, mLinePaint,mPathPaint,mPointPaint;
    //柱狀圖的寬度
    private float mPaintRectWidth;
    //路徑
    private Path mPath;
    //高跟寬
    private float mWidth, mHeight;
    //柱狀圖的數量
    private final float mCount = 6;
    //偏移量
    private final float offsets=1;

    private float mRectHeight;
    //x軸的坐標
    private List xline=new ArrayList();
    //Y軸的坐標
    private List yline=new ArrayList();

    //左邊文字
    private float []x={2.46f,2.45f,2.44f,2.43f,2.42f,2.41f,2.40f};
    //底部文字
    private String [] day={"07-01","07-02","07-03","07-04","07-05","07-06","07-07"};

注釋標記的也是夠詳細了,為了大家能夠看得懂,也為了提高的博客質量,我們注意到,這裡有文字,有數量,基本涵蓋了我們這裡索要用到的所有的變量。

下面開始初始化操作。


    private void initView() {
        //繪制線和文字的顏色
        mTextPaint = new Paint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setColor(Color.parseColor("#cccccc"));
        mTextPaint.setTextSize(25);
        mTextPaint.setStrokeWidth(1);

        //繪制折線圖的點
        mPointPaint= new Paint();
        mPointPaint.setAntiAlias(true);
        mPointPaint.setColor(Color.parseColor("#000000"));
        mPointPaint.setTextSize(25);
        mPointPaint.setStrokeWidth(5);

        //繪制柱狀圖的畫筆
        mLinePaint = new Paint();
        mLinePaint.setAntiAlias(true);

        //繪制折線圖的畫筆
        mPathPaint= new Paint();
        mPathPaint.setAntiAlias(true);
        mPathPaint.setColor(Color.parseColor("#ff0000"));
        mPathPaint.setStyle(Style.STROKE);

        //折線圖的路徑
        mPath=new Path();

    }

這裡主要就是給畫筆初始化,可以看到每一個畫筆的顏色、寬度都是不一樣的,值的注意的是,這裡面的畫筆並沒有設置镂空樣式。

接下來我們看看怎麼去賦值,老規矩,我們還是選擇在onSizeChange()裡面進行賦值,代碼如下:

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth=(float)(getWidth()-getWidth()*0.1);
        mHeight=(float)(getHeight()-getHeight()*0.1);
        mRectHeight=(float)(getHeight()-getHeight()*0.1);
        mPaintRectWidth=(float) (mWidth*0.8/mCount);
        mLinePaint.setStrokeWidth(mPaintRectWidth);
    }

跟之前的不一樣,我們以前所要用的寬度跟高度,直接就是使用方法裡的,但是現在我們沒有這麼做,例如:(float)(getWidth()-getWidth()*0.1);我們進行了一定的處理,這樣可以提高頁面的舒適性,提高用戶體驗。

好了,准備工作做好了,接下來看看onDraw方法裡面的操作,代碼如下:

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        onDrawRect(canvas);     
        onDrawLine(canvas);
        canvasPath(canvas);
    }

喲呵,怎麼這麼簡單,就三個東西?對的,就是這麼簡單粗暴,從名字中也可以看出,第一個是繪制矩形,第二個繪制線,第三個就是繪制折線。是不是很快呢,下面看看具體的實現方式。

第一個方法:

    //繪制6個矩形
    private void onDrawRect(Canvas canvas) {
        for (int i = 0; i < 7; i++) {
            if (i%2==0) {
                mLinePaint.setColor(Color.parseColor("#eeeeee"));
            }else {
                mLinePaint.setColor(Color.parseColor("#ece1f3"));
            }   
            float left  =(float) (mWidth * 0.4 / 2 + mPaintRectWidth * i + offsets);
            float right=(float) (mWidth * 0.4 / 2 + mPaintRectWidth* (i + 1));

            canvas.drawRect(left,(float)(mRectHeight*0.01),right, mHeight, mLinePaint);
        }

    }

第二個:

    //繪制網格線
    private void onDrawLine(Canvas canvas){
        //第一條線
        canvas.drawLine(mPaintRectWidth-mPaintRectWidth/2, (float)(mRectHeight*0.01), getWidth(),  (float)(mRectHeight*0.01), mTextPaint);
        //定義這裡高度
        float height;
        //橫七條
        for (float i = 0; i < 7; i++) {
            //從上到下
            if (i==0) {
                height=i;
            }else {
                height=mRectHeight*(i/6);
                float size=mTextPaint.measureText(x[(int)i]+"");
                //繪制線
                canvas.drawLine(mPaintRectWidth+mPaintRectWidth/2, height, getWidth(),  height, mTextPaint);
                //繪制左邊Y軸的文字
                canvas.drawText(x[(int)i]+"", (float)(mPaintRectWidth-mPaintRectWidth*0.35), height+size/5, mTextPaint);
            }

        }
        //豎七條
        canvas.drawLine((float) (mPaintRectWidth-mPaintRectWidth/2),0, (float) (mPaintRectWidth-mPaintRectWidth/2),  mHeight, mTextPaint);
        for (float i = 0; i < 7; i++) {
            //從左到右
            canvas.drawLine((float) (mWidth * 0.4 / 2 + mPaintRectWidth * i),0, (float) (mWidth * 0.4 / 2 + mPaintRectWidth * i),  mHeight, mTextPaint);
            //繪制底邊的日期文字
            canvas.drawText(day[(int) i], (float) (mWidth * 0.34 / 2 + mPaintRectWidth * i), (float)(mHeight+mHeight*0.1), mTextPaint);
            //准備好下面折線圖的X軸坐標
            xline.add((float) (mWidth * 0.4 / 2 + mPaintRectWidth * i));
        }
        //折線圖的第一個點
        xline.add((float) (mPaintRectWidth-mPaintRectWidth/2));



    }

這裡的代碼相對較多,我專門加了許多的注釋,可以用心的看看。

第三個繪制折線:

    //繪制折線路徑
    public void canvasPath(Canvas canvas){


        for (int j = 0; j < yline.size(); j++) {

            float x=xline.get(j);
            float y =yline.get(j);
            float aftery=Math.initData(y);
            if (j==0) {
                mPath.moveTo(x,aftery );
            }else{

                mPath.lineTo(x,aftery );
            }
            canvas.drawPoint(x, aftery, mPointPaint);
            float size=mPointPaint.measureText(y+"");
            canvas.drawText(y+"", (float)(x-size/2), (float)(aftery+size*0.25), mPointPaint);
        }
        canvas.drawPath(mPath, mPathPaint);
    }

這裡的繪制折線包括繪制線、點、文字、還有文字的轉換、但是這個轉換可以根據自己的需求來進行定制。

最後向外面暴露一個方法,用於更新坐標。

    //用於設置Y軸的坐標值
    public void setDataY( List yline) {
        this.yline.clear();
        this.yline=yline;
    }
    //一個更新UI的方法
    public void invalidata(){
        invalidate();
    }

文字的轉換我這裡用一個自己的類去處理了,代碼如下:

    public static float initData(float a){

        if (2.40f<=a&&a<2.41f) {
            a=540f-540f/(a/0.01f);
        }else if(2.41f<=a&&a<2.42f){
            a=480f-480f/(a/0.01f);
        }else if (2.42f<=a&&a<2.43f) {
            a=360f-360f/(a/0.01f);
        }else if (2.43f<=a&&a<2.44f) {
            a=270f-270f/(a/0.01f);
        }else if (2.44f<=a&&a<2.45f) {
            a=180f-180f/(a/0.01f);
        }else if (2.45f<=a&&a<2.46f) {
            a=90f-90f/(a/0.01f);
        }

        return a;

    }

以上就是邏輯的實現過程了。最後,我把所有代碼貼上來:

AnnualyieldView.java

/**
 * 小瓶蓋 2016年7月13日18:08:28
 * 
 * @author Android自定義View——實現理財類APP七日年化收益折線圖效果
 *
 *相關博客地址 http://blog.csdn.net/qq_25193681
 */
public class AnnualyieldView extends View {

    private Paint mTextPaint, mLinePaint,mPathPaint,mPointPaint;
    //柱狀圖的寬度
    private float mPaintRectWidth;
    //路徑
    private Path mPath;
    //高跟寬
    private float mWidth, mHeight;
    //柱狀圖的數量
    private final float mCount = 6;
    //偏移量
    private final float offsets=1;

    private float mRectHeight;
    //x軸的坐標
    private List xline=new ArrayList();
    //Y軸的坐標
    private List yline=new ArrayList();

    //左邊文字
    private float []x={2.46f,2.45f,2.44f,2.43f,2.42f,2.41f,2.40f};
    //底部文字
    private String [] day={"07-01","07-02","07-03","07-04","07-05","07-06","07-07"};

    public AnnualyieldView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        initView();

    }

    public AnnualyieldView(Context context, AttributeSet attrs) {
        super(context, attrs);

        initView();
    }

    public AnnualyieldView(Context context) {
        super(context);

        initView();
    }

    private void initView() {
        //繪制線和文字的顏色
        mTextPaint = new Paint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setColor(Color.parseColor("#cccccc"));
        mTextPaint.setTextSize(25);
        mTextPaint.setStrokeWidth(1);

        //繪制折線圖的點
        mPointPaint= new Paint();
        mPointPaint.setAntiAlias(true);
        mPointPaint.setColor(Color.parseColor("#000000"));
        mPointPaint.setTextSize(25);
        mPointPaint.setStrokeWidth(5);

        //繪制柱狀圖的畫筆
        mLinePaint = new Paint();
        mLinePaint.setAntiAlias(true);

        //繪制折線圖的畫筆
        mPathPaint= new Paint();
        mPathPaint.setAntiAlias(true);
        mPathPaint.setColor(Color.parseColor("#ff0000"));
        mPathPaint.setStyle(Style.STROKE);

        //折線圖的路徑
        mPath=new Path();

    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth=(float)(getWidth()-getWidth()*0.1);
        mHeight=(float)(getHeight()-getHeight()*0.1);
        mRectHeight=(float)(getHeight()-getHeight()*0.1);
        mPaintRectWidth=(float) (mWidth*0.8/mCount);
        mLinePaint.setStrokeWidth(mPaintRectWidth);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        onDrawRect(canvas);     
        onDrawLine(canvas);
        canvasPath(canvas);
    }
    //繪制6個矩形
    private void onDrawRect(Canvas canvas) {
        for (int i = 0; i < 7; i++) {
            if (i%2==0) {
                mLinePaint.setColor(Color.parseColor("#eeeeee"));
            }else {
                mLinePaint.setColor(Color.parseColor("#ece1f3"));
            }   
            float left  =(float) (mWidth * 0.4 / 2 + mPaintRectWidth * i + offsets);
            float right=(float) (mWidth * 0.4 / 2 + mPaintRectWidth* (i + 1));

            canvas.drawRect(left,(float)(mRectHeight*0.01),right, mHeight, mLinePaint);
        }

    }
    //繪制網格線
    private void onDrawLine(Canvas canvas){
        //第一條線
        canvas.drawLine(mPaintRectWidth-mPaintRectWidth/2, (float)(mRectHeight*0.01), getWidth(),  (float)(mRectHeight*0.01), mTextPaint);
        //定義這裡高度
        float height;
        //橫七條
        for (float i = 0; i < 7; i++) {
            //從上到下
            if (i==0) {
                height=i;
            }else {
                height=mRectHeight*(i/6);
                float size=mTextPaint.measureText(x[(int)i]+"");
                //繪制線
                canvas.drawLine(mPaintRectWidth+mPaintRectWidth/2, height, getWidth(),  height, mTextPaint);
                //繪制左邊Y軸的文字
                canvas.drawText(x[(int)i]+"", (float)(mPaintRectWidth-mPaintRectWidth*0.35), height+size/5, mTextPaint);
            }

        }
        //豎七條
        canvas.drawLine((float) (mPaintRectWidth-mPaintRectWidth/2),0, (float) (mPaintRectWidth-mPaintRectWidth/2),  mHeight, mTextPaint);
        for (float i = 0; i < 7; i++) {
            //從左到右
            canvas.drawLine((float) (mWidth * 0.4 / 2 + mPaintRectWidth * i),0, (float) (mWidth * 0.4 / 2 + mPaintRectWidth * i),  mHeight, mTextPaint);
            //繪制底邊的日期文字
            canvas.drawText(day[(int) i], (float) (mWidth * 0.34 / 2 + mPaintRectWidth * i), (float)(mHeight+mHeight*0.1), mTextPaint);
            //准備好下面折線圖的X軸坐標
            xline.add((float) (mWidth * 0.4 / 2 + mPaintRectWidth * i));
        }
        //折線圖的第一個點
        xline.add((float) (mPaintRectWidth-mPaintRectWidth/2));



    }
    //繪制折線路徑
    public void canvasPath(Canvas canvas){


        for (int j = 0; j < yline.size(); j++) {

            float x=xline.get(j);
            float y =yline.get(j);
            float aftery=Math.initData(y);
            if (j==0) {
                mPath.moveTo(x,aftery );
            }else{

                mPath.lineTo(x,aftery );
            }
            canvas.drawPoint(x, aftery, mPointPaint);
            float size=mPointPaint.measureText(y+"");
            canvas.drawText(y+"", (float)(x-size/2), (float)(aftery+size*0.25), mPointPaint);
        }
        canvas.drawPath(mPath, mPathPaint);
    }
    //用於設置Y軸的坐標值
    public void setDataY( List yline) {
        this.yline.clear();
        this.yline=yline;
    }
    //一個更新UI的方法
    public void invalidata(){
        invalidate();
    }
}

MainActivity.java

/**
 * 小瓶蓋 2016年7月13日18:08:28
 * 
 * @author Android自定義View——實現理財類APP七日年化收益折線圖效果
 *
 *相關博客地址 http://blog.csdn.net/qq_25193681
 */
public class MainActivity extends Activity {
    private AnnualyieldView annualyieldView;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        annualyieldView=(AnnualyieldView) findViewById(R.id.line);
        initdata();
    }
    private void initdata() {
        List yline=new ArrayList();
        yline.add(2.420123f);
        yline.add(2.444122f);
        yline.add(2.45359f);
        yline.add(2.4206f);
        yline.add(2.4357f);
        yline.add(2.4228f);
        yline.add(2.4350f);
        annualyieldView.setDataY(yline);

    }

}

布局文件activity_main.xml:



    

        

        
    

還有一個用於轉換的類,Math.java

/**
 * 小瓶蓋 2016年7月13日18:08:28
 * 
 * @author Android自定義View——實現理財類APP七日年化收益折線圖效果
 *
 *相關博客地址 http://blog.csdn.net/qq_25193681
 */
public class Math {

    public static float initData(float a){

        if (2.40f<=a&&a<2.41f) {
            a=540f-540f/(a/0.01f);
        }else if(2.41f<=a&&a<2.42f){
            a=480f-480f/(a/0.01f);
        }else if (2.42f<=a&&a<2.43f) {
            a=360f-360f/(a/0.01f);
        }else if (2.43f<=a&&a<2.44f) {
            a=270f-270f/(a/0.01f);
        }else if (2.44f<=a&&a<2.45f) {
            a=180f-180f/(a/0.01f);
        }else if (2.45f<=a&&a<2.46f) {
            a=90f-90f/(a/0.01f);
        }

        return a;

    }
}

以上就是代碼的全部內容,我記得我大學的老實說,不懂的地方就自己多敲代碼,多了就懂了,雖然那時候我不認同,但是現在覺得還是有一定道理,都是一樣過來的,現在希望能夠跟大家一起進步。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved