Android 控制你的音量淡入淡出吧~

刚刚听到淡入淡出这个效果还是挺懵逼的,后面有同事告诉我试下一个场景:当手机用网易云音乐播放音乐的时候,如果这时候听微信语音中断播放音乐,这时候你会细心发现网易音乐的静音和播放都有渐入渐出效果。试下还真的有这种细节上的效果~

** 我简单说明下效果 **
1、淡入。从0到1过程。音量声音不会马上变化,是有一个过度的增大
2、淡出。从1到0过程。音量声音不会马上变化,是有一个过度的降低

所以下面看下怎么实现的:

一、SOURCE

整个控制器大概是以下调用逻辑:

muteVolumeManager.png

底层其实就是由handler去做Delayed动态增大或者降低音量,逻辑原理都比较好理解,所以这里笔者就不详细介绍,笔者抽成一个简化版本代码贴上来,希望可以给读者一些参考价值~

二、CODE

/**
 * 音量淡入淡出管理者
 * Created by siven on 17/3/22.
 */

public class MuteVolumeManager {

    // action
    private static final int ACTION_RESTORE_VALUE = 1000;
    private static final int ACTION_STOP_VALUE = 1001;

    // 淡出与淡出时间
    private int restoreTime = 2000; // 恢复 淡入时间为2秒
    private int stopTime = 1000; // 静音 淡出时间为1秒

    private float muteCurVolume = 0f;
    private float muteTargetVolume = 0f;

    private float unMuteCurVolume = 0f;
    private float unMuteTargetVolume = 0f;

    private boolean isMuteing = false;
    private boolean isUnMuteing = false;

    // listenter
    private VolumeListenter volumeListenter;
    public void setVolumeListenter(VolumeListenter volumeListenter) {
        this.volumeListenter = volumeListenter;
    }

    // handler control
    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            if (msg.what == ACTION_RESTORE_VALUE){

                if (muteCurVolume < muteTargetVolume) {

                    muteCurVolume += 0.1f;
                    if (muteCurVolume > 1) {
                        muteCurVolume = 1;
                    }
                    if (muteCurVolume < muteTargetVolume){
                        muteCurVolume = muteTargetVolume;
                    }
//                    Logger.d("siven","实时恢复音量 " + muteCurVolume);
                    if (muteCurVolume < muteTargetVolume) {
                        notifyVolumeChange(muteCurVolume);//最大1.0,是个百分比
                        handler.sendEmptyMessageDelayed(ACTION_RESTORE_VALUE, restoreTime/10);//2秒恢复音量100%音量
                    }else{
                        muteCurVolume = muteTargetVolume;
                        notifyVolumeChange(muteCurVolume);//最大1.0,是个百分比

                        if (volumeListenter!=null && isUnMuteing) volumeListenter.onCompleteUnMute(muteCurVolume);
                        isUnMuteing = false;
                    }

                }else if (muteCurVolume >= muteTargetVolume){
                    notifyVolumeChange(muteTargetVolume);//最大1.0,是个百分比
//                    Logger.d("siven","实时恢复音量 " + muteTargetVolume);
                    if (volumeListenter!=null && isUnMuteing) volumeListenter.onCompleteUnMute(muteCurVolume);
                    isUnMuteing = false;
                }

            }else if (msg.what == ACTION_STOP_VALUE){

                if (unMuteCurVolume > unMuteTargetVolume){

                    unMuteCurVolume -=0.1;

                    if (unMuteCurVolume <0){unMuteCurVolume = 0;}

                    notifyVolumeChange(unMuteCurVolume);
//                    Logger.d("siven","实时静音音量 " + unMuteCurVolume);

                    if (unMuteCurVolume > unMuteTargetVolume) {
                        handler.sendEmptyMessageDelayed(ACTION_STOP_VALUE, stopTime/10);//0.5秒恢复音量100%音量
                    }else{
                        if (volumeListenter!=null && isMuteing) volumeListenter.onCompleteMute(unMuteCurVolume);
                        isMuteing = false;
                    }

                }else{
                    notifyVolumeChange(0f);//静音
                    if (volumeListenter!=null && isMuteing) volumeListenter.onCompleteMute(unMuteCurVolume);
                    isMuteing = false;
                }


            }

        }
    };



    /**
     * 恢复音量,淡入效果
     */
    public void unMute(float curVolume,float tagetVolume){

        if (isUnMuteing) return;
        isUnMuteing = true;

        this.muteTargetVolume = tagetVolume;
        this.muteCurVolume = curVolume;

        handler.sendEmptyMessage(ACTION_RESTORE_VALUE);

    }

    /**
     * 静音,淡出效果
     */
    public void mute(float curVolume){

        if (isMuteing) return;
        isMuteing = true;

        this.unMuteCurVolume = curVolume;
        this.unMuteTargetVolume = 0f;

        handler.sendEmptyMessage(ACTION_STOP_VALUE);
    }

    private void notifyVolumeChange(float volume){
        if (volumeListenter != null){
            volumeListenter.onVolumeChange(volume);
        }
    }

    public interface VolumeListenter{
        public void onCompleteMute(float curVolume);
        public void onCompleteUnMute(float curVolume);
        public void onVolumeChange(float volume);
    }


}

这里有说明下VolumeListenter里面三个回调作用,** onCompleteMute 当发生静音(即淡出)的时候,淡出结束完成后回调。 onCompleteUnMute则是相反,淡入结束完成后回调。 onVolumeChange **则是淡入淡出时音量变化回调,这时候只需要在外部调用者控制mediaplayer音量即可,详情看下面举例。

三、DEMO

//.....

private MuteVolumeManager  volumeManager;

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initMediaPlayer();
        initManager();

        muteBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
               volumeManager.mute(0f);
            }
        });

   
          unMuteBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                volumeManager.mute(0f,0.5f);// 我只需要恢复到一半
            }
        });
       
    }

    private void initManager() {
        volumeManager = new MuteVolumeManager();
        volumeManager.setVolumeListenter(new VolumeListenter() {
            public void onCompleteMute(float curVolume) {
                Log.i("siven","静音完成,当前音量为: " + curVolume);
            }

            public void onCompleteUnMute(float curVolume) {
                Log.i("siven","恢复音量完成,当前音量为: " + curVolume);
            }

            public void onVolumeChange(float volume) {
                // 动态设置音量
                mediaPlayer.setVolume(volume,volume);
            }
        });
    }

    private void initMediaPlayer(){
       //...
    }

//.....

三、END

技术、创业、架构等等...有想法欢迎交流
by siven(qq:708854877 email:sy.wu@foxmail.com)

2017.5.25

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,478评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,825评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,482评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,726评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,633评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,018评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,168评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,320评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,264评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,288评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,995评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,587评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,909评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,284评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,862评论 2 339

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,260评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,977评论 4 60
  • 文/萱小孩 有一句话说的好啊,纸是包不住火的,马上就到了九月,开学的日子,本来是个值得开心的时刻,我的内心却是一团...
    萱小孩阅读 218评论 0 3
  • 提出好问题 提出能解决的好问题 能提供好问题的缘由 能反省创造力不足 能关注 能发现自己的目的 能培养创造能力 能...
    jieroarchl阅读 150评论 0 1
  • Docker 来了! Docker 的目标之一就是缩短代码从开发 -> 测试 -> 部署的上线运行的周期,同时让你...
    谢烟客阅读 295评论 1 1