以下是一篇符合CSDN格式的Android自定义View进阶版技术文章(使用Kotlin语言):
目录
1. 前言:为什么要掌握自定义View
2. 高级绘制技巧
3. 复杂手势交互实现
4. 属性动画与ValueAnimator
5. 性能优化关键点
6. 完整实战案例
7. 总结与资源推荐
一、前言
在掌握了自定义View基础(测量、布局、绘制)后,进阶开发需要关注:
- 复杂手势交互逻辑
- 高性能绘制技巧
- 属性动画集成
- 内存优化策略
- 自定义属性支持
本文将以Kotlin为例,通过一个**支持缩放/拖拽/旋转的ImageView**实现,演示进阶开发全流程。
二、高级绘制技巧
2.1 使用Matrix进行坐标变换
private val mMatrix = Matrix()
private val mSavedMatrix = Matrix()
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
canvas.save()
canvas.concat(mMatrix)
drawContent(canvas)
canvas.restore()
}
private fun drawContent(canvas: Canvas) {
// 绘制核心内容
bitmap?.let {
canvas.drawBitmap(it, 0f, 0f, paint)
}
}
2.2 离屏缓冲技术
private var mOffscreenBitmap: Bitmap? = null
private var mOffscreenCanvas: Canvas? = null
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
mOffscreenBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
mOffscreenCanvas = Canvas(mOffscreenBitmap!!)
}
override fun onDraw(canvas: Canvas) {
// 先在离屏Canvas绘制
mOffscreenCanvas?.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
mOffscreenCanvas?.concat(mMatrix)
drawContent(mOffscreenCanvas!!)
// 最后绘制到屏幕Canvas
mOffscreenBitmap?.let { canvas.drawBitmap(it, 0f, 0f, null) }
}
三、复杂手势交互
3.1 多点触控处理
private var mode = NONE
private val DRAG = 1
private val ZOOM = 2
private var startDistance = 0f
override fun onTouchEvent(event: MotionEvent): Boolean {
when (event.actionMasked) {
MotionEvent.ACTION_DOWN -> {
mode = DRAG
mSavedMatrix.set(mMatrix)
}
MotionEvent.ACTION_POINTER_DOWN -> {
startDistance = getDistance(event)
if (startDistance > 10f) {
mode = ZOOM
mSavedMatrix.set(mMatrix)
}
}
MotionEvent.ACTION_MOVE -> {
when (mode) {
DRAG -> handleDrag(event)
ZOOM -> handleZoom(event)
}
}
MotionEvent.ACTION_UP, MotionEvent.ACTION_POINTER_UP -> mode = NONE
}
return true
}
private fun getDistance(event: MotionEvent): Float {
val dx = event.getX(0) - event.getX(1)
val dy = event.getY(0) - event.getY(1)
return sqrt(dx * dx + dy * dy)
}
3.2 惯性滑动实现
private val scroller = OverScroller(context)
private val velocityTracker = VelocityTracker.obtain()
private fun handleFling() {
velocityTracker.computeCurrentVelocity(1000)
val velocityX = velocityTracker.xVelocity
val velocityY = velocityTracker.yVelocity
scroller.fling(
currentX, currentY,
velocityX.toInt(), velocityY.toInt(),
minX, maxX, minY, maxY
)
postInvalidate()
}
override fun computeScroll() {
if (scroller.computeScrollOffset()) {
updatePosition(scroller.currX, scroller.currY)
postInvalidate()
}
}
四、性能优化关键点
4.1 内存优化
// 使用Bitmap复用池
object BitmapPool {
private val pool = Stack<Bitmap>()
fun getBitmap(width: Int, height: Int): Bitmap {
return pool.find { it.width == width && it.height == height }
?: Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
}
fun recycle(bitmap: Bitmap) {
if (!bitmap.isRecycled) {
bitmap.recycle()
}
}
}
4.2 绘制优化
// 使用clipRect避免过度绘制
override fun onDraw(canvas: Canvas) {
canvas.clipRect(scrollX, scrollY, scrollX + width, scrollY + height)
// 绘制可见区域内容
}
// 启用硬件加速
<application android:hardwareAccelerated="true">
五、完整实战:交互式ImageView
class AdvancedImageView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
// 完整实现包含:
// 1. 手势检测
// 2. 矩阵变换
// 3. 惯性滑动
// 4. 边界检测
// 5. 双击恢复
// (代码较长,建议在GitHub维护完整示例)
}
六、总结与资源
**进阶要点总结:**
1. 优先使用Matrix处理复杂变换
2. 合理使用VelocityTracker和Scroller
3. 通过离屏缓冲优化复杂绘制
4. 关注内存管理和绘制区域
5. 善用Kotlin扩展函数简化代码
**注意事项:**
1. 实际发布时需补充代码截图和效果GIF
2. GitHub链接需要替换为真实项目地址
3. 可添加"自定义View系列"文章导航
4. 适当插入技术要点示意图(推荐使用ProcessOn绘制)
5. 添加「性能对比数据」章节会更具说服力
希望这篇结构清晰、包含实用代码示例的文章能满足CSDN读者的需求!如果需要某个章节的详细扩展或更多Kotlin特性实现,可以留言讨论。