自定義view之心率線

先發個圖:


我拿着設計圖問美工MM,中間這波浪是什麼鬼。她說是心率線。額,,,,好吧,無語,畫唄。

再怎麼說你也弄個正弦波出來啊,算了,看你顏值的份上。。。

效果圖:



基本原理圖如下,在view的右側非可視區內加載脈衝數組,一個脈衝數組記錄了脈衝那幾個點在view中的高度




1.  定義attr屬性,並在構造體初始化。

attrs.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="HeartRateLine">
        <attr name="pulses" format="integer"/>
        <attr name="pointsOfEachPulse" format="integer"/>
        <attr name="speed" format="integer"/>     
    </declare-styleable>    
</resources>
2.onMeasure不重寫,直接onDraw(), layout_width和layout_height最好賦確定值,下面放整個view的代碼。

HeartRateLine.java:

public class HeartRateLine extends View {
	
	//脈衝個數
	private int pulses;
	//每個脈衝的點數,用於畫path
	private int pointsOfEachPulse;
	//心率線每移動一個點距所需的時間
	private int speed;
	private Paint paint;
	
	private int[] pointsHeight;
	private int points;
	private boolean isInit=false;
	private int count;

	public HeartRateLine(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		// TODO Auto-generated constructor stub
		
		TypedArray array=context.obtainStyledAttributes(attrs, R.styleable.HeartRateLine);
		pulses=array.getInt(R.styleable.HeartRateLine_pulses, 5);
		pointsOfEachPulse=array.getInt(R.styleable.HeartRateLine_pointsOfEachPulse, 10);
		speed=array.getInt(R.styleable.HeartRateLine_speed, 100);		
		
		array.recycle();
		
		paint=new Paint();
		paint.setColor(Color.RED);
		paint.setAntiAlias(true);
		paint.setStrokeWidth(1f);
		paint.setStyle(Style.STROKE);
		
		//在view可視區內的點數
		points=pulses*pointsOfEachPulse;
		//+pointsOfEathPulse是增加在View的非可視區內的點數(即在非可視區加載一個脈衝),
		//+1是爲了數組前後依次賦值時避免到最後一個點賦值越界的情況
		pointsHeight=new int[points+pointsOfEachPulse+1];		
		
	}

	public HeartRateLine(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
		// TODO Auto-generated constructor stub
	}

	public HeartRateLine(Context context) {
		this(context, null);
		// TODO Auto-generated constructor stub
	}

	@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		
		//點與點之間的間隔
		int intervalBetweenPoints=getWidth()/(pulses*pointsOfEachPulse-1);
		
		//初始化所有點的高,使之全部等於高的一半
		if(!isInit){
			for(int i=0; i<pointsHeight.length; i++){
				pointsHeight[i]=getHeight()/2;
			}
			isInit=true;
		}
		
		//創建一條路徑,並按點與點的間隔遞增和poitsHeight數據得到點的位置
		Path path=new Path();
		path.moveTo(0, getHeight()/2);
		for(int i=0; i<pointsHeight.length; i++){
			path.lineTo(intervalBetweenPoints*i, pointsHeight[i]);
		}
		
		//畫路徑
		canvas.drawPath(path, paint);
		
		//使pointsHeight前後依次賦值並重繪,使路徑一個點距一個點距地動起來,
		//且每一個pulse週期(即pointsOfEachPulse),則在view的右邊不可視區域加載新的pulse
		postDelayed(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				for(int i=0; i<points+pointsOfEachPulse; i++){
					pointsHeight[i]=pointsHeight[i+1];
				}
				if(count==pointsOfEachPulse){
					//隨機一個高度以內的數值
					int height=(int) (Math.random()*getHeight()/2);
					
					//在pointsOfEachPulse這幾個點之內畫好你想要的pulse形狀
					//這裏實例只是簡單地上下放一個隨機高度而已	
					//這裏要確保pointsOfEachPulse>3,否則越界
					for(int i=0; i<pointsOfEachPulse; i++){
						if(i==1){
							pointsHeight[points+i]=getHeight()/2-height;
						}else if(i==2){
							pointsHeight[points+i]=getHeight()/2+height;
						}else{
							pointsHeight[points+i]=getHeight()/2;
						}						
					}					
					count=0;
				}
				count++;
				
				invalidate();
			}
		}, speed);
	}

}

我只是簡單地畫了一個閃電狀的脈衝圖形,其實還可以增加脈衝點數,利用CornerPathEffect可以畫出正弦波圖形的,這裏就簡單顯示一下而已。


代碼下載:github

發佈了33 篇原創文章 · 獲贊 50 · 訪問量 21萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章