一、前言
創(chuàng)新互聯(lián)專業(yè)為企業(yè)提供巴州網(wǎng)站建設(shè)、巴州做網(wǎng)站、巴州網(wǎng)站設(shè)計(jì)、巴州網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)與制作、巴州企業(yè)網(wǎng)站模板建站服務(wù),十余年巴州做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。
添加文本,也是屬于 一個(gè)比較簡單的功能,在第二篇的時(shí)候,添加了橡皮擦,在橡皮擦里面通過一個(gè)模式的形式進(jìn)行畫筆的判斷,當(dāng)然文本也是如此,添加一個(gè)文本模式,在onTouchDown的時(shí)候,彈出PopupWindow,輸入文本,然后PopupWindow消失的時(shí)候,利用staticLayout繪制到畫布上即可。當(dāng)然也有些需要注意的地方

下面一步步來實(shí)現(xiàn)
二、實(shí)現(xiàn)
2.1 添加文本模式
例如橡皮擦那樣,添加多一個(gè)文本模式,然后setModel的時(shí)候,需要把畫筆的樣式修改為FILL,如果是STROKE進(jìn)行文字繪制會變成空心文字。
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
/**
* 設(shè)置畫筆模式
*/
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 是一個(gè)為不可編輯的文本布局的類,這意味著一旦布局完成,文本內(nèi)容就不可以改變。在單純地使用TextView來展示靜態(tài)文本的時(shí)候,創(chuàng)建的就是 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);我們畫板的繪制文字也是用到了這個(gè)StaticLayout,它有三個(gè)構(gòu)造方法,我們用最少那個(gè)即可:
public StaticLayout(CharSequence source, //字符串 TextPaint paint, //畫筆對象 int width, //layout的寬度,字符串超出寬度時(shí)自動換行。 Layout.Alignment align, //layout的對其方式,有ALIGN_CENTER, ALIGN_NORMAL, ALIGN_OPPOSITE 三種。 float spacingmult, //相對行間距,相對字體大小,1.5f表示行間距為1.5倍的字體高度。 float spacingadd, //在基礎(chǔ)行距上添加多少 boolean includepad) //文本頂部和底部是否留白
所以,bean類在之前的基礎(chǔ)上,添加了文本、寬度、xy軸的偏移,然后繪制的時(shí)候,利用staticLayout進(jìn)行了繪制。
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)){
//調(diào)節(jié)畫布起始坐標(biāo)進(jìn)行繪制
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)
//恢復(fù)畫布坐標(biāo)
canvas.translate(-mOffX,-mOffY)
}
}
else -> {
canvas.drawPath(mPath,mPaint)
}
}
}
fun getMode():Long = mMode
}2.3 彈窗處理
接下來,設(shè)置一個(gè)彈框PopupWindow進(jìn)行文本的輸入,彈窗里面的控件就是一個(gè)EditText。 在彈窗消失的時(shí)候添加到畫筆列表,然后進(jìn)行重繪。 在這里有三點(diǎn)注意點(diǎn)
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()
//自動彈出軟鍵盤,會導(dǎo)致布局變化,重測量、繪制
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)
}在觸摸的時(shí)候,進(jìn)行顯示。 移動的時(shí)候不用操作,手指起來的時(shí)候也不用操作
@SuppressLint("ClickableViewAccessibility")
override fun onTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN -> { //手指按下的時(shí)候
//記錄上次觸摸的坐標(biāo),注意ACTION_DOWN方法只會執(zhí)行一次
preX = event.x
preY = event.y
when (mMode) {
EDIT_MODE_TEXT -> {
//彈出popupWidnwo輸入text
showTextPopup()
//文字在隱藏的時(shí)候添加到list
}
else -> {
//將起始點(diǎn)移動到當(dāng)前坐標(biāo)
mPath.moveTo(event.x, event.y)
mPaintedList.add(PaintBean(Paint(mPaint), Path(mPath)))
}
}
}
MotionEvent.ACTION_MOVE -> { //手指移動的時(shí)候
when (mMode) {
EDIT_MODE_TEXT -> {
}
else -> {
//繪制圓滑曲線,即貝塞爾曲線,貝塞爾曲線這個(gè)知識自行了解
mPaintedList.get(mPaintedList.size - 1).mPath?.quadTo(preX, preY, event.x, event.y)
preX = event.x
preY = event.y
//重新繪制,會調(diào)用onDraw方法
invalidate()
}
}
}
MotionEvent.ACTION_UP -> {}
}
return true
}因?yàn)槔L制在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!!)
}
//繪制固化的內(nèi)容到緩存Canvas
mBufferCanvas?.drawBitmap(mHoldBitmap, 0f, 0f, null)
//繪制記錄的畫筆
for (paint in mPaintedList) {
paint.draw(mBufferCanvas!!)
}
//畫出緩存bitmap的內(nèi)容
canvas.drawBitmap(mBufferBitmap, 0f, 0f, null)
}以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。
當(dāng)前文章:Android畫板開發(fā)之添加文本文字
文章出自:http://www.chinadenli.net/article4/ishdoe.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站營銷、面包屑導(dǎo)航、小程序開發(fā)、網(wǎng)站收錄、網(wǎng)站內(nèi)鏈、網(wǎng)站改版
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)