1. 程式人生 > >手把手教你打造一個心電圖效果View Android自定義View

手把手教你打造一個心電圖效果View Android自定義View

大家好,看我像不像蘑菇…因為我在學校呆的發黴了。這裡寫圖片描述

思而不學則殆

麗麗說得對,我有奇怪的疑問,大都是思而不學造成的,在我書讀不夠的情況下想太多,大多等於白想這裡寫圖片描述,所以革命沒成功,同志仍需努力。

好了廢話不說了,由於布總要做一個心電圖的玩意,所以做來練練手,總之拿到的UI圖如下:
這裡寫圖片描述

做好的效果如下:
這裡寫圖片描述
拿到圖,先做一些簡單的分析。呃..

  • 背景表格的繪製
  • 心電圖的繪製

背景表格的繪製:

首先drawColor黑色,然後用迴圈來畫線、

心電圖的繪製:

看樣子是path,應該沒問題。

於是就大幹一番,按照這倆步驟畫完了。。結果發現,嗯。。確實畫上去了,關鍵怎麼讓他動呢。。 輕而易舉想到scrollBy吧。然後你就發現。。背景也跟著變了。。 遇到問題就要解決。。所以這裡投機取巧一下 把兩個View分離,即背景是一個View,折線圖是一個View。

首先,建立一個View,用來做背景View。他有一些屬性,因為這些View本來是一個,後來又有一個折現View需要相同的屬性,所以索性偷懶改成protected修飾。。
轉載請註明出處:http://blog.csdn.net/wingichoy/article/details/51023865

public class CardiographView extends View {
    //畫筆
    protected Paint mPaint;
    //折現的顏色
    protected int mLineColor = Color.parseColor("#76f112");
    //網格顏色
protected int mGridColor = Color.parseColor("#1b4200"); //小網格顏色 protected int mSGridColor = Color.parseColor("#092100"); //背景顏色 protected int mBackgroundColor = Color.BLACK; //自身的大小 protected int mWidth,mHeight; //網格寬度 protected int mGridWidth = 50; //小網格的寬度 protected int
mSGridWidth = 10; //心電圖折現 protected Path mPath ;

定義了這些屬性,在構造器裡初始化一下畫筆和Path

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

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

    public CardiographView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mPaint = new Paint();
        mPath = new Path();
    }

接下來拿到自身的寬高。注意為了簡化例子,這裡就不測量了

@Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        mWidth = w;
        mHeight = h;
        super.onSizeChanged(w, h, oldw, oldh);
    }

準備工作都完成,開始繪製背景,建立一個drawBackground(Canvas canvas)方法。
可以想到,用for迴圈來畫橫線豎線。橫線的起始x座標都是0,終止x座標是mWidth, y座標為i*mGridWidth(網格寬度),我們要拿到網格的個數,即寬高除以網格寬度,具體操作看程式碼:

 private void initBackground(Canvas canvas) {

        canvas.drawColor(mBackgroundColor);
        //畫小網格

        //豎線個數
        int vSNum = mWidth /mSGridWidth;

        //橫線個數
        int hSNum = mHeight/mSGridWidth;
        mPaint.setColor(mSGridColor);
        mPaint.setStrokeWidth(2);
        //畫豎線
        for(int i = 0;i<vSNum+1;i++){
            canvas.drawLine(i*mSGridWidth,0,i*mSGridWidth,mHeight,mPaint);
        }
        //畫橫線
        for(int i = 0;i<hSNum+1;i++){

            canvas.drawLine(0,i*mSGridWidth,mWidth,i*mSGridWidth,mPaint);
        }

        //豎線個數
        int vNum = mWidth / mGridWidth;
        //橫線個數
        int hNum = mHeight / mGridWidth;
        mPaint.setColor(mGridColor);
        mPaint.setStrokeWidth(2);
        //畫豎線
        for(int i = 0;i<vNum+1;i++){
            canvas.drawLine(i*mGridWidth,0,i*mGridWidth,mHeight,mPaint);
        }
        //畫橫線
        for(int i = 0;i<hNum+1;i++){
            canvas.drawLine(0,i*mGridWidth,mWidth,i*mGridWidth,mPaint);
        }


    }

現在的執行效果是這樣的:
這裡寫圖片描述
呃。。。看起來像點樣子了。。

現在給加上Path吧。。新建一個View,寫到相對佈局的底部

<?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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.wingsofts.cardiograph.MainActivity">
<com.wingsofts.cardiograph.CardiographView
    android:layout_width="match_parent"
    android:layout_height="match_parent"></com.wingsofts.cardiograph.CardiographView>

    <com.wingsofts.cardiograph.PathView
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>

為了簡單起見,新建一個View 繼承CardiographView, 這裡只需要重寫他的ondraw方法即可,其他屬性不需要定義。

 private void drawPath(Canvas canvas) {
        // 重置path
        mPath.reset();

        //用path模擬一個心電圖樣式
        mPath.moveTo(0,mHeight/2);
        int tmp = 0;
        for(int i = 0;i<10;i++) {
            mPath.lineTo(tmp+20, 100);
            mPath.lineTo(tmp+70, mHeight / 2 + 50);
            mPath.lineTo(tmp+80, mHeight / 2);

            mPath.lineTo(tmp+200, mHeight / 2);
            tmp = tmp+200;
        }
        //設定畫筆style
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(mLineColor);
        mPaint.setStrokeWidth(5);
        canvas.drawPath(mPath,mPaint);

    }

好了,現在畫出來是這樣的:
這裡寫圖片描述

那怎麼讓他動起來呢。 當然是scrollBy了~~ 這裡注意下scrollBy 和scrollTo的區別,面試常考的,之後再postInvalidateDelayed即可

  @Override
    protected void onDraw(Canvas canvas) {
        drawPath(canvas);
        scrollBy(1,0);
        postInvalidateDelayed(10);
    }

大功告成! 這樣就和上面的實現圖一樣了:

這裡寫圖片描述

當然這只是個demo,你可以根據自己的需求去不同的座標去繪製,來達到真實的心電圖效果。

如果你喜歡我的部落格,請點關注哦。。

另外:如果你有職位 只要在廣州 歡迎拉我,我剛辭實習工作,六月就要畢業了,即將失業了!!!

本專案地址(求star):點選開啟