class CameraView @JvmOverloads constructor(
context: Context, @Nullable attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
defStyleRes: Int = 0
) : View(context, attrs, defStyleAttr, defStyleRes) {
private var bitmapWidth: Float = dp2px(200F)
private var bitmap: Bitmap
private val paint: Paint = Paint(Paint.ANTI_ALIAS_FLAG)
private val camera: Camera = Camera()
var topFlip: Float = -0F // -45
set(value) {
field = value
invalidate()
}
var bottomFlip: Float = 0F // 45
set(value) {
field = value
invalidate()
}
var flipRotate: Float = 0F // 90
set(value) {
field = value
invalidate()
}
init {
bitmap = getTargetWidthBitmap(bitmapWidth.toInt())
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
camera.save()
canvas.save()
canvas.translate(width / 2F, height / 2F)
canvas.rotate(-flipRotate)
camera.rotateX(topFlip)
camera.setLocation(0F, 0F, -4 * resources.displayMetrics.density)
camera.applyToCanvas(canvas)
canvas.clipRect(-bitmapWidth, -bitmapWidth, bitmapWidth, 0F)
canvas.rotate(flipRotate)
canvas.translate(-width / 2F, -height / 2F)
canvas.drawBitmap(bitmap, width / 2 - bitmapWidth / 2, height / 2 - bitmapWidth / 2, paint)
canvas.restore()
camera.restore()
camera.save()
canvas.save()
canvas.translate(width / 2F, height / 2F)
canvas.rotate(-flipRotate)
camera.rotateX(bottomFlip)
camera.setLocation(0F, 0F, -4 * resources.displayMetrics.density)
camera.applyToCanvas(canvas)
canvas.clipRect(-bitmapWidth, 0F, bitmapWidth, bitmapWidth)
canvas.rotate(flipRotate)
canvas.translate(-width / 2F, -height / 2F)
canvas.drawBitmap(bitmap, width / 2 - bitmapWidth / 2, height / 2 - bitmapWidth / 2, paint)
canvas.restore()
camera.restore()
}
private fun getTargetWidthBitmap(targetWidth: Int): Bitmap {
val options: BitmapFactory.Options = BitmapFactory.Options()
options.inJustDecodeBounds = true
BitmapFactory.decodeResource(resources, R.drawable.wechat, options)
options.inJustDecodeBounds = false
options.inDensity = options.outWidth
options.inTargetDensity = targetWidth
return BitmapFactory.decodeResource(resources, R.drawable.wechat, options)
}
private fun dp2px(dp: Float) = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dp,
Resources.getSystem().displayMetrics
)
/**
* 动画
*/
fun playAnimatorSet() {
val animatorSet: AnimatorSet = AnimatorSet()
val topFlipAnimator = ObjectAnimator.ofFloat(this, "topFlip", 0F, -45F)
topFlipAnimator.startDelay = 1000
topFlipAnimator.duration = 1000
val bottomFlipAnimator = ObjectAnimator.ofFloat(this, "bottomFlip", 0F, 45F)
bottomFlipAnimator.startDelay = 1000
bottomFlipAnimator.duration = 1000
val flipRotateAnimator = ObjectAnimator.ofFloat(this, "flipRotate", 0F, 90F)
flipRotateAnimator.startDelay = 1000
flipRotateAnimator.duration = 1000
animatorSet.playSequentially(bottomFlipAnimator, flipRotateAnimator, topFlipAnimator)
animatorSet.startDelay = 1000
animatorSet.start()
}
}