安卓3D旋转容器_实现任意视图3D旋转
发布日期:2021-06-29 18:29:51 浏览次数:2 分类:技术文章

本文共 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() }}

完整源代码

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

转载地址:https://cxyxy.blog.csdn.net/article/details/107410915 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:安卓开发入门教程-UI控件_SeekBar
下一篇:安卓实现登陆界面3D旋转切换

发表评论

最新留言

路过按个爪印,很不错,赞一个!
[***.219.124.196]2024年04月12日 23时39分18秒