• 手把手教你打造一个心电图效果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):点击打开

  • 相关阅读:
    第九周学习进度
    用户场景描述
    第九天
    第10天
    求两个有序数组的中值
    计算字符串中最长子字符串的长度
    计算两个数之和
    将string 转int
    判断一个int 型整数 是否为回文数
    php 对象的一些特性
  • 原文地址:https://www.cnblogs.com/muyuge/p/6333525.html
Copyright © 2020-2023  润新知