前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >仿抖音发布按住拍呼吸效果

仿抖音发布按住拍呼吸效果

作者头像
用户1108631
发布2019-08-17 12:41:35
7290
发布2019-08-17 12:41:35
举报
文章被收录于专栏:每天学点Android知识

抖音——时下最火的app之一,发布过程中有个按住拍的呼吸效果,效果如下所示:

上面两个按钮,都是采用属性动画进行控制的,但实现细节稍有不同,左上采用的是StateListAnimator,只需要考虑跟随手指动就可以了;右下是在onTouch里面控制动画开启or关闭。 demo采用了自定义View的方式,重点有几点:

  1. 属性动画,定义View不具备的属性——内部半径参数
  2. onTouch(),跟随手指随动
  3. StateListAnimator,按照View不同状态执行不同动画。

代码实现

跟随手指随动

代码语言:javascript
复制
var myX: Float = 0f    var myY: Float = 0f    var xDiff: Float = 0f    var yDiff: Float = 0f    override fun onTouchEvent(event: MotionEvent?): Boolean {        when (event?.action) {            MotionEvent.ACTION_DOWN -> {                myX = x                myY = y                xDiff = event?.rawX - x                yDiff = event?.rawY - y            }            MotionEvent.ACTION_MOVE -> {                x = event?.rawX - xDiff                y = event?.rawY - yDiff            }            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {                //回到最初的位置                animate().x(myX).y(myY)            }        }        return super.onTouchEvent(event)    }

手指按下时,记录View的x、y值,move时改变x和y值,松开时,回到最初的位置。

自定义属性

代码语言:javascript
复制
var innerRaduisFactor: Float = 0f        //内部半径因子,[0,1)        set(value) {            field = value            invalidate()        }val showText = "按住拍"    override fun onDraw(canvas: Canvas?) {        super.onDraw(canvas)        if (innerRaduisFactor >= MIN_INNER_RADIUS_FACTOR) {            paint.style = Paint.Style.STROKE            val left = measuredWidth * (1 - innerRaduisFactor) / 2            val right = left + (width / 2 - left) * 2            paint.strokeWidth = measuredWidth * (1 - innerRaduisFactor) / 2            canvas?.drawArc(left, left, right, right, 0f, 360f, false, paint)        } else {            paint.style = Paint.Style.FILL            canvas?.drawCircle(width / 2.0f, height / 2.0f, width / 2.0f, paint)            paint.textSize = 40f            paint.color = Color.WHITE            val textX = (width - paint.measureText(showText)) / 2.0f            val textY = height / 2 + Math.abs(paint.fontMetrics.ascent + paint.fontMetrics.descent) / 2            canvas?.drawText(showText, 0, showText.length, textX, textY, paint)            paint.color = Color.RED        }    }

innerRadiusFactor设置时,调用invalidate触发onDraw(),这样属性动画就可以使用innerRadiusFactor属性了。

StateListAnimator实现方式

关于StateListAnimator,可以参考让View跟随状态动起来——StateListAnimator。本例子中的代码主要是在statepressed=true状态下,尺寸扩大1.5,然后innerRadiusFactor在[0.75,0.9]之间无限回荡;在statepressed=false状态下,恢复到最初状态。

代码语言:javascript
复制
val breathAnimator: StateListAnimator by lazy {        val pressedOuterAnim = AnimatorSet().apply {            play(ObjectAnimator.ofFloat(this@BreathView, SCALE_X, 1.0f, 1.5f))                    .with(ObjectAnimator.ofFloat(this@BreathView, SCALE_Y, 1.0f, 1.5f))        }        val pressedInnerAnim = ObjectAnimator.ofFloat(this, "innerRaduisFactor", MAX_INNER_RADIUS_FACTOR, MIN_INNER_RADIUS_FACTOR).apply {            repeatMode = ValueAnimator.REVERSE            repeatCount = ValueAnimator.INFINITE            duration = 1000        }        val pressedAnim = AnimatorSet().apply {            play(pressedOuterAnim).before(pressedInnerAnim)        }        val normalOuterAnim = AnimatorSet().apply {            play(ObjectAnimator.ofFloat(this@BreathView, SCALE_X, 1.0f))                    .with(ObjectAnimator.ofFloat(this@BreathView, SCALE_Y, 1.0f))        }        val normalInnerAnim = ObjectAnimator.ofFloat(this, "innerRaduisFactor", 0f)        val normalAnim = AnimatorSet().apply {            play(normalOuterAnim).before(normalInnerAnim)        }        StateListAnimator().apply {            addState(intArrayOf(android.R.attr.state_pressed), pressedAnim)            addState(intArrayOf(-android.R.attr.state_pressed), normalAnim)        }    }    init {        isClickable = true        stateListAnimator = breathAnimator    }

在init{}中给View设置stateListAnimator,需要注意的是isClickable必须得设为true,不然移动和动画都是无效的。

onTouch()方法中控制动画的开启与关闭

首先依然是定义属性动画,这个和StateListAnimator类似的,只不过那里是将两个动画组合在了一起,这里需要拆分开来。然后在onTouch()方法里面开启和关闭,onTouch()方法如下:

代码语言:javascript
复制
override fun onTouchEvent(event: MotionEvent?): Boolean {        when (event?.action) {            MotionEvent.ACTION_DOWN -> {                myX = x                myY = y                xDiff = event?.rawX - x                yDiff = event?.rawY - y                normalAnimator.cancel()                pressedAnimtor.start()            }            MotionEvent.ACTION_MOVE -> {                x = event?.rawX - xDiff                y = event?.rawY - yDiff            }            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {                animate().x(myX).y(myY)                pressedAnimtor.cancel()                normalAnimator.start()            }        }        return super.onTouchEvent(event)    }

在down事件中开启innerRadiusFactor缩放的动画,在up或cancel事件中关闭动画。 另外需要注意的是,在onDetachFromWindow()中关闭动画,

代码语言:javascript
复制
override fun onDetachedFromWindow() {        super.onDetachedFromWindow()        pressedAnimtor.cancel()        normalAnimator.cancel()    }

总结

以上就是我这边想到的两种方式实现,其实本质都还是属性动画。 关于代码,可以参考[BreathView]:https://github.com/wangli135/ClimbDemo/blob/master/jetpackdemo/src/main/java/com/xingfeng/jetpackdemo/animation/propertyanimator/BreathView.kt(https://github.com/wangli135/ClimbDemo/blob/master/jetpackdemo/src/main/java/com/xingfeng/jetpackdemo/animation/propertyanimator/BreathView.kt和[BreathView2]:https://github.com/wangli135/ClimbDemo/blob/master/jetpackdemo/src/main/java/com/xingfeng/jetpackdemo/animation/propertyanimator/BreathView2.kt(https://github.com/wangli135/ClimbDemo/blob/master/jetpackdemo/src/main/java/com/xingfeng/jetpackdemo/animation/propertyanimator/BreathView2.kt。 实际上,BreathView可以做的更精细化些,比如加入一些自定义属性,这样可定制更高些,这里只是为了模仿抖音的效果,因此就没有做的很细致。感兴趣的朋友可以对其做的精细化些。

参考

  • https://developer.android.com/guide/topics/graphics/prop-animation?hl=zh-cn#ViewState
  • https://developer.android.com/reference/android/animation/StateListAnimator?hl=zh-cn
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-03-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 每天学点Android知识 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 代码实现
    • 跟随手指随动
      • 自定义属性
        • StateListAnimator实现方式
          • onTouch()方法中控制动画的开启与关闭
          • 总结
          • 参考
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档