gpt4 book ai didi

android - 汉堡包菜单图标在 Android 中交叉动画

转载 作者:行者123 更新时间:2023-11-30 01:31:22 25 4
gpt4 key购买 nike

我正在尝试用十字图标替换菜单图标,但我不知道比替换 ImageView 中的源更好的解决方案,而且我找不到完成的转换图像的库。

Menu icon Cross icon

任何帮助将不胜感激。

最佳答案

Android 有一个用于在汉堡包和箭头之间设置动画的可绘制对象:android.support.v7.graphics.drawable.DrawerArrowDrawable此可绘制对象使用非常通用的 Canvas 绘制方法。如果您有一些空闲时间并准备好从事一些乏味的工作,您可以通过查看此示例来制作几乎任何东西的动画。

例如,这里是交叉绘制的“汉堡包”:

/**
* Simple animating drawable between the "hamburger" icon and cross icon
*
* Based on [android.support.v7.graphics.drawable.DrawerArrowDrawable]
*/
class HamburgerCrossDrawable(
/** Width and height of the drawable (the drawable is always square) */
private val size: Int,
/** Thickness of each individual line */
private val barThickness: Float,
/** The space between bars when they are parallel */
private val barGap: Float
) : Drawable() {

private val paint = Paint()
private val thick2 = barThickness / 2.0f

init {
paint.style = Paint.Style.STROKE
paint.strokeJoin = Paint.Join.MITER
paint.strokeCap = Paint.Cap.BUTT
paint.isAntiAlias = true

paint.strokeWidth = barThickness
}

override fun draw(canvas: Canvas) {
if (progress < 0.5) {
drawHamburger(canvas)
} else {
drawCross(canvas)
}
}

private fun drawHamburger(canvas: Canvas) {
val bounds = bounds
val centerY = bounds.exactCenterY()
val left = bounds.left.toFloat() + thick2
val right = bounds.right.toFloat() - thick2

// Draw middle line
canvas.drawLine(
left, centerY,
right, centerY,
paint)

// Calculate Y offset to top and bottom lines
val offsetY = barGap * (2 * (0.5f - progress))

// Draw top & bottom lines
canvas.drawLine(
left, centerY - offsetY,
right, centerY - offsetY,
paint)
canvas.drawLine(
left, centerY + offsetY,
right, centerY + offsetY,
paint)
}

private fun drawCross(canvas: Canvas) {
val bounds = bounds
val centerX = bounds.exactCenterX()
val centerY = bounds.exactCenterY()
val crossHeight = barGap * 2 + barThickness * 3
val crossHeight2 = crossHeight / 2

// Calculate current cross position
val distanceY = crossHeight2 * (2 * (progress - 0.5f))
val top = centerY - distanceY
val bottom = centerY + distanceY
val left = centerX - crossHeight2
val right = centerX + crossHeight2

// Draw cross
canvas.drawLine(
left, top,
right, bottom,
paint)
canvas.drawLine(
left, bottom,
right, top,
paint)
}

override fun setAlpha(alpha: Int) {
if (alpha != paint.alpha) {
paint.alpha = alpha
invalidateSelf()
}
}

override fun setColorFilter(colorFilter: ColorFilter?) {
paint.colorFilter = colorFilter
invalidateSelf()
}

override fun getIntrinsicWidth(): Int {
return size
}

override fun getIntrinsicHeight(): Int {
return size
}

override fun getOpacity(): Int {
return PixelFormat.TRANSLUCENT
}

/**
* Drawable color
* Can be animated
*/
var color: Int = 0xFFFFFFFF.toInt()
set(value) {
field = value
paint.color = value
invalidateSelf()
}

/**
* Animate this property to transition from hamburger to cross
* 0 = hamburger
* 1 = cross
*/
var progress: Float = 0.0f
set(value) {
field = value.coerceIn(0.0f, 1.0f)
invalidateSelf()
}

}

您可以像使用任何其他可绘制对象一样使用此可绘制对象,例如将 ImageView src 设置为此可绘制对象:

imageView = AppCompatImageView(context)
addView(imageView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
hamburgerDrawable = HamburgerCrossDrawable(
size = dpToPx(20).toInt(),
barThickness = dpToPx(2),
barGap = dpToPx(5)
)
hamburgerDrawable.color = hamburgerColor
imageView.setImageDrawable(hamburgerDrawable)

要使 drawable 实际上从汉堡包变为十字形并返回,您需要更改 HamburgerCrossDrawable.progress(0 代表汉堡包,1 代表十字形):

val animator = ValueAnimator.ofFloat(0.0f, 1.0f)
animator.interpolator = AccelerateDecelerateInterpolator()
animator.duration = 300
animator.addUpdateListener {
val progress = it.animatedValue as Float
val color = interpolateColor(hamburgerColor, crossColor, progress)
hamburgerDrawable.color = color
hamburgerDrawable.progress = progress
}
animator.start()

关于android - 汉堡包菜单图标在 Android 中交叉动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35716854/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com