Android 用 ValueAnimator 实现 Media

作者: summerlyy | 来源:发表于2017-07-29 11:43 被阅读508次

    其实我觉得大家只要看到标题应该就知道怎么实现了,不过还是贴一下过程, 当个记录吧.


    Android 封装的 MediaPlayer 为我们提供了设置音量的方法.

    public void setVolume(float leftVolume, float rightVolume)
    
    • leftVolumerightVolume 其实是声音的放大系数 , 取值区间为: [0,1]
    • 0 表示无声, 1表示原声音大小

    于是我们可以用 ValueAnimator来实现声音淡入淡出效果.

    kotlin 的实现方法

    /**
     * 产生一个声音渐变效果,可以在暂停或者播放的时候调用
     * @param from 渐变起始的声音大小,取值范围: 0-1,0表示无声,1表示声音最大
     * @param to 渐变结束的声音大小,取值范围: 0-1,0表示无声,1表示声音最大
     * @param doneCallback 声音渐变正常结束时的回调
     */
    private fun MediaPlayer.volumeGradient(from: Float, to: Float, 
                                           doneCallback: (() -> Unit)? = null) {
        val animator = ValueAnimator.ofFloat(from, to)
        animator.duration = 500
        animator.interpolator = LinearInterpolator()
        animator.addUpdateListener {
            val volume = it.animatedValue as Float
            try {
                //此时可能 mediaplayer 状态发生了改变,所以用try catch包裹,一旦发生错误,立马取消
                setVolume(volume, volume)
            } catch (e: Exception) {
                it.cancel()
            }
        }
        //当淡入淡出效果结束时,将声音调回原样
        animator.addListener {
            onAnimationCancel {
                mediaPlayer.setVolume(from, from)
            }
            onAnimationEnd {
                mediaPlayer.setVolume(from, from)
                doneCallback?.invoke()
            }
        animator.start()
    }
    

    调用时就这样做:

    //暂停播放
    mediaPlayer.volumeGradient(1f, 0f) {
        mediaPlayer.pause()
    }
    //开始播放
    mediaPlayer.start()
    mediaPlayer.volumeGradient(0f, 1f)
    

    Java版本?

    interface DoneCallBack {
        void onComplete();
    }
    
    public static void volumeGradient(final MediaPlayer mediaPlayer,
                                      final float from, final float to,
                                      @Nullable DoneCallBack doneCallBack) {
        ValueAnimator animator = ValueAnimator.ofFloat(from, to);
        animator.setDuration(500);
        animator.setInterpolator(new LinearInterpolator());
        animator.addUpdateListener(it -> {
            float volume = (float) it.getAnimatedValue();
            try {
                //此时可能 mediaPlayer 状态发生了改变,所以用try catch包裹,一旦发生错误,立马取消
                mediaPlayer.setVolume(volume, volume);
            } catch (Exception e) {
                it.cancel();
            }
        });
        animator.addListener(new Animator.AnimatorListener() {
    
            @Override
            public void onAnimationStart(Animator animation) {
    
            }
    
            @Override
            public void onAnimationEnd(Animator animation) {
                mediaPlayer.setVolume(from, from);
                if (doneCallBack != null) {
                    doneCallBack.onComplete();
                }
            }
    
            @Override
            public void onAnimationCancel(Animator animation) {
                try {
                    mediaPlayer.setVolume(from, from);
                } catch (Exception e) {
                    //忽略
                }
            }
    
            @Override
            public void onAnimationRepeat(Animator animation) {
    
            }
        });
        animator.start();
    }
    

    相关文章

      网友评论

        本文标题:Android 用 ValueAnimator 实现 Media

        本文链接:https://www.haomeiwen.com/subject/vggqlxtx.html