视频框架 Vitamio 使用教程+部分心得 (四) 滑动控制声音和亮度+android 4.4.X 以上时全屏播放
来源:互联网 发布:流量攻击软件 编辑:程序博客网 时间:2024/05/01 01:17
转载注明出处:
http://blog.csdn.net/u010181592/article/category/5893483
文章出自 我不只是看客的博客
先列出参考资料:
* Vitamio 官网:http://www.vitamio.org(不太稳定,时常打不开)
* 农民伯伯 博客:http://www.cnblogs.com/over140/category/409230.html(开发者之一,博客中有部分Vitamio中文API)
上一篇博文介绍了自定义MediaController 的用法,这次继续完成我们视频播放器的其他功能:滑动控制声音和亮度( 针对左右滑动调节视频进度的问题,博主测试了下 发现 Vitamio对进度条seekBar的封装性很强,木有留下相关操作接口。不修改源文件下实现比较困难,所以放到以后再说……)
还有,测试发现,在第一篇博文使用的全屏,在4.4.X以上的系统时会出现标题栏虽然被隐藏,但任然会留下黑边的bug;还有无法完全隐藏掉虚拟按键的问题。这篇博客我们就解决以上三个问题;
完全全屏
google了一下5.0 隐藏虚拟按键的,网上好多,但参差不齐,这里直接上代码:
public void toggleHideyBar() { // BEGIN_INCLUDE (get_current_ui_flags) // The UI options currently enabled are represented by a bitfield. // getSystemUiVisibility() gives us that bitfield. int uiOptions = getWindow().getDecorView().getSystemUiVisibility(); int newUiOptions = uiOptions; // END_INCLUDE (get_current_ui_flags) // BEGIN_INCLUDE (toggle_ui_flags) boolean isImmersiveModeEnabled = ((uiOptions | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) == uiOptions); if (isImmersiveModeEnabled) { Log.i(TAG, "Turning immersive mode mode off. "); } else { Log.i(TAG, "Turning immersive mode mode on."); } // Navigation bar hiding: Backwards compatible to ICS. if (Build.VERSION.SDK_INT >= 14) { newUiOptions ^= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; } // Status bar hiding: Backwards compatible to Jellybean if (Build.VERSION.SDK_INT >= 16) { newUiOptions ^= View.SYSTEM_UI_FLAG_FULLSCREEN; } // Immersive mode: Backward compatible to KitKat. // Note that this flag doesn't do anything by itself, it only augments the behavior // of HIDE_NAVIGATION and FLAG_FULLSCREEN. For the purposes of this sample // all three flags are being toggled together. // Note that there are two immersive mode UI flags, one of which is referred to as "sticky". // Sticky immersive mode differs in that it makes the navigation and status bars // semi-transparent, and the UI flag does not get cleared when the user interacts with // the screen. if (Build.VERSION.SDK_INT >= 18) { newUiOptions ^= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; } getWindow().getDecorView().setSystemUiVisibility(newUiOptions); //END_INCLUDE (set_ui_flags)}
解释一下,4.4以后推出了一个全新的api——ImmersiveMode,用户沉浸模式(就是完全全屏,隐藏虚拟按键和状态栏) 方法针对不容的sdk加载了不同的模式,而且flag一共有5种模式
// BEGIN_INCLUDE (get_current_ui_flags) // The "Decor View" is the parent view of the Activity. It's also conveniently the easiest // one to find from within a fragment, since there's a handy helper method to pull it, and // we don't have to bother with picking a view somewhere deeper in the hierarchy and calling // "findViewById" on it. View decorView = getActivity().getWindow().getDecorView(); int newUiOptions = uiOptions; // END_INCLUDE (get_current_ui_flags) // BEGIN_INCLUDE (toggle_lowprofile_mode) // Low profile mode doesn't resize the screen at all, but it covers the nav & status bar // icons with black so they're less distracting. Unlike "full screen" and "hide nav bar," // this mode doesn't interact with immersive mode at all, but it's instructive when running // this sample to observe the differences in behavior. if (mLowProfileCheckBox.isChecked()) { newUiOptions |= View.SYSTEM_UI_FLAG_LOW_PROFILE;//低调模式:通知栏和虚拟键变暗 } else { newUiOptions &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE; } // END_INCLUDE (toggle_lowprofile_mode) ` // BEGIN_INCLUDE (toggle_fullscreen_mode) // When enabled, this flag hides non-critical UI, such as the status bar, // which usually shows notification icons, battery life, etc // on phone-sized devices. The bar reappears when the user swipes it down. When immersive // mode is also enabled, the app-drawable area expands, and when the status bar is swiped // down, it appears semi-transparently and slides in over the app, instead of pushing it // down. if (mHideStatusBarCheckBox.isChecked()) {//全屏模式:隐藏状态栏,但并不隐藏虚拟键 newUiOptions |= View.SYSTEM_UI_FLAG_FULLSCREEN; } else { newUiOptions &= ~View.SYSTEM_UI_FLAG_FULLSCREEN; } // END_INCLUDE (toggle_fullscreen_mode) // BEGIN_INCLUDE (toggle_hidenav_mode) // When enabled, this flag hides the black nav bar along the bottom, // where the home/back buttons are. The nav bar normally instantly reappears // when the user touches the screen. When immersive mode is also enabled, the nav bar // stays hidden until the user swipes it back. if (mHideNavCheckbox.isChecked()) {//隐藏虚拟键,点击可出现 newUiOptions |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; } else { newUiOptions &= ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; } // END_INCLUDE (toggle_hidenav_mode) // BEGIN_INCLUDE (toggle_immersive_mode) // Immersive mode doesn't do anything without at least one of the previous flags // enabled. When enabled, it allows the user to swipe the status and/or nav bars // off-screen. When the user swipes the bars back onto the screen, the flags are cleared // and immersive mode is automatically disabled. if (mImmersiveModeCheckBox.isChecked()) { newUiOptions |= View.SYSTEM_UI_FLAG_IMMERSIVE; } else { newUiOptions &= ~View.SYSTEM_UI_FLAG_IMMERSIVE; } // END_INCLUDE (toggle_immersive_mode) // BEGIN_INCLUDE (toggle_immersive_mode_sticky) // There's actually two forms of immersive mode, normal and "sticky". Sticky immersive mode // is different in 2 key ways: // // * Uses semi-transparent bars for the nav and status bars // * This UI flag will *not* be cleared when the user interacts with the UI. // When the user swipes, the bars will temporarily appear for a few seconds and then // disappear again. if (mImmersiveModeStickyCheckBox.isChecked()) { newUiOptions |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; } else { newUiOptions &= ~View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; } // END_INCLUDE (toggle_immersive_mode_sticky) // BEGIN_INCLUDE (set_ui_flags) //Set the new UI flags. decorView.setSystemUiVisibility(newUiOptions); Log.i(TAG, "Current height: " + decorView.getHeight() + ", width: " + decorView.getWidth()); // END_INCLUDE (set_ui_flags)
同样需要在setContentView()前调用;
滑动调节亮度和声音
需求。左侧上下滑动调节亮度,右侧上下滑动调节声音,中间添加提示:
界面文件,因为点击之后控制器会布满屏幕,所及监听和显示组件都要添加到 MediaController中
<RelativeLayout android:id="@+id/operation_volume_brightness" android:layout_width="150dp" android:layout_height="75dp" android:layout_centerInParent="true" android:background="@drawable/videobg" android:orientation="horizontal" android:padding="0dip" android:visibility="gone"> <ImageView android:id="@+id/operation_bg" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:src="@drawable/video_volumn_bg"/> <TextView android:id="@+id/operation_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/operation_bg" android:layout_centerHorizontal="true" android:layout_alignParentBottom ="true" android:text="32:22/45:00" android:textColor="#ffffff" android:textSize="10sp" android:visibility="gone" /> </RelativeLayout>
只需要在控制器文件中添加一个图片显示和文字显示就好,为方便显示,套在一个RelativeLayout中
MyMediaController.class
public class MyMediaController extends MediaController {private static final int HIDEFRAM = 0;//控制提示窗口的显示private static final int SHOW_PROGRESS = 2;private GestureDetector mGestureDetector;//手势监听类private ImageButton img_back;//返回键private ImageView img_Battery;//电池电量显示private TextView textViewTime;//时间提示private TextView textViewBattery;//文字显示电池private VideoView videoView;private Activity activity;private Context context;private int controllerWidth = 0;//设置mediaController高度为了使横屏时top显示在屏幕顶端private View mVolumeBrightnessLayout;//提示窗口private ImageView mOperationBg;//提示图片private TextView mOperationTv;//提示文字private AudioManager mAudioManager;private SeekBar progress;private boolean mDragging;private MediaPlayerControl player;//最大声音private int mMaxVolume;// 当前声音private int mVolume = -1;//当前亮度private float mBrightness = -1f;//返回监听private View.OnClickListener backListener = new View.OnClickListener() { public void onClick(View v) { if(activity != null){ activity.finish(); } }};private Handler myHandler = new Handler() { @Override public void handleMessage(Message msg) { long pos; switch (msg.what) { case HIDEFRAM://隐藏提示窗口 mVolumeBrightnessLayout.setVisibility(View.GONE); mOperationTv.setVisibility(View.GONE); break; } }};//videoview 用于对视频进行控制的等,activity为了退出public MyMediaController(Context context, VideoView videoView , Activity activity) { super(context); this.context = context; this.videoView = videoView; this.activity = activity; WindowManager wm = (WindowManager) context .getSystemService(Context.WINDOW_SERVICE); controllerWidth = wm.getDefaultDisplay().getWidth(); mGestureDetector = new GestureDetector(context, new MyGestureListener());}@Overrideprotected View makeControllerView() { View v = ((LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(getResources().getIdentifier("mymediacontroller", "layout", getContext().getPackageName()), this); v.setMinimumHeight(controllerWidth); //TOP// img_back = (ImageButton) v.findViewById(getResources().getIdentifier("mediacontroller_top_back", "id", context.getPackageName()));// img_Battery = (ImageView) v.findViewById(getResources().getIdentifier("mediacontroller_imgBattery", "id", context.getPackageName()));// img_back.setOnClickListener(backListener);// textViewBattery = (TextView)v.findViewById(getResources().getIdentifier("mediacontroller_Battery", "id", context.getPackageName()));// textViewTime = (TextView)v.findViewById(getResources().getIdentifier("mediacontroller_time", "id", context.getPackageName())); img_back = (ImageButton) v.findViewById(R.id.mediacontroller_top_back); img_Battery = (ImageView) v.findViewById(R.id.mediacontroller_imgBattery); img_back.setOnClickListener(backListener); textViewBattery = (TextView)v.findViewById(R.id.mediacontroller_Battery); textViewTime = (TextView)v.findViewById(R.id.mediacontroller_time); progress = (SeekBar)v.findViewById(R.id.mediacontroller_seekbar); //mid mVolumeBrightnessLayout = (RelativeLayout)v.findViewById(R.id.operation_volume_brightness); mOperationBg = (ImageView)v.findViewById(R.id.operation_bg); mOperationTv = (TextView) v.findViewById(R.id.operation_tv); mOperationTv.setVisibility(View.GONE); mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); mMaxVolume = mAudioManager .getStreamMaxVolume(AudioManager.STREAM_MUSIC); return v;}@Overridepublic boolean dispatchKeyEvent(KeyEvent event) { System.out.println("MYApp-MyMediaController-dispatchKeyEvent"); return true;}@Overridepublic boolean onTouchEvent(MotionEvent event) { if (mGestureDetector.onTouchEvent(event)) return true; // 处理手势结束 switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_UP: endGesture(); break; } return super.onTouchEvent(event);}/** * 手势结束 */private void endGesture() { mVolume = -1; mBrightness = -1f; // 隐藏 myHandler.removeMessages(HIDEFRAM); myHandler.sendEmptyMessageDelayed(HIDEFRAM, 1);}private class MyGestureListener extends GestureDetector.SimpleOnGestureListener { @Override public boolean onSingleTapUp(MotionEvent e) { return false; } @Override public boolean onSingleTapConfirmed(MotionEvent e) { //当收拾结束,并且是单击结束时,控制器隐藏/显示 toggleMediaControlsVisiblity(); return super.onSingleTapConfirmed(e); } @Override public boolean onDown(MotionEvent e) { return true; }//滑动监听 @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { float mOldX = e1.getX(), mOldY = e1.getY(); int y = (int) e2.getRawY(); int x = (int) e2.getRawX(); Display disp = activity.getWindowManager().getDefaultDisplay(); int windowWidth = disp.getWidth(); int windowHeight = disp.getHeight(); if (mOldX > windowWidth * 3.0 / 4.0) {// 右边滑动 屏幕 3/4 onVolumeSlide((mOldY - y) / windowHeight); } else if (mOldX < windowWidth * 1.0 / 4.0) {// 左边滑动 屏幕 1/4 onBrightnessSlide((mOldY - y) / windowHeight); } return super.onScroll(e1, e2, distanceX, distanceY); } //双击暂停或开始 @Override public boolean onDoubleTap(MotionEvent e) { playOrPause(); return true; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { return super.onFling(e1, e2, velocityX, velocityY); }}/** * 滑动改变声音大小 * * @param percent */private void onVolumeSlide(float percent) { if (mVolume == -1) { mVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); if (mVolume < 0) mVolume = 0; // 显示 mVolumeBrightnessLayout.setVisibility(View.VISIBLE); mOperationTv.setVisibility(VISIBLE); } int index = (int) (percent * mMaxVolume) + mVolume; if (index > mMaxVolume) index = mMaxVolume; else if (index < 0) index = 0; if (index >= 10) { mOperationBg.setImageResource(R.drawable.volmn_100); } else if (index >= 5 && index < 10) { mOperationBg.setImageResource(R.drawable.volmn_60); } else if (index > 0 && index < 5) { mOperationBg.setImageResource(R.drawable.volmn_30); } else { mOperationBg.setImageResource(R.drawable.volmn_no); } //DecimalFormat df = new DecimalFormat("######0.00"); mOperationTv.setText((int) (((double) index / mMaxVolume)*100)+"%"); // 变更声音 mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, index, 0);}/** * 滑动改变亮度 * * @param percent */private void onBrightnessSlide(float percent) { if (mBrightness < 0) { mBrightness = activity.getWindow().getAttributes().screenBrightness; if (mBrightness <= 0.00f) mBrightness = 0.50f; if (mBrightness < 0.01f) mBrightness = 0.01f; // 显示 //mOperationBg.setImageResource(R.drawable.video_brightness_bg); mVolumeBrightnessLayout.setVisibility(View.VISIBLE); mOperationTv.setVisibility(VISIBLE); } WindowManager.LayoutParams lpa = activity.getWindow().getAttributes(); lpa.screenBrightness = mBrightness + percent; if (lpa.screenBrightness > 1.0f) lpa.screenBrightness = 1.0f; else if (lpa.screenBrightness < 0.01f) lpa.screenBrightness = 0.01f; activity.getWindow().setAttributes(lpa); mOperationTv.setText((int) (lpa.screenBrightness * 100) + "%"); if (lpa.screenBrightness * 100 >= 90) { mOperationBg.setImageResource(R.drawable.light_100); } else if (lpa.screenBrightness * 100 >= 80 && lpa.screenBrightness * 100 < 90) { mOperationBg.setImageResource(R.drawable.light_90); } else if (lpa.screenBrightness * 100 >= 70 && lpa.screenBrightness * 100 < 80) { mOperationBg.setImageResource(R.drawable.light_80); } else if (lpa.screenBrightness * 100 >= 60 && lpa.screenBrightness * 100 < 70) { mOperationBg.setImageResource(R.drawable.light_70); } else if (lpa.screenBrightness * 100 >= 50 && lpa.screenBrightness * 100 < 60) { mOperationBg.setImageResource(R.drawable.light_60); } else if (lpa.screenBrightness * 100 >= 40 && lpa.screenBrightness * 100 < 50) { mOperationBg.setImageResource(R.drawable.light_50); } else if (lpa.screenBrightness * 100 >= 30 && lpa.screenBrightness * 100 < 40) { mOperationBg.setImageResource(R.drawable.light_40); } else if (lpa.screenBrightness * 100 >= 20 && lpa.screenBrightness * 100 < 20) { mOperationBg.setImageResource(R.drawable.light_30); } else if (lpa.screenBrightness * 100 >= 10 && lpa.screenBrightness * 100 < 20) { mOperationBg.setImageResource(R.drawable.light_20); }}public void setTime(String time){ if (textViewTime != null) textViewTime.setText(time);}//显示电量,public void setBattery(String stringBattery){ if(textViewTime != null && img_Battery != null){ textViewBattery.setText(stringBattery + "%"); int battery = Integer.valueOf(stringBattery); if(battery < 15)img_Battery.setImageDrawable(getResources().getDrawable(R.drawable.battery_15)); if(battery < 30 && battery >= 15)img_Battery.setImageDrawable(getResources().getDrawable(R.drawable.battery_15)); if(battery < 45 && battery >= 30)img_Battery.setImageDrawable(getResources().getDrawable(R.drawable.battery_30)); if(battery < 60 && battery >= 45)img_Battery.setImageDrawable(getResources().getDrawable(R.drawable.battery_45)); if(battery < 75 && battery >= 60)img_Battery.setImageDrawable(getResources().getDrawable(R.drawable.battery_60)); if(battery < 90 && battery >= 75)img_Battery.setImageDrawable(getResources().getDrawable(R.drawable.battery_75)); if(battery > 90 )img_Battery.setImageDrawable(getResources().getDrawable(R.drawable.battery_90)); }}//隐藏/显示private void toggleMediaControlsVisiblity(){ if (isShowing()) { hide(); } else { show(); }}//播放与暂停private void playOrPause(){ if (videoView != null) if (videoView.isPlaying()) { videoView.pause(); } else { videoView.start(); }}}
具体代码都有注释,相对简单易懂,搞定;
还要在Activity中添加完全全屏:
PlayActivity.class
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //定义全屏参数 int flag = WindowManager.LayoutParams.FLAG_FULLSCREEN; //获得当前窗体对象 Window window = PlayActivity.this.getWindow(); //设置当前窗体为全屏显示 window.setFlags(flag, flag); //完全全屏 toggleHideyBar(); //设置视频解码监听 if (!io.vov.vitamio.LibsChecker.checkVitamioLibs(this)) return; setContentView(R.layout.activity_play);......}
效果图:
Demo下载
下一篇会解决作用滑动控制进度,以及Vitamio其他部分中文API;
- 视频框架 Vitamio 使用教程+部分心得 (四) 滑动控制声音和亮度+android 4.4.X 以上时全屏播放
- 视频框架 Vitamio 使用教程+部分心得(一)准备
- 视频框架 Vitamio 使用教程+部分心得 (五) 左右滑动快进快退 + VideoView部分中文API
- 视频框架 Vitamio 使用教程+部分心得 (三) 视频控制器MediaController + 部分中文API
- 视频框架 Vitamio 使用教程+部分心得 (二)第一个视频demo
- 视频框架 Vitamio 使用教程+部分心得 (二)第一个视频demo
- Vitamio 视频框架使用心得
- android视频播放框架Vitamio
- vitamio视频播放框架使用
- android开发视频播放器-----视频播放 Vitamio框架的使用(一)
- 视频框架 Vitamio 使用教程
- Android使用Vitamio框架自定义视频播放器
- 使用Vitamio打造自己的Android万能播放器(2)—— 手势控制亮度、音量、缩放
- 使用Vitamio打造自己的Android万能播放器(2)—— 手势控制亮度、音量、缩放
- 使用Vitamio打造自己的Android万能播放器(2)—— 手势控制亮度、音量、缩放
- 使用Vitamio打造自己的Android万能播放器(2)—— 手势控制亮度、音量、缩放
- 使用Vitamio打造自己的Android万能播放器(2)—— 手势控制亮度、音量、缩放
- 使用Vitamio打造自己的Android万能播放器(2)—— 手势控制亮度、音量、缩放
- Foundation 之 NSData
- JSON解析转化list对象为String时出错
- Ubuntu Kylin 15.10 配置搜狗输入法
- PHP mysql 事务处理实例
- XListView
- 视频框架 Vitamio 使用教程+部分心得 (四) 滑动控制声音和亮度+android 4.4.X 以上时全屏播放
- Java基本语法小结
- 素数测试算法-Miller-Rabin算法
- python的属性和方法
- VIM学习笔记--基本操作
- 主机和虚拟机之间不能互通解决办法
- Mangos源码分析(2):服务器结构探讨之登录服的负载均衡
- OC 之可变数组
- uIP的ARP协议分析