实现自定义音量盘
来源:互联网 发布:php curl 跳转页面 编辑:程序博客网 时间:2024/05/18 02:52
思路:监听音量的上下按键,显示自定义的音量键盘,然后通过异步线程调整声音的大小,因为这是一个耗时的过程,
/** * 音量显示面板 * */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
- 实现自定义音量盘
- 自定义实现MPVolumeView音量控件
- 自定义实现MPVolumeView音量控件
- 自定义实现MPVolumeView音量控件
- 自定义实现MPVolumeView音量控件
- 自定义音量调节控件的实现
- 【Android界面实现】自定义音量调节控件的实现
- Android 自定义SeekBar动态改变 硬件音量大小 实现和音量键的同步
- 控制系统音量,自定义MPVolumeView
- 自定义View音量调节
- 自定义 音量view
- Android 自定义音量控件
- Android自定义音量调节
- seekbar实现音量调节
- 实现动态音量条
- android 实现音量调节
- SeekBar实现音量设置
- Android 自定义音量调节控件
- java线程池使用详解
- 自定义输入框清空按钮
- Vue 折腾记
- CodeIgniter框架源码学习之框架入口文件--index.php
- lnmap实战之负载均衡架构+高可用keepalived
- 实现自定义音量盘
- bzoj 1012: [JSOI2008]最大数maxnumber(树状数组)
- Mysql数据库远程连接10038报错问题原因及解决方案
- React webpack配置文件暴露
- 达内课程-面向对象之多态
- hdu1201 18岁生日
- PHP哈希弱类型比较缺陷
- 文章标题
- WA