当前位置: 移动技术网 > 移动技术>移动开发>Android > Android画板开发之添加文本文字

Android画板开发之添加文本文字

2019年07月31日  | 移动技术网移动技术  | 我要评论

一、前言

添加文本,也是属于 一个比较简单的功能,在第二篇的时候,添加了橡皮擦,在橡皮擦里面通过一个模式的形式进行画笔的判断,当然文本也是如此,添加一个文本模式,在ontouchdown的时候,弹出popupwindow,输入文本,然后popupwindow消失的时候,利用staticlayout绘制到画布上即可。当然也有些需要注意的地方

下面一步步来实现

二、实现

2.1 添加文本模式

例如橡皮擦那样,添加多一个文本模式,然后setmodel的时候,需要把画笔的样式修改为fill,如果是stroke进行文字绘制会变成空心文字。

companion object {
    const val edit_mode_pen = 0x1l    //画笔模式
    const val edit_mode_eraser = 0x2l  //橡皮擦模式
    const val edit_mode_text = 0x3l  //文字模式

  }

  @retention(annotationretention.source)
  @intdef(edit_mode_pen, edit_mode_eraser, edit_mode_text)
  annotation class editmode

  /**
   * 设置画笔模式
   */
  fun setmodel(@editmode model: long) {
    mmode = model
    when (model) {
      edit_mode_pen -> {
        //画线
        mpaint.xfermode = null
        mpaint.style = paint.style.stroke
      }
      edit_mode_eraser -> {
        mpaint.xfermode = porterduffxfermode(porterduff.mode.clear)

      }
      edit_mode_text -> {
        mpaint.style = paint.style.fill
      }
    }
  }

2.2 修改bean类型

staticlayout 是一个为不可编辑的文本布局的类,这意味着一旦布局完成,文本内容就不可以改变。在单纯地使用textview来展示静态文本的时候,创建的就是 staticlayout,在api25,textview源码6858行可以看到。

staticlayout.builder builder = staticlayout.builder.obtain(mhint, 0,
     mhint.length(), mtextpaint, hintwidth)
     .setalignment(alignment)
     .settextdirection(mtextdir)
     .setlinespacing(mspacingadd, mspacingmult)
     .setincludepad(mincludepad)
     .setbreakstrategy(mbreakstrategy)
     .sethyphenationfrequency(mhyphenationfrequency);

我们画板的绘制文字也是用到了这个staticlayout,它有三个构造方法,我们用最少那个即可:

public staticlayout(charsequence source, //字符串
   textpaint paint, //画笔对象
   int width,  //layout的宽度,字符串超出宽度时自动换行。
   layout.alignment align, //layout的对其方式,有align_center, align_normal, align_opposite 三种。
   float spacingmult,  //相对行间距,相对字体大小,1.5f表示行间距为1.5倍的字体高度。
   float spacingadd,  //在基础行距上添加多少
   boolean includepad)  //文本顶部和底部是否留白

所以,bean类在之前的基础上,添加了文本、宽度、xy轴的偏移,然后绘制的时候,利用staticlayout进行了绘制。

data class paintbean(
    var mpaint: paint,  //保存画笔
    var mpath: path?,     //保存路径
    var mtext: string,    //文本
    var mwidth: int,
    var moffx: float,
    var moffy: float,
    private @tptextview.editmode var mmode:long
) {

  constructor(mpaint: paint, mpath: path) : this(mpaint,mpath,"",0,0f,0f,tptextview.edit_mode_pen)

  /**
   * 撤销和反撤销之后 重新绘制
   * @param canvas 绘制的画布
   */
  fun draw(canvas: canvas){

    when(mmode){

      tptextview.edit_mode_text -> {

        if(!textutils.isempty(mtext)){
          //调节画布起始坐标进行绘制
          canvas.translate(moffx,moffy)
          //利用staticlayout生成文字,不然不能换行
          val staticlayout = staticlayout(mtext,mpaint as textpaint,mwidth, layout.alignment.align_normal, 1.0f, 0.0f, false)
          staticlayout.draw(canvas)
          //log.e("@@","长度:"+staticlayout.width)
          //canvas.drawtext(mtext,mtextoffx,mtextoffy,mpaint)
          //恢复画布坐标
          canvas.translate(-moffx,-moffy)

        }

      }
      else -> {
        canvas.drawpath(mpath,mpaint)
      }

    }

  }

  fun getmode():long = mmode

}

2.3 弹窗处理

接下来,设置一个弹框popupwindow进行文本的输入,弹窗里面的控件就是一个edittext。 在弹窗消失的时候添加到画笔列表,然后进行重绘。 在这里有三点注意点

  • 软键盘自动弹出
  • 编辑框显示在软键盘上面
  • 弹框显示的位置
  • 右边越界
private var mtextpopup: popupwindow? = null
private var mtextview: edittext? = null

  /**
   * 显示popup文本输入弹窗
   */
  private fun showtextpopup() {

    if (null == mtextpopup) {
      mtextview = edittext(context)
      mtextview?.hint = "文字"

      mtextpopup = popupwindow(mtextview,
          windowmanager.layoutparams.wrap_content, windowmanager.layoutparams.wrap_content,
          true)
      mtextpopup?.setondismisslistener {
        if (!textutils.isempty(mtextview?.text)) {
          //添加到列表
          mpaintedlist.add(
              paintbean(textpaint(mpaint), null, mtextview?.text.tostring(), (width - prex).toint(),prex,prey - mtextview!!.height / 2, edit_mode_text))

          invalidate()
        }
      }
      //让popup显示在软键盘上面
      mtextpopup?.softinputmode = windowmanager.layoutparams.soft_input_adjust_resize
    }

    mtextview?.requestfocus()

    //自动弹出软键盘,会导致布局变化,重测量、绘制
    val imm = context.getsystemservice(service.input_method_service) as inputmethodmanager
    imm.togglesoftinput(0, inputmethodmanager.hide_not_always)


    mtextpopup?.showatlocation(this, gravity.top and gravity.left, prex.toint(), prey.toint()+mtextview!!.height)

  }

在触摸的时候,进行显示。 移动的时候不用操作,手指起来的时候也不用操作

@suppresslint("clickableviewaccessibility")
  override fun ontouchevent(event: motionevent): boolean {

    when (event.action) {
      motionevent.action_down -> { //手指按下的时候
        //记录上次触摸的坐标,注意action_down方法只会执行一次
        prex = event.x
        prey = event.y
        when (mmode) {

          edit_mode_text -> {
            //弹出popupwidnwo输入text
            showtextpopup()
            //文字在隐藏的时候添加到list
          }
          else -> {
            //将起始点移动到当前坐标
            mpath.moveto(event.x, event.y)
            mpaintedlist.add(paintbean(paint(mpaint), path(mpath)))
          }
        }

      }
      motionevent.action_move -> { //手指移动的时候
        when (mmode) {
          edit_mode_text -> {

          }
          else -> {
            //绘制圆滑曲线,即贝塞尔曲线,贝塞尔曲线这个知识自行了解
            mpaintedlist.get(mpaintedlist.size - 1).mpath?.quadto(prex, prey, event.x, event.y)
            prex = event.x
            prey = event.y
            //重新绘制,会调用ondraw方法
            invalidate()
          }

        }
      }
      motionevent.action_up -> {}
    }

    return true
  }

因为绘制在bean类里面,所以view的ondraw方法还是以前那样,不需要变化:

@suppresslint("drawallocation")
  override fun ondraw(canvas: canvas) {
    super.ondraw(canvas)

    //超出缓存的就固化到缓存bitmap
    while (mpaintedlist.size > paint_recored_num) {
      val paint = mpaintedlist.removeat(0)
      paint.draw(mholdcanvas!!)
    }

    //绘制固化的内容到缓存canvas
    mbuffercanvas?.drawbitmap(mholdbitmap, 0f, 0f, null)

    //绘制记录的画笔
    for (paint in mpaintedlist) {
      paint.draw(mbuffercanvas!!)
    }

    //画出缓存bitmap的内容
    canvas.drawbitmap(mbufferbitmap, 0f, 0f, null)

  }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网