博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
安卓3D旋转容器_实现任意视图3D旋转
阅读量:1895 次
发布时间:2019-04-26

本文共 7618 字,大约阅读时间需要 25 分钟。

关注 ,免费获取全套安卓开发学习资料

用途

支持对任何视图进行包裹后3D翻转.

效果图

主要代码

class ThreeDLayout(context: Context?, attrs: AttributeSet? = null) : ViewGroup(context, attrs) {
private val mCamera: Camera private val mMatrix: Matrix //this viewgroup's center private var mCenterX = 0 private var mCenterY = 0 //rotateDegree private var mCanvasRotateY = 0f private var mCanvasRotateX = 0f private var mCanvasMaxRotateDegree = 50f private var mMode = MODE_BOTH_X_Y private val mDensity: Float private val mValues = FloatArray(9) //the flag of touch private var isCanTouch = false //the degree of animation private var mDegreeY = 0f private var mDegreeX = 0f //the flag of animate private var isPlaying = false //the degree of longer animate private var mLoopAnimateY = 0 override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
check(childCount == 1) {
"ThreeDLayout can only have one child" } val child = getChildAt(0) measureChild(child, widthMeasureSpec, heightMeasureSpec) //only one child view,so give the same size setMeasuredDimension(child.measuredWidth, child.measuredHeight) } override fun onLayout( changed: Boolean, l: Int, t: Int, r: Int, b: Int ) {
val child = getChildAt(0) child.layout(0, 0, child.measuredWidth, child.measuredHeight) } override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh) mCenterX = w / 2 mCenterY = h / 2 } override fun onDraw(canvas: Canvas) {
mMatrix.reset() mCamera.save() if (mMode == MODE_Y || mMode == MODE_BOTH_X_Y) {
mCamera.rotateX(mCanvasRotateX) } if (mMode == MODE_X || mMode == MODE_BOTH_X_Y) {
mCamera.rotateY(mCanvasRotateY) } mCamera.rotateY(mDegreeY) mCamera.rotateX(mDegreeX) if (isPlaying) {
mCamera.rotateY(mLoopAnimateY++.toFloat()) if (mLoopAnimateY == 360) {
mLoopAnimateY = 0 } invalidate() } mCamera.getMatrix(mMatrix) // fix the Camera bug, mMatrix.getValues(mValues) mValues[6] = mValues[6] / mDensity mValues[7] = mValues[7] / mDensity mMatrix.setValues(mValues) mCamera.restore() mMatrix.preTranslate(-mCenterX.toFloat(), -mCenterY.toFloat()) mMatrix.postTranslate(mCenterX.toFloat(), mCenterY.toFloat()) canvas.concat(mMatrix) super.onDraw(canvas) } override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
return if (isCanTouch) {
true } else {
super.onInterceptTouchEvent(ev) } } override fun onTouchEvent(event: MotionEvent): Boolean {
return if (isCanTouch) {
val x = event.x val y = event.y when (event.action) {
MotionEvent.ACTION_MOVE -> {
rotateCanvasWhenMove(x, y) invalidate() return true } MotionEvent.ACTION_UP -> {
mDegreeY = 0f rotateCanvasWhenMove(mCenterX.toFloat(), mCenterY.toFloat()) invalidate() return true } } true } else {
super.onTouchEvent(event) } } /** * get the value to rotate */ private fun rotateCanvasWhenMove(x: Float, y: Float) {
val dx = x - mCenterX val dy = y - mCenterY var percentX = dx / mCenterX var percentY = dy / mCenterY if (percentX > 1f) {
percentX = 1f } else if (percentX < -1f) {
percentX = -1f } if (percentY > 1f) {
percentY = 1f } else if (percentY < -1f) {
percentY = -1f } mCanvasRotateY = mCanvasMaxRotateDegree * percentX mCanvasRotateX = -(mCanvasMaxRotateDegree * percentY) } fun setTouchable(canTouch: Boolean) {
isCanTouch = canTouch } fun setTouchMode(mode: Int) {
mMode = mode isCanTouch = true } /** * set the max rotate degree */ fun setMaxRotateDegree(degree: Int) {
mCanvasMaxRotateDegree = degree.toFloat() } /** * start horizontal turn animate */ fun startHorizontalAnimate(duration: Long) {
val animator = ValueAnimator.ofFloat(-180f, 0f) animator.addUpdateListener {
animation -> mDegreeY = animation.animatedValue as Float invalidate() } animator.addListener(object : Animator.AnimatorListener {
override fun onAnimationStart(animation: Animator) {
} override fun onAnimationEnd(animation: Animator) {
mDegreeY = 0f animator.removeAllUpdateListeners() } override fun onAnimationCancel(animation: Animator) {
} override fun onAnimationRepeat(animation: Animator) {
} }) animator.duration = duration animator.start() } /** * start horizontal turn animate delayed */ fun startHorizontalAnimateDelayed(delayed: Long, duration: Long) {
Thread(Runnable {
try {
Thread.sleep(delayed) } catch (e: InterruptedException) {
e.printStackTrace() } post {
startHorizontalAnimate(duration) } }).start() } /** * start vertical turn animate */ fun startVerticalAnimate(duration: Long) {
val animator = ValueAnimator.ofFloat(-180f, 0f) animator.addUpdateListener {
animation -> mDegreeX = animation.animatedValue as Float invalidate() } animator.addListener(object : Animator.AnimatorListener {
override fun onAnimationStart(animation: Animator) {
} override fun onAnimationEnd(animation: Animator) {
mDegreeX = 0f animator.removeAllUpdateListeners() } override fun onAnimationCancel(animation: Animator) {
} override fun onAnimationRepeat(animation: Animator) {
} }) animator.duration = duration animator.start() } /** * start vertical turn animate delayed */ fun startVerticalAnimateDelayed(delayed: Long, duration: Long) {
Thread(Runnable {
try {
Thread.sleep(delayed) } catch (e: InterruptedException) {
e.printStackTrace() } post {
startVerticalAnimate(duration) } }).start() } /** * start loop animate */ fun startHorizontalAnimate() {
isPlaying = true invalidate() } /** * stop the loop animate */ fun stopAnimate() {
isPlaying = false mLoopAnimateY = 0 invalidate() } companion object {
//the touch mode var MODE_X = 0 var MODE_Y = 1 var MODE_BOTH_X_Y = 2 } init {
//set a default background to make sure onDraw() dispatch if (background == null) {
setBackgroundColor(Color.parseColor("#ffffff")) } var dm = DisplayMetrics() dm = resources.displayMetrics mDensity = dm.density mCamera = Camera() mMatrix = Matrix() }}

完整源代码

关注头条号,第一时间获取最新文章:

转载地址:http://hwodf.baihongyu.com/

你可能感兴趣的文章
五年,我成为了一名嵌入式工程师。
查看>>
2020年电赛题目,命题专家们怎么看?
查看>>
PCB元器件摆放不可忽略的10个技巧
查看>>
掌握AI核心技术没有秘籍,能自己创造就是王道
查看>>
大学老师的月薪多少?实话实说:4万多一点……
查看>>
2020年电赛题目,命题专家权威解析!
查看>>
美国无人机在火星首飞成功,创造历史,3米飞行高度悬停30秒
查看>>
缺货涨价很久的MCU的国产和国外厂家汇总!(80家)
查看>>
华为重磅反击,鸿蒙来了!
查看>>
常用电子接口大全,遇到不认识的,就翻出来对照辨认!
查看>>
芯片IC附近为啥要放0.1uF的电容?
查看>>
电赛 | 19年全国一等奖,北航学子回忆录。
查看>>
电赛 | 19年全国一等奖,北航学子回忆录(上)
查看>>
电赛 | 19年全国一等奖,北航学子回忆录(下)
查看>>
突破!台积电1nm芯片,有了新进展。
查看>>
一文读懂全系列树莓派!
查看>>
自制一个害羞的口罩,见人就闭嘴,戴着可以喝奶茶
查看>>
聊聊我是如何编程入门的
查看>>
J-Link该如何升级固件?
查看>>
485通信自动收发电路,历史上最详细的解释
查看>>