Android自定义控件实现简单写字板功能

 更新时间:2016年04月14日 08:44:34   作者:So,Cool  
这篇文章主要介绍了Android自定义控件实现简单写字板功能的相关资料,需要的朋友可以参考下

先来看看效果图

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

一、实现

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

创建View

处理View的布局

绘制View

与用户进行交互

优化已定义的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);
  }

总结

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

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

相关文章

  • 自定义View之kotlin绘制折线图实例教程

    自定义View之kotlin绘制折线图实例教程

    折线图是我们在开发中经常会遇到的一个需求,下面这篇文章主要给大家介绍了关于自定义View之kotlin绘制折线图的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧
    2018-09-09
  • Android  View移动的六种方法小结

    Android View移动的六种方法小结

    在android开发中,经常会遇到一个view需要它能够支持滑动的需求。下面通过本篇文章给大家介绍android view移动的六种方法,对android view移动相关知识感兴趣的朋友一起学习吧
    2015-12-12
  • Android实现渐变启动页和带有指示器的引导页

    Android实现渐变启动页和带有指示器的引导页

    这篇文章主要为大家详细介绍了Android实现渐变启动页和带有指示器的引导页,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-09-09
  • 支付宝咻一咻怎么用 Android帮你实现咻一咻

    支付宝咻一咻怎么用 Android帮你实现咻一咻

    Android帮你实现咻一咻,这篇文章主要为大家介绍了支付宝咻一咻的几种思路,感兴趣的朋友可以参考一下
    2016-02-02
  • Android中handler使用浅析

    Android中handler使用浅析

    本文主要介绍了Android中handler的使用,具有很好的参考价值。下面跟着小编一起来看下吧
    2017-03-03
  • Android 手势 正则匹配图片实例代码

    Android 手势 正则匹配图片实例代码

    这篇文章主要介绍了Android 手势 正则匹配图片实例代码,需要的朋友可以参考下
    2017-07-07
  • ExpandableListView实现简单二级列表

    ExpandableListView实现简单二级列表

    这篇文章主要为大家详细介绍了ExpandableListView实现简单二级列表,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-11-11
  • Android开机自启动程序详解

    Android开机自启动程序详解

    本篇文章是对Android开机自启动程序进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • Android SDK命令行工具Monkey参数及使用解析

    Android SDK命令行工具Monkey参数及使用解析

    这篇文章主要介绍了Android SDK命令行工具Monkey参,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值数及使用解析,需要的朋友可以参考下
    2020-10-10
  • Android BottomNavigationView与Fragment重建与重叠问题解决方法探索

    Android BottomNavigationView与Fragment重建与重叠问题解决方法探索

    这篇文章主要介绍了Android BottomNavigationView与Fragment重建与重叠问题解决,总的来说这并不是一道难题,那为什么要拿出这道题介绍?拿出这道题真正想要传达的是解题的思路,以及不断优化探寻最优解的过程。希望通过这道题能给你带来一种解题优化的思路
    2023-01-01

最新评论