实现效果类似于: http://thenewcode.com/819/A-Before-And-After-Image-Comparison-Slide-Control-in-HTML5
实际显示效果:
![](https://img.haomeiwen.com/i13651212/56ec397e9ba00e4b.png)
源码:
class ComparisonImageView : View {
private val mImageViewA by lazy {
ImageView(context).apply {
setImageResource(R.drawable.t1)
scaleType = ImageView.ScaleType.CENTER_CROP
}
}
private val mImageViewB by lazy {
ImageView(context).apply {
setImageResource(R.drawable.t2)
scaleType = ImageView.ScaleType.CENTER_CROP
}
}
private val mDrawableBar by lazy { resources.getDrawable(R.drawable.ic_hd) }
private val mDrawableLine by lazy { resources.getDrawable(R.drawable.shape_vertical_line_gradient) }
private val lineHalfWidth by lazy { 1.dpToPx() }
private val dp12 by lazy { 12f.dpToPx() }
private val dp34 by lazy { 34f.dpToPx() }
private val dp64 by lazy { 64f.dpToPx() }
private val dp74 by lazy { 114f.dpToPx() }
var drawMode = 0
var srcText: String = "美图前"
var tarText: String = "美图后"
var textBottomDp = dp12
constructor(context: Context?) : super(context)
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
constructor(
context: Context?,
attrs: AttributeSet?,
defStyleAttr: Int,
defStyleRes: Int
) : super(context, attrs, defStyleAttr, defStyleRes)
private val mTextPain by lazy {
TextPaint().apply {
color = Color.parseColor("#FFFFFF")
textSize = 14f.spToPx()
strokeWidth = 0.9F
style = Paint.Style.FILL_AND_STROKE
isAntiAlias = true
setShadowLayer(3f, 0f, 1f.dpToPx(), Color.parseColor("#80000000"))
}
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
if (drawMode == 1) {
mImageViewB.draw(canvas)
return
}
mImageViewB.draw(canvas)
canvas.save()
canvas.clipRect(getLineValue(), 0, width, height)
mImageViewA.draw(canvas)
canvas.restore()
//中线 start
canvas.save()
canvas.clipRect(getLineValue() - lineHalfWidth, 0, getLineValue() + lineHalfWidth, height)
mDrawableLine.setBounds(0, 0, width, height)
mDrawableLine.draw(canvas)
canvas.restore()
//中线 end
//绘制文字-左边
if (srcText.isNotBlank() && linePer != 0f) {
canvas.drawText(srcText, getLineValue() + dp12, height - textBottomDp, mTextPain)
}
//绘制文字-右边
if (tarText.isNotBlank() && linePer != 1f) {
canvas.drawText(
tarText,
getLineValue() - mTextPain.measureText(srcText) - dp12,
height - textBottomDp,
mTextPain
)
}
canvas.save()
canvas.translate(getLineValue() - dp64 / 2, height - dp64 - dp34)
mDrawableBar.setBounds(0, 0, dp64.toInt(), dp64.toInt())
mDrawableBar.draw(canvas)
canvas.restore()
}
/**
* 0 默认 左右滑动对比
* 1 全部显示处理后
*/
fun setCompareMode(mode: Int) {
if (drawMode == mode) return
drawMode = mode
postInvalidate()
}
var linePer = 0.5f
private fun getLineValue(): Int {
return (width * linePer).toInt()
}
/**
* 播放对比效果
* @param start 起始值
* @param end 结束值
* @param duration 动画时间
*/
fun autoPlayDrawImage(start: Float, end: Float, duration: Long = 1000) {
postDelayed({
val va = ValueAnimator.ofFloat(start, end)
va.interpolator = LinearInterpolator()
va.addUpdateListener {
linePer = it.animatedValue as Float
postInvalidate()
}
va.duration = duration
va.start()
}, 150)
}
var startX = 0f
override fun onTouchEvent(event: MotionEvent?): Boolean {
event ?: return false
when (event.action) {
MotionEvent.ACTION_DOWN -> {
startX = event.rawX
val lx = getLineValue()
return (startX > (lx - dp74)) && (startX < (lx + dp74))
}
MotionEvent.ACTION_MOVE -> {
val movx = event.rawX
val dir = movx - startX
val lx = getLineValue()
linePer = (lx + dir) / width
if (linePer < 0) {
linePer = 0f
} else if (linePer >= 1) {
linePer = 1f
}
startX = movx
invalidate()
return true
}
MotionEvent.ACTION_UP -> {
}
}
return true
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
mImageViewA.measure(widthMeasureSpec, heightMeasureSpec)
mImageViewB.measure(widthMeasureSpec, heightMeasureSpec)
}
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
super.onLayout(changed, left, top, right, bottom)
mImageViewA.layout(left, top, right, bottom)
mImageViewB.layout(left, top, right, bottom)
}
internal inline fun String.debugLog() {
if (BuildConfig.DEBUG) {
Log.d(ComparisonImageView::class.java.simpleName, this)
}
}
}
如果本文对你有帮助就点个赞支持下吧~~~
网友评论