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