CameraX:动画缩放

CameraX: Animated Zoom

我正在开发一个相机应用程序,我想要双击缩放之类的东西。我能够实现它,但后来我想通过动画缩放来改进应用程序的用户体验。我尝试应用一个 Ticker 逻辑来做到这一点,但是从 CameraX API 执行一个简单的缩放调用需要自己的时间(高到无法在流畅的动画中使用它。有什么方法可以让我制作动画从当前缩放值缩放到预期值?

代码:

            public boolean onDoubleTap(MotionEvent e) {
                Log.i(TAG, "===============Double tap detected.=========");

                final ZoomState zoomState = camera.getCameraInfo().getZoomState().getValue();
                float start, diff;

                if(zoomState!=null) {
                    start = zoomState.getZoomRatio();
                    diff = start * 0.5f;

                    final Calendar calendar = Calendar.getInstance();
                    final int ANIM_DURATION_IN_MS = 2000;
                    final long endTime = Calendar.getInstance().getTimeInMillis() + ANIM_DURATION_IN_MS;

                    double elapsed = 1.0;

                    while(elapsed>0.0) {
                        elapsed = endTime - Calendar.getInstance().getTimeInMillis();
                        double d = 1 - elapsed/(float)ANIM_DURATION_IN_MS;

                        Log.i(TAG, "getTime: " + Calendar.getInstance().getTimeInMillis());
                        Log.i(TAG, "endTime: " + endTime);
                        Log.i(TAG, "d: " + d);

                        try {
                            camera.getCameraControl().setZoomRatio((float) (start+(diff*d))).get();
                        } catch (ExecutionException | InterruptedException executionException) {
                            executionException.printStackTrace();
                        }
                        Log.i(TAG, "zoomRatio: " + (float) (start+diff*d));
                    }

                    Log.i(TAG, "Done");

                    camera.getCameraControl().setZoomRatio(start+diff);
                }

                return super.onDoubleTap(e);
            }

您可以在短时间内逐渐将缩放级别更改为所需的缩放级别来创建此动画,但您可以在 CameraX 中使用线性缩放而不是使用缩放比率 - 这将为您提供平滑的过渡,而且很容易实现:

linearZoomSeekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {        
    override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
        cameraControl.setLinearZoom(progress / 100f)
    }

    override fun onStartTrackingTouch(seekBar: SeekBar?) {}

    override fun onStopTrackingTouch(seekBar: SeekBar?) {}
})

此示例使用搜索栏,但您可以使用自动更改其值的值动画器来执行此操作。

线性缩放值动画设置示例:

// Initializing the animator with values to zoom - min:0f - max:1f
ValueAnimator animator = ValueAnimator.ofFloat(0.1f, 0.2f, 0.3f, 0.4f, 0.5f);
// Setting animation duration
animator.setDuration(200);
// Adding listener for every value update of the animation
animator.addUpdateListener(valueAnimator -> camera.getCameraControl().setLinearZoom((float) valueAnimator.getAnimatedValue()));
// Start the zoom animation
animator.start();

在值动画器的初始化中放置的值越多,动画看起来就越流畅。