概述

上一篇文章我们对自定义控件进行了一个大体的知识介绍。今天就来学习自定义一个简单的写字板控件。

先来看看效果图

就是简单的根据手指写下的轨迹去画出内容

实现

在上一篇文章里提到了android官方给出的自定义控件需要考虑以下几点:

  1. 创建View
  2. 处理View的布局
  3. 绘制View
  4. 与用户进行交互
  5. 优化已定义的View

就按照这个步骤来完成今天的自定义控件

1、创建View

上篇提到创建View这一步的时候要考虑的就是很简单的自定义属性的声明、使用。

今天的控件可以有一些什么自定义属性呢?要实现写字板,其实就是三个东西:写字板的颜色、笔的颜色、笔的粗细。所以接下来自定义属性。

<?xml version="1.0" encoding="utf-8"?>
<resources> <declare-styleable name="WritingBoardView">
<attr name="boardBackground" format="color"></attr> <!--画板颜色-->
<attr name="paintColor" format="color"></attr> <!--画笔颜色-->
<attr name="paintWidth" format="dimension"></attr> <!--画笔宽度-->
</declare-styleable>
</resources>

定义了就是为了要使用

<?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"
xmlns:custom="http://schemas.android.com/apk/res-auto"
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.qiangyu.test.writingboardview.MainActivity"> <com.qiangyu.test.writingboardview.view.WritingBoardView
android:layout_width="match_parent"
android:layout_height="match_parent"
custom:paintColor="@color/colorAccent"
custom:boardBackground="@color/colorPrimary"
custom:paintWidth="3dp"/>
</RelativeLayout>

简单的设置了boardBackground、paintWidth和paintColor属性

使用这里只需要注意命名空间,android提供给我们的用android,我们可以自定义我们属性的命名空间 
写法为:xmlns:你取的名=”http://schemas.android.com/apk/res-auto”,这里的res-auto可以换成你控件的包名

在XML布局文件中设置的属性要在自定义属性中获取到,所以我们必须实现带有Context, AttributeSet的构造方法

   private int mBoardBackground;//画板颜色
private int mPaintColor;//画笔颜色
private int mPaintWidth;//画笔宽度
private Path mPath;
private Paint mPaint;//画笔 public WritingBoardView(Context context) {
this(context,null);
} public WritingBoardView(Context context, AttributeSet attrs) {
this(context, attrs,0);
} public WritingBoardView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context,attrs);
} private void init(Context context,AttributeSet attrs) {
TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.WritingBoardView);
mBoardBackground = a.getColor(R.styleable.WritingBoardView_boardBackground,Color.WHITE);
mPaintColor = a.getColor(R.styleable.WritingBoardView_paintColor,Color.BLUE);
mPaintWidth = a.getDimensionPixelSize(R.styleable.WritingBoardView_paintWidth,
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,5,getResources().getDisplayMetrics()));
a.recycle();
mPaint = new Paint();
mPath = new Path();
setBackgroundColor(mBoardBackground);
mPaint.setColor(mPaintColor);
mPaint.setStrokeWidth(mPaintWidth);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setAntiAlias(true);
}

上面代码确保了每个构造方法最终都调用了第三个构造方法里的init(context,attrs) 方法来获取自定义属性和初始化一些信息

通过固定的写法、简单的获取到自定义属性,并且给当前view设置背景、为Paint设置了样式和颜色。完成写字板很重要的就是这里的Path类。

先来介绍一下Path类

看构造方法的注释

/**
* The Path class encapsulates compound (multiple contour) geometric paths
* consisting of straight line segments, quadratic curves, and cubic curves.
* It can be drawn with canvas.drawPath(path, paint), either filled or stroked
* (based on the paint's Style), or it can be used for clipping or to draw
* text on a path.
*/
public class Path { ... }

大体就是说Path封装了由了直线和各种曲线组成几何图形信息。我们可以调用canvas通过drawPath方法来画一些东西。 
我们最终的draw就是需要用到drawPath

Path里包含了很多设置几何图形的方法如addRect、addArc。 
今天重点说用到的两个方法:

  /**
* Set the beginning of the next contour to the point (x,y).
*
* @param x The x-coordinate of the start of a new contour
* @param y The y-coordinate of the start of a new contour
*/
public void moveTo(float x, float y) {
native_moveTo(mNativePath, x, y);
}

moveTo方法就是设置下一个连线或者图形最开始的位置。

/**
* Add a line from the last point to the specified point (x,y).
* If no moveTo() call has been made for this contour, the first point is
* automatically set to (0,0).
*
* @param x The x-coordinate of the end of a line
* @param y The y-coordinate of the end of a line
*/
public void lineTo(float x, float y) {
isSimplePath = false;
native_lineTo(mNativePath, x, y);
}

lineTo方法简单的添加一条上一个点到当前点的线。

有了这两个方法我们就可以实线写字板了

2、处理View的布局

由于这个自定义控件本身就需要一块内容当写字板,所以就不用特别的布局处理了,只是在mode为UNSPECIFIED的时候可能会导致布局显示不出来。

在这里就不进行特殊处理了。

3、绘制View、与用户进行交互

由于该控件本身就需要交互才产生效果,所以之前的两步放在一起考虑了。

上面说到过Canvas有一个drawPath方法。drawPath最后绘制出来什么样其实是看Path里包含的信息。

我们要实现实时显示手写的内容,只需要在滑动的时候获取的坐标通过Path的lineTo方法将线一点一点的连起来。

当手指抬起再落下的时候应该又是一条新的线,所以在落下的时候我们需要调用moveTo方法来为下一条轨迹设置一个起点。

 @Override
public boolean onTouchEvent(MotionEvent event) {
float touchX = event.getX();
float touchY = event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
mPath.moveTo(touchX,touchY);//重新设置即将出现的线的起点
break;
case MotionEvent.ACTION_MOVE:
mPath.lineTo(touchX,touchY);//连线
break;
case MotionEvent.ACTION_UP:
break;
}
invalidate();//通知系统重绘
return true;//要处理当前事件
}

在onTouch中return true表示要处理当前事件。并且在每一次操作调用invalidate来绘制界面,我们的onDraw 方法只需要简单的调用drawPath就可以了

 @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(mPath,mPaint);
}

总结

其实就是通过手指的触摸事件来控制轨迹的改变,按照固定的模式,一个简单的自定义控件就大功告成啦!

一个简单的写字板就基本完成了,当然你感兴趣可以扩展一下,加上在运行时改变画笔的颜色、画板的颜色。添加字体擦除去的功能。

最后别忘记给我点个赞评论支持下!哈哈

源码下载

一起来学习Android自定义控件2-简单的写字板控件的更多相关文章

  1. Android自己定义控件2-简单的写字板控件

    概述 上一篇文章我们对自己定义控件进行了一个大体的知识介绍. 今天就来学习自己定义一个简单的写字板控件. 先来看看效果图 就是简单的依据手指写下的轨迹去画出内容 实现 在上一篇文章里提到了androi ...

  2. Android自定义控件View(三)组合控件

    不少人应该见过小米手机系统音量控制UI,一个圆形带动画效果的音量加减UI,效果很好看.它是怎么实现的呢?这篇博客来揭开它的神秘面纱.先上效果图 相信很多人都知道Android自定义控件的三种方式,An ...

  3. Android自定义控件View(二)继承控件

    在前一篇博客中学习了Android自定义控件View的流程步骤和注意点,不了解的童鞋可以参考Android自定义控件View(一).这一节开始学习自定义控件View(二)之继承系统已有的控件.我们来自 ...

  4. Android自定义控件:自适应大小的文本控件

    需求 自适应大小的文本: 效果图: 项目开发中,开发人员根据UI人员提供的一套尺寸,布局了一些带文本的页面, 往往会少考虑一些数据极限的问题,造成机型屏幕适配问题. 例如: 文本(或数值)长度可变,如 ...

  5. android 自定义控件之NetWorkImageView 处理listview等控件中的图片加载乱序问题

    0.调用: BaseAdapter中设置方法 holder.iv.loadImage(url); adapter_xxx.xml 中 控件需要用 xxx.NetWorkImageView 1 NetW ...

  6. 一起来学习Android自定义控件1

    概述 Android已经为我们提供了大量的View供我们使用,但是可能有时候这些组件不能满足我们的需求,这时候就需要自定义控件了.自定义控件对于初学者总是感觉是一种复杂的技术.因为里面涉及到的知识点会 ...

  7. Android开发学习之路--UI之自定义布局和控件

    新的一年已经开始了,今天已经是初二了,两天没有学习了,还是要来继续学习下.一般手机的title都是actionbar,就像iphone一样可以后退,可以编辑.这里自定义布局就来实现下这个功能,首先准备 ...

  8. (转)sl简单自定义win窗体控件

    sl简单自定义win窗体控件      相信大家接触过不少win窗体控件ChildWin子窗口就的sl自带的一个  而且网上也有很多类似的控件,而今天我和大家分享下自己制作个win窗体控件,希望对初学 ...

  9. WPF教程十一:简单了解并使用控件模板

    WPF教程十一:简单了解并使用控件模板 这一章梳理控件模板,每个WPF控件都设计成无外观的,但是行为设计上是不允许改变的,比如使用Button的控件时,按钮提供了能被点击的内容,那么自由的改变控件外观 ...

随机推荐

  1. Android 开源框架Universal-Image-Loader完全解析(一)--- 基本介绍及使用

    转载博客:http://blog.csdn.net/xiaanming/article/details/26810303 大家好!差不多两个来月没有写文章了,前段时间也是在忙换工作的事,准备笔试面试什 ...

  2. angularjs与jquery特效slidetoggle结合

    之前使用jquery的slidetoggle方法,可以轻易的实现元素的收缩展开:使用angularjs后,没有找到相关的方法,通过多方面查资料,自己写了个demo,展示slidetoggle的angu ...

  3. Deadlock Detecting--转

    /* Java Threads, 3rd Edition By Scott Oaks, Henry Wong 3rd Edition September 2004 ISBN: 0-596-00782- ...

  4. 站在巨人的肩膀上---重新自定义 android- ExpandableListView 收缩类,实现列表的可收缩扩展

    距离上次更新博客,时隔略长,诸事繁琐,赶在去广州答辩之前,分享下安卓 android 中的一个 列表收缩 类---ExpandableListView 先上效果图: 如果想直接看实现此页面的代码请下滑 ...

  5. js 把数字转成2 ,8,16进制的方法

    直接上代码 <!DOCTYPE html> <html> <body> <script> var myNumber = 128; document.wr ...

  6. 深入seajs源码系列三

    入口方法 每个程序都有个入口方法,类似于c的main函数,seajs也不例外.系列一的demo在首页使用了seajs.use(),这便是入口方法.入口方法可以接受2个参数,第一个参数为模块名称,第二个 ...

  7. C#获取图片的后缀名

    最近在学习过程中遇到一个问题,就是如何获取图片的格式,对于一张知道全路径的照片,如果其路径包含后缀名的话,要取得后缀名,只需要一行代码即可: var ext = System.IO.Path.GetE ...

  8. mysql 日期函数总结

    1.0 格式化:DATE_FORMAT() 函数用于以不同的格式显示日期/时间数据. 语法 DATE_FORMAT(date,format) date 参数是合法的日期.format 规定日期/时间的 ...

  9. Win 10 UWP开发系列:设置AppBarButton的图标

    在WP8以前,页面最下面的四个小圆按钮是不支持绑定的,WP8.1 RT之后,系统按钮升级成了AppBarButton,并且支持绑定了.在Win10 UWP开发中,按钮的样式发生了变化,外面的圆圈没有了 ...

  10. 重温Bootstrap

    预热 ★ 学习要点 1. 理解其GridSystem(栅格排版): 2. 熟悉其所提供的各种CSS样式及显示效果: 3. 知道提供了哪些直接可用的UI组件,以及如何使用JavaScript去调整其交互 ...