实现自定义音量盘

思路:监听音量的上下按键,显示自定义的音量键盘,然后通过异步线程调整声音的大小,因为这是一个耗时的过程,

/**
 * 音量显示面板
 *
 */
public class VolumePanel extends Handler implements OnKeyListener, OnSeekBarChangeListener {

    /**
     * 日志标签
     */
    public static final String TAG = VolumePanel.class.getSimpleName();
    /**
     * 面板自动关闭延迟时间({@value} ms)
     */
    public static final long DIALOG_DISMISS_DELAY = 5 * 1000;
    /**
     * 显示面板消息
     */
    public static final int MSG_SHOW = 0;
    /**
     * 关闭面板消息
     */
    public static final int MSG_DISMISS = 1;
    /**
     * 弹出框
     */
    private Dialog mDialog;
    /**
     * 弹出框视图
     */
    private View mView;
    /**
     * 进度条视图
     */
    private SeekBar mSeekbarView;
    /**
     * 面板
     */
    private ViewGroup mPanel;
    /**
     * 用于放置音量显示条的视图
     */
    private ViewGroup mSliderGroup;
    /**
     * 音量显示条视图
     */
    private ViewGroup mGroupView;
    /**
     * 音量条前面的图标
     */
    private ImageView mStreamIcon;
    /**
     * Android上下文
     */
    private Context mContext;
    /**
     * 音量进度
     */
    private int mProgress;

    /**
     * 声音流枚举
     * 
     *
     */
    private enum StreamResources {
        RingerStream(AudioManager.STREAM_RING, R.string.volume_icon_description_ringer, R.drawable.ic_audio_ring_notif,
                R.drawable.ic_audio_ring_notif_mute, false), VoiceStream(AudioManager.STREAM_VOICE_CALL,
        `R.string.volume_icon_description_incall, R.drawable.ic_audio_phone, R.drawable.ic_audio_phone, false), MediaStream(
                AudioManager.STREAM_MUSIC, R.string.volume_icon_description_media, R.drawable.ic_audio_vol,
                R.drawable.ic_audio_vol_mute, true);

        int streamType;
        int descRes;
        int iconRes;
        int iconMuteRes;
        // RING, VOICE_CALL & BLUETOOTH_SCO are hidden unless explicitly
        // requested
        boolean show;

        /**
         * 声音流枚举
         * 
         * @param streamType
         *            声音流类型
         * @param descRes
         *            声音流描述
         * @param iconRes
         *            声音流图标
         * @param iconMuteRes
         *            声音流静音图标
         * @param show
         *            是否显示
         */
        StreamResources(int streamType, int descRes, int iconRes, int iconMuteRes, boolean show) {
            this.streamType = streamType;
            this.descRes = descRes;
            this.iconRes = iconRes;
            this.iconMuteRes = iconMuteRes;
            this.show = show;
        }
    };

    /**
     * 声音流列表
     */
    private final StreamResources[] STREAMS = { StreamResources.RingerStream, StreamResources.VoiceStream,
            StreamResources.MediaStream };
    /**
     * 当前的流
     */
    private StreamResources currentStream;

    /**
     * 构造方法
     * 
     * @param context
     *            Android上下文,必须是Application
     * @param itemOnly
     *            只显示音量进度条
     */
    public VolumePanel(Context context, boolean itemOnly) {
        super(context.getMainLooper());
        LayoutInflater inflater = LayoutInflater.from(context);

        // 初始化音量进度条
        mGroupView = (ViewGroup) inflater.inflate(R.layout.volume_adjust_item, null);
        mSeekbarView = (SeekBar) mGroupView.findViewById(R.id.seekbar);
        mSeekbarView.setOnSeekBarChangeListener(this);
        mStreamIcon = (ImageView) mGroupView.findViewById(R.id.stream_icon);

        if (itemOnly) {
            mView = mGroupView;
        } else {
            // 初始化音量面板
            mView = inflater.inflate(R.layout.volume_adjust, null);
            mPanel = (ViewGroup) mView.findViewById(R.id.visible_panel);
            mSliderGroup = (ViewGroup) mView.findViewById(R.id.slider_group);
            mSliderGroup.addView(mGroupView);
        }

        // 初始化弹出框
        mDialog = new Dialog(context) {
            @Override
            public boolean onTouchEvent(MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
                    dismiss();
                    return true;
                }
                return super.onTouchEvent(event);
            }
        };
        mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        mDialog.setContentView(mView);

        // 初始化窗口
        Window window = mDialog.getWindow();
        window.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
        window.setGravity(Gravity.TOP);
        LayoutParams lp = window.getAttributes();
        lp.token = null;
        // Offset from the top
        lp.y = context.getResources().getDimensionPixelOffset(R.dimen.volume_panel_top);
        lp.width = LayoutParams.WRAP_CONTENT;
        lp.height = LayoutParams.WRAP_CONTENT;
        window.setAttributes(lp);
        window.addFlags(LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCH_MODAL
                | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);

        mDialog.setOnKeyListener(this);

        // 保存Android上下文
        mContext = context;
    }

    /**
     * 显示面板
     */
    public void show() {
        Log.i(TAG, "show volume panel");
        sendEmptyMessage(MSG_SHOW);
    }

    /**
     * 关闭面板
     */
    public void dismiss() {
        Log.i(TAG, "dismiss volume panel");
        sendEmptyMessage(MSG_DISMISS);
    }

    @Override
    public void handleMessage(Message msg) {
        // 获取音频管理器
        AudioManager manager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);

        switch (msg.what) {
        // 显示面板
        case MSG_SHOW:
            // 获取调整的声音模式
            int stream = RtpStreamReceiver.getjStream();
            // 判断是否在振铃,如果振铃则调整振铃音量
            Ringtone ringtone = JAudioLauncher.oRingtone;
            if (ringtone != null && ringtone.isPlaying()) {
                stream = ringtone.getStreamType();
            }

            // 获取音量最大值
            int max = manager.getStreamMaxVolume(stream);

            // 最大声音和音量面板不匹配时重新设置
            if (max != mSeekbarView.getMax()) {
                mSeekbarView.setMax(max);
            }

            // 获取音量,设置进度
            int volume = manager.getStreamVolume(stream);
            Log.d(TAG, "volume : " + volume);
            mProgress = volume;
            mSeekbarView.setProgress(volume);

            // 获取流信息,设置进度条
            for (StreamResources streamResources : STREAMS) {
                if (streamResources.streamType == stream) {
                    // 设置音量图标
                    if (volume == 0) {
                        mStreamIcon.setImageResource(streamResources.iconMuteRes);
                    } else {
                        mStreamIcon.setImageResource(streamResources.iconRes);
                    }

                    streamResources.show = true;
                    currentStream = streamResources;
                    break;
                }

                currentStream = null;
                streamResources.show = false;
            }

            // 显示面板
            mDialog.show();
            // 移除关闭消息
            removeMessages(MSG_DISMISS);
            // 设置关闭消息,延迟DIALOG_DISMISS_DELAY
            sendEmptyMessageDelayed(MSG_DISMISS, DIALOG_DISMISS_DELAY);
            break;
        // 关闭面板
        case MSG_DISMISS:
            // 移除关闭消息
            removeMessages(MSG_DISMISS);
            // 如果显示,则关闭
            if (mDialog.isShowing()) {
                mDialog.dismiss();
            }
            break;
        }
        super.handleMessage(msg);
    }

    @Override
    public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
        // 监听按键,继续调用调整声音方法
        if (event.getAction() == KeyEvent.ACTION_DOWN) {
            if (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
                JAudioLauncher.adjust(keyCode, true, mContext);
                return true;
            }
        }

        return false;
    }

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
        mProgress = seekBar.getProgress();
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
        int progress = seekBar.getProgress();
        if (mProgress != progress && currentStream != null) {
            RtpStreamReceiver.setStreamVolume(currentStream.streamType, progress, AudioManager.FLAG_PLAY_SOUND
                    | AudioManager.FLAG_VIBRATE, mContext);
        }
    }

}





 自定义的音量键盘布局
  <?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="80dip"
android:orientation="horizontal"
android:layout_marginTop="8dip"
android:layout_marginBottom="8dip"
android:gravity="left|center_vertical">

<ImageView
    android:id="@+id/stream_icon"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="16dip"
    android:background="?android:attr/selectableItemBackground"
    />

<SeekBar
    style="?android:attr/seekBarStyle"
    android:id="@+id/seekbar"
    android:layout_width="300dp"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:padding="16dip"
    android:layout_marginRight="16dip" />

 </LinearLayout>

///修改声音的方法
    static void setStreamVolume(final int stream,         final int vol, final int flags,
  final Context context) {
if (setVolumeService != null) {
  // 使用线程池调整声音
  setVolumeService.execute(new Runnable() {
    public void run() {
      if (debug) {
        Log.d(TAG, "setStreamVolume : (stream : " + stream + ", vol : " + vol + ", flags : "
            + flags + ")");
      }

               AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
      am.setStreamVolume(stream, vol, flags);
  });
} else {
  Log.w(TAG, "setStreamVolume setVolumeService is null");
   }
    }

//开启一个异步线程

 /**
   * 用于设置音量大小操作的线程池
   */
  static ExecutorService setVolumeService = Executors.newSingleThreadExecutor(new ThreadFactory() {

    @Override
    public Thread newThread(Runnable r) {
      return new Thread(r, "setStreamVolume");
    }
  });
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值