Android 화판 개발 에 텍스트 추가
텍스트 를 추가 하 는 것 도 비교적 간단 한 기능 입 니 다.두 번 째 편 에 서 는 지우 개 를 추가 하고 지우개 에 하나의 패턴 으로 붓 을 그 리 는 판단 을 합 니 다.물론 텍스트 도 마찬가지 입 니 다.텍스트 모드 를 추가 하고 onTouch Down 에 서 는 PopupWindow 를 연주 하고 텍스트 를 입력 한 다음 에 PopupWindow 가 사라 질 때.static Layout 를 이용 하여 캔버스 에 그리 면 됩 니 다.물론 주의해 야 할 부분도 있 습 니 다.
다음 단계 로 넘 어가 도록 하 겠 습 니 다.
실현
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 형식 수정Static Layout 는 편집 할 수 없 는 텍스트 레이아웃 을 위 한 클래스 입 니 다.이것 은 레이아웃 이 완성 되면 텍스트 내용 을 바 꿀 수 없다 는 것 을 의미 합 니 다.단순히 TextView 를 사용 하여 정적 텍스트 를 보 여줄 때 만 든 것 은 Static Layout 입 니 다.api 25,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);
우리 화판 의 그리 기 문자 도 이 Static Layout 를 사 용 했 습 니 다.세 가지 구조 방법 이 있 습 니 다.우 리 는 최소한 그것 을 사용 하면 됩 니 다.
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 축의 오프셋 을 추가 한 다음 에 그 릴 때 static Layout 를 이용 하여 그 렸 습 니 다.
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 탄창 처리다음은 팝 업 윈도 우 를 설정 하여 텍스트 입력 을 합 니 다.팝 업 창 에 있 는 컨트롤 은 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)
}
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Bitrise에서 배포 어플리케이션 설정 테스트하기이 글은 Bitrise 광고 달력의 23일째 글입니다. 자체 또는 당사 등에서 Bitrise 구축 서비스를 사용합니다. 그나저나 며칠 전 Bitrise User Group Meetup #3에서 아래 슬라이드를 발표했...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.