Android动画之Activity,View背景的3D缩小

需求

有时候我们在底部弹出一个对话框的时候,很多app为了良好的视觉效果,会将原先的view进行3D缩放。如图是手机京东选择配送方式时,弹出底部对话框,背景View的缩放效果。(ps. Android端没有此效果)手机京东效果

实现方式 1 ScaleAnimation

使用ScaleAnimation是可以实现放大缩小的效果的,但是是没有类似京东这种的3D效果,如果不追求那么极致的体验,还是可以的,毕竟简单方便。

        rootView = findViewById(android.R.id.content)

private fun startShowAnimation() {
        val scaleAnimation = ScaleAnimation(1f, 0.93f, 1f, 0.93f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f)
        scaleAnimation.interpolator = LinearInterpolator()
        scaleAnimation.duration = 300
        scaleAnimation.fillAfter = true
        rootView.startAnimation(scaleAnimation)
    }

实现方式2 自定义动画通过setPolyToPoly

通过 setPolyToPoly 可以实现任务的变形,参数的解释

 /**

     * @param src   源点坐标数组(X,Y)两个为一个点
     * @param srcIndex 数组开始位置
     * @param dst   目标坐标数组
     * @param dstIndex 数组开始位置
     * @param pointCount 用到的点的数量[0..4]
     * @return true if the matrix was set to the specified transformation
     */
    public boolean setPolyToPoly(float[] src, int srcIndex,
                                 float[] dst, int dstIndex,
                                 int pointCount) {
class MyAnimation : Animation() {
    private var mWidth:Float = 0.0f
    private var mHeight:Float = 0.0f

    override fun initialize(width: Int, height: Int, parentWidth: Int, parentHeight: Int) {
        super.initialize(width, height, parentWidth, parentHeight)
        mHeight= height.toFloat()
        mWidth= width.toFloat()
    }

    override fun applyTransformation(interpolatedTime: Float, t: Transformation?) {
        //动画偏移的距离,理论上为了适配,应该使用宽,或者高的百分比,这里方便使用固定值
        var dValue=60f
        //阶段1的动画,时间占比0.6,下方不变,上分开始缩放
        if(interpolatedTime<=0.6f)
        {
            var f1 =interpolatedTime*1/0.6f
            //源定点坐标
            var src = floatArrayOf(0f, 0f
                    , mWidth, 0f
                    , mWidth, mHeight
                    , 0f,mHeight
            )
            //目标定点坐标
            var dest= floatArrayOf(dValue*f1,dValue*f1,
                    mWidth-dValue*f1,dValue*f1,
                    mWidth,mHeight,
                    0f,mHeight)
            //通过src与dest的坐标,来计算出变换的矩阵,
            t?.matrix?.setPolyToPoly(src,0,dest,0,4 )
        }else //阶段2动画时间占比0.4,上方不变,下方缩放
        {
            var f2=(interpolatedTime-0.4f)*1/0.6f
            var src = floatArrayOf(0f, 0f
                    , mWidth, 0f
                    , mWidth, mHeight
                    , 0f,mHeight
            )
            var dest= floatArrayOf(dValue,dValue,
                    mWidth-dValue,dValue,
                    mWidth-dValue*f2,mHeight-dValue*f2,
                    dValue*f2,mHeight-dValue*f2)
            //最后一个参数表示测控点的数量 取值范围是: 0到4
            //为4时 可以进行 缩放、旋转、平移、错切以及任何形变
            t?.matrix?.setPolyToPoly(src,0,dest,0,4 )
        }


    }
}

效果android效果

实现方式3 自定义动画通过camera

这种方式也是google的ApiDemo中实现3d变换的方式,通过Camera实现(此Camera非Hardware包下的camera,不是用来拍照的,可以理解为一个在捕获屏幕View的相机,当相机的位置,角度,距离不同,看到的View自然也是不一样的)。因为有谷歌的demo,这里只是简单的实现方式2中第一阶段的动画。详细的可以参考Google ApiDemo

class CameraAnimation : Animation() {
    private lateinit var mCamera: Camera
    private var centerX=0f
    private var centerY=0f
    override fun initialize(width: Int, height: Int, parentWidth: Int, parentHeight: Int) {
        super.initialize(width, height, parentWidth, parentHeight)
        mCamera = Camera()
        //中心点坐标,屏幕底部正中央
        centerX= (width/2).toFloat()
        centerY= (height).toFloat()
    }

    override fun applyTransformation(interpolatedTime: Float, t: Transformation?) {
        //super.applyTransformation(interpolatedTime, t)
        val camera = mCamera
        val matrix=t?.matrix

        camera.save()
        camera.rotateX(1f)
        camera.getMatrix(matrix)
        camera.restore()
        // 调节中心点
        matrix?.preTranslate(-centerX, -centerY);
        matrix?.postTranslate(centerX, centerY);
    }
}

总结

其实三种实现方式归根到底是一样的,最终都是通过Animation控制Matrix来实现View的变换动画,这也是andorid动画的实现方式。与其它平台不同的是android维护的是一个3阶矩阵,不像ios,opengl等维护一个4阶矩阵,可以方便的进行基于Z轴的变换。但是归根结底,对于没有厚度的View来说,伪3D的显示效果完全可以通过平面变换来产生3D的错觉,利用setPolyToPoly可以方便的实现这种效果。

展开阅读全文
©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值