600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > android 卷轴动画效果 Android自定义View-卷轴

android 卷轴动画效果 Android自定义View-卷轴

时间:2018-11-16 18:55:52

相关推荐

android 卷轴动画效果 Android自定义View-卷轴

0.

今天是母亲节,谨以此文献和此程序给我的母亲,节日快乐。

话不多说,先看效果

image

附上git地址 Github

1.

想好再动笔,整个卷轴有左右卷轴柄,纸和文字组成,默认卷轴关闭,点击是张开,张开后点击就合上,打开时速度由快到慢。功能分析到这,思路也就很明确了,那就动笔吧。

2.

private var dis = 0 //每个卷轴到中心的距离

private var textColor = Color.BLACK //文字颜色

private var reelColor = Color.RED //卷轴柄的颜色

private var paperColor = Color.WHITE //纸的颜色

private var textSize = 20f //文字颜色

private var text = "" //卷轴上的文字

private var reelWidth = 40f //卷轴柄宽度

private var duration = 3000 //卷轴打开所需时间

private lateinit var disAnimator: ValueAnimator //操控卷轴打开进度

private var isExpand = false //卷轴是否处于打开状态

private var reelTopBarHeight = 20f //卷轴柄上端小木块的高度

private var lineOffset = 10f //纸上分割线的距离

这里要说到的是dis变量用来控制每个卷轴柄到中心的距离,也是控制纸宽度的参数,而disAnimator是用来控制dis的改变,同时为了控制卷轴打开速度和总时间的。

private fun initAnimator()

{

disAnimator = ValueAnimator.ofInt(0, duration / 1000)

disAnimator.duration = duration.toLong()

disAnimator.interpolator = AccelerateDecelerateInterpolator()

disAnimator.addUpdateListener {

dis = (it.animatedFraction * (width / 2 - reelWidth)).toInt()

postInvalidate()

}

}

disAnimator设置了的值的变化范围是从0到总时间/1000, 由dis = (it.animatedFraction * (width / 2 - reelWidth)).toInt()可知

0<=dis<=width/2-reelWidth

3.

实现文字随着纸张的展开逐渐显露出来的效果,这是这个控件的重点。首先看drawText方法

private fun drawText(canvas: Canvas)

{

textSize = Math.min(textSize, (height - reelTopBarHeight * 2 - lineOffset * 2))

paint.isFakeBoldText = true

paint.textSize=textSize

val centerX = width.toFloat() / 2

val centerY = height.toFloat() / 2

val rect = Rect()

paint.getTextBounds(text, 0, text.length, rect)

canvas.drawText(text, centerX - rect.width() / 2, centerY + rect.height() / 2, paint)

}

很简单,就是讲文字绘制在中心位置。

再看darwPaper方法

private fun drawPaper(canvas: Canvas)

{

val centerX = width.toFloat() / 2

val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)

val canvasTmp = Canvas(bitmap)

paint.color = paperColor

canvasTmp.drawRect(centerX - dis, reelTopBarHeight, centerX + dis, height - reelTopBarHeight, paint)

paint.color = Color.BLACK

paint.strokeWidth = 2f

canvas.drawBitmap(bitmap, 0f, 0f, paint)

}

绘制宽度随dis改变的纸。

要想实现文字只在已有宽度的纸上显示,那么我们就需要接住xfermode了,关于xfermode我就不仔细说了,不懂的请自行百度,这里我们采用DST_ATOP来实现这个功能,大家可能发现为什么drawPaper的时候生成了一个bitmap,和一个tempCanvas,最终绘制的是一个bitmap,那是因为为了控制它的透明区域不要太小,要让它足够覆盖到要和它结合绘制的文字内容,否则得到的结果很可能不是你想要的

看onDraw方法

override fun onDraw(canvas: Canvas?)

{

super.onDraw(canvas)

canvas?.let {

val count = it.saveLayer(null, null, Canvas.ALL_SAVE_FLAG) //设置离屏缓冲,不设置的话会有问题

paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_ATOP) //设置xfermode

drawText(it) //绘制文字

drawPaper(it) //绘制纸

paint.xfermode = null

drawPaerLines(it) //绘制纸上的线

it.restoreToCount(count) //恢复

drawReels(it) //绘制卷轴柄

}

}

4.

根据状态来判断点击时卷轴是打开还是收缩回去

override fun onTouchEvent(event: MotionEvent?): Boolean

{

when (event?.action)

{

MotionEvent.ACTION_DOWN ->

{

if (!disAnimator.isRunning)

{

if (!isExpand)

{

val centerX = width / 2.toFloat()

if (event.x >= centerX - reelWidth && event.x <= centerX + reelWidth)

{

startAnimator()

isExpand = true

}

}

else

{

disAnimator.reverse()

isExpand = false

}

}

return true

}

}

return false

}

5.

因为使用了Anmator,为了避免内存泄漏,注意添加以下代码

override fun onDetachedFromWindow()

{

super.onDetachedFromWindow()

disAnimator.cancel()

}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。