时间:2021-05-19
一、前言
添加文本,也是属于 一个比较简单的功能,在第二篇的时候,添加了橡皮擦,在橡皮擦里面通过一个模式的形式进行画笔的判断,当然文本也是如此,添加一个文本模式,在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。 在弹窗消失的时候添加到画笔列表,然后进行重绘。 在这里有三点注意点
在触摸的时候,进行显示。 移动的时候不用操作,手指起来的时候也不用操作
@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) }以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
本文实例总结了Android开发之TextView控件用法。分享给大家供大家参考,具体如下:TextView控件可以向用户展现文本信息,我们可以设置该文本信息是
本文总结分析了Android编程开发之EditText中inputType属性。分享给大家供大家参考,具体如下:android1.5以后添加了软件虚拟键盘的功能
本文实例讲述了Android编程开发之TextView文字显示和修改方法。分享给大家供大家参考,具体如下:一.新建一个Activity和Layout首先在lay
本文实例为大家分享了Android画画板展示的具体代码,供大家参考,具体内容如下main.xml布局main布局/*画板canvas画板paint手势识别器整体
本文实例讲述了Android开发之ViewSwitcher用法。分享给大家供大家参考,具体如下:android.widget.ViewSwitcher是View