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

时间: 2024-10-10 08:02:14

手把手教你打造一个心电图效果View Android自定义View的相关文章

手把手教你打造一个Material Design风格的App(二)

--接上文. 3.1添加ToolBar(ActionBar) 添加ToolBar非常简单,你需要做的仅仅是为toolbar创建一个单独的layout布局,如果你想在哪里展示toolbar,只要在对应布局里将toolbar的布局文件include进来即可. (8)在res-->layout文件夹下创建一个名为toolbar.xml的文件,然后在里面添加一个android.support.v7.widget.Toolbar元素,这样就创建了一个具有特定高度和主题的toolbar. toolbar.x

手把手教你打造一个Material Design风格的App(三)

--接上文. 3.2添加抽屉导航 添加导航抽屉跟Android 5.0之前是一样的,只是以前我们使用ListView来作为菜单容器,现在我们则使用Material Design风格的RecyclerView. (14)在你工程的java文件夹中,创建3个名为activity.adapter.model的包,将MainActivity.java移到activtiy包中,这样做使得你的代码可以很好地组织和管理. (15)打开位于app模块下的build.gradle文件并添加如下依赖.添加完依赖之后

手把手教你打造一个Material Design风格的App(一)

你应该听说过Android的Material Design,它是在Android 5.0(Lollipop)版本引入的.在Material Design中还引入了很多新东西,比如Material Theme,新的小部件,自定义的阴影,矢量图片及自定义动画等.如果你之前没有用过Material Design,那么本文将是一个很好的入门教程. 在这篇教程中,我们将会学习Material Design开发的基本步骤,即编写自定义的主题以及使用RecyclerView来实现抽屉导航. 通过下面的两个链接

手把手带你做一个超炫酷loading成功动画view Android自定义view

写在前面: 本篇可能是手把手自定义view系列最后一篇了,实际上我也是一周前才开始真正接触自定义view,通过这一周的练习,基本上已经熟练自定义view,能够应对一般的view需要,那么就以本篇来结尾告一段落,搞完毕设的开题报告后去学习新的内容. 有人对我说类似的效果网上已经有了呀,直接拿来就可以用,为什么还要写.我个人的观点是:第三方控件多数不能完全满足UI的要求,如果需要修改,那么必须理解他的实现,所以很有必要自己去写一款出来,成为程序的创造者,而不单单是使用者.所以,写一写已经实现的效果,

手把手带你画一个漂亮蜂窝view Android自定义view

上一篇做了一个水波纹view  不知道大家有没有动手试试呢点击打开链接 这个效果做起来好像没什么意义,如果不加监听回调 图片就能直接替代.写这篇博客的目的是锻炼一下思维能力,以更好的面多各种自定义view需求. 转载请注明出处:http://blog.csdn.net/wingichoy/article/details/50554058 本文是和代码同步写的.也就是说在写文章的时候才敲的代码.这样会显得文章有些许混乱.但是我想这样记录下来,一个自定义view的真正的制作过程,是一点一点,一步步跟

手把手教你打造一个Material Design风格的App(四)

--接上文. 3.3实现导航抽屉菜单项的选择 尽管导航抽屉已经实现了,但是你会发现选择抽屉列表项并没有反应,这是因为我们还没有实现RecycleView items的点击监听. 因为我们在导航抽屉里有3个菜单(Home,Friends & Messages),所以需要为每一个菜单项创建一个独立的Fragment. (24)在res-->layout里面,创建一个名为fragment_home.xml的文件并添加如下代码. fragment_home.xml <RelativeLayou

Android自定义View——实现理财类APP七日年化收益折线图效果

这段时间的自定义View学习,学会了绘制柱状图.绘制折线图.绘制进度控件,那我们今天就来聊聊另外一种自定义的View,这就是我们常见的七日年化收益折线图效果.先看看长什么样. 这就是效果图了,元素相对而言还是比较多的,这里有线.柱状图.文字.折线.点等等.看起来好像很复杂,但是呢,只要一步一步的实现,那还是可以达到这种效果的,之前我们说过的, 自定义View,就像是在photo shop里面画图,想要什么就画什么,我们可以有很多的画笔工具,也可以有很多的图层. 先看看我们这一次用到哪些变量. p

Android自定义View效果目录

1.绚丽的loading动效的实现 2.Android自定义View:进度条+冒泡文本 3.Android雷达图(蜘蛛网图) 4.Android文本闪烁 5.Android绘制圆形进度条 6.重写TextView,实现圆形背景,文本居中显示

Android 自定义View合集

自定义控件学习 https://github.com/GcsSloop/AndroidNote/tree/master/CustomView 小良自定义控件合集 https://github.com/Mr-XiaoLiang 自定义控件三部曲 http://blog.csdn.net/harvic880925?viewmode=contents Android 从0开始自定义控件之View基础知识与概念 http://blog.csdn.net/airsaid/article/details/5