本文为原创文章,转载请注明出处。
文章最后附带DEMO,请需要的朋友下载。
从API 17开始,Android提供了Presentation类,为多屏异显开发提供了官方支持,当然最终需求的实现也需要底层硬件及驱动的支持。
基本需求:控制辅屏全屏显示与主显不同的内容,且当主显全屏显示的内容变化后对辅屏显示内容的延续性(例如辅屏视频播放)不产生影响。
本文主要内容有以下几点:
(1)Presentation的基本用法;
(2)自定义Dialog的使用(全屏);
(3)采用自定义Dialog对话框方式代替Activity间的切换,防止因Activity进入Paused状态导致Presentation不再显示或显示内容不持续的情况,例如想让辅屏连续播放视频,如果采用Activity切换方式,在Activity切换后新的Activity控制的Presentation很难延续上一个Presentation的视频播放位置且用户体验不好。
Presentation的高级用法比如硬件状态改变事件监听等,请参考官方API或其他文章。
通常,使用Presentation有几个要点:
(1)生命周期,Android API官方文档有段原话"A presentation is automatically canceled (see cancel()
) when the display to which it is attached is removed. An activity should take care of pausing and resuming whatever content is playing within the presentation whenever the activity itself is paused or resumed.",意思是当与presentation 绑定的Display被移除或Activitiey进入pauseed、resuming状态时必须由我们自己控制Presentation的生命周期即Activity不在主显显示时由其创建的Presentation也将消失。
(2)获得Display,每个Presentation必须指定单独的Display用于与主屏幕不同内容的展现。
(3)设置ContentView,与Activity一样,Presentation也可以通过setContentView方法设置Presentation展现的XML布局文件。
说明:为了便于代码重构和逻辑分离,自定义的Presentation和Dialog均定义成单独的类,如果功能很简单也可以定义成内部类。
一、自定义Presentation显示
通常获得Presentation显示需要的Display有两种方法,MediaRouter 和DisplayManager ,本文将采用DisplayManage获取Display的方式。
(1)创建布局文件presentation_content.xml,效果如下:
(2)创建XiaoshubaoPresentation.java类文件:
1 package xiaoshubao.presentationdemo; 2 3 import android.app.Presentation; 4 import android.content.Context; 5 import android.os.Bundle; 6 import android.view.Display; 7 import android.widget.TextView; 8 9 /** 10 * 作者:xiaoshubao 11 * 时间:2016/06/30 12 * 版本: V1.0 13 * 说明: 14 */ 15 public class XiaoshubaoPresentation extends Presentation { 16 private Display mdisplay; 17 public XiaoshubaoPresentation(Context context, Display display) { 18 super(context, display); 19 this.mdisplay = display; 20 } 21 22 23 @Override 24 protected void onStart() { 25 super.onStart(); 26 MessageUtils.showInfo("MyPresentation....onStart"); 27 } 28 29 @Override 30 protected void onStop() { 31 super.onStop(); 32 MessageUtils.showInfo("MyPresentation....onStop"); 33 } 34 35 @Override 36 public void show() { 37 super.show(); 38 MessageUtils.showInfo("MyPresentation....show"); 39 } 40 41 @Override 42 public void hide() { 43 super.hide(); 44 MessageUtils.showInfo("MyPresentation....hide"); 45 } 46 47 @Override 48 public void dismiss() { 49 super.dismiss(); 50 MessageUtils.showInfo("MyPresentation....dismiss"); 51 } 52 53 @Override 54 protected void onCreate(Bundle savedInstanceState) { 55 super.onCreate(savedInstanceState); 56 setContentView(R.layout.presentation_content); 57 initData(); 58 MessageUtils.showInfo("MyPresentation....savedInstanceState"); 59 } 60 61 private void initData() { 62 TextView mPresentationId = (TextView) findViewById(R.id.presentationIdTextView); 63 mPresentationId.setText("" + mdisplay.getDisplayId()); 64 } 65 }
(3)显示XiaoshubaoPresentation
1 /** 2 * 初始化辅屏显示 3 */ 4 private void initPresentation() { 5 DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE); 6 if (displayManager != null) { 7 Display[] displays = displayManager.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION); 8 for (Display display : displays) { 9 XiaoshubaoPresentation mPresentation = new XiaoshubaoPresentation(this, display); 10 mPresentation.show(); 11 mPresentationListView.add(mPresentation); 12 } 13 } 14 TextView presentationCount=(TextView)findViewById(R.id.presentationCount); 15 presentationCount.setText("辅屏数量:"+mPresentationListView.size()); 16 }
代码说明:
- DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);获得displayManager对象,以便于获得显示屏幕的抽象对象Display。
-
Display[] displays = displayManager.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
DISPLAY_CATEGORY_PRESENTATION:This category can be used to identify secondary displays that are suitable for
* use as presentation displays such as HDMI or Wireless displays,即选择可供Presentation显示内容的Display。
-
XiaoshubaoPresentation mPresentation = new XiaoshubaoPresentation(this, display);//设置Presentation的呈现Display
-
mPresentation.show();//显示Presentation
(4)隐藏Presentation
presentation.hide();
(5)释放Presentation资源
presentation.dismiss();
二、自定义Dialog显示
大致思路:定义Style控制Dialog全屏显示->定义Dialog XML布局文件->自定义Dialog类文件->响应Dialog界面控件事件。
(1)定义Dialog全屏显示的Style
1 <style name="XiaoshubaoDialogStyle"> 2 <item name="android:windowNoTitle">true</item> 3 <item name="android:windowFullscreen">true</item> 4 </style>
(2)Dialog布局文件效果
Dialog1效果
Dialog2效果
(3)创建XiaoshubaoFirstDialog.java类文件
1 package xiaoshubao.presentationdemo; 2 3 import android.app.Dialog; 4 import android.content.Context; 5 import android.view.View; 6 import android.widget.Button; 7 8 /** 9 * 作者:xiaoshubao 10 * 时间:2016/06/30 11 * 版本: V1.0 12 * 说明: 13 */ 14 public class XiaoshubaoFirstDialog extends Dialog { 15 private Context context; 16 private XiaoshubaoFirstDialog dialog; 17 18 public XiaoshubaoFirstDialog(Context context, int themeResId) { 19 super(context, themeResId); 20 this.context = context; 21 dialog = this; 22 } 23 24 @Override 25 public void create() { 26 super.create(); 27 } 28 29 @Override 30 public void show() { 31 super.show(); 32 initListener(); 33 } 34 35 /** 36 * 初始化控件事件 37 */ 38 private void initListener() { 39 Button createSecondDialogButton = (Button) findViewById(R.id.createSecondDialogButton); 40 createSecondDialogButton.setOnClickListener(btn_createSecondDialog); 41 42 Button dismmisDialogButton = (Button) findViewById(R.id.dismmisDialogButton); 43 dismmisDialogButton.setOnClickListener(dismmisDialogOnclick); 44 } 45 46 private View.OnClickListener btn_createSecondDialog = new View.OnClickListener() { 47 @Override 48 public void onClick(View v) { 49 XiaoshubaoSecondDialog secondDialog = new XiaoshubaoSecondDialog(context, R.style.XiaoshubaoDialogStyle); 50 secondDialog.setContentView(R.layout.dialog_second); 51 secondDialog.show(); 52 } 53 }; 54 private View.OnClickListener dismmisDialogOnclick = new View.OnClickListener() { 55 @Override 56 public void onClick(View v) { 57 dialog.dismiss(); 58 } 59 }; 60 }
(4)创建XiaoshubaoSecondDialog.java类文件
1 package xiaoshubao.presentationdemo; 2 3 import android.app.Dialog; 4 import android.content.Context; 5 import android.view.View; 6 import android.widget.Button; 7 8 /** 9 * 作者:xiaoshubao 10 * 时间:2016/06/30 11 * 版本: V1.0 12 * 说明: 13 */ 14 public class XiaoshubaoSecondDialog extends Dialog { 15 public XiaoshubaoSecondDialog(Context context, int themeResId) { 16 super(context, themeResId); 17 dialog=this; 18 } 19 private XiaoshubaoSecondDialog dialog; 20 @Override 21 public void create() { 22 super.create(); 23 } 24 25 @Override 26 public void show() { 27 super.show(); 28 initListener(); 29 } 30 /** 31 * 初始化控件事件 32 */ 33 private void initListener() { 34 Button dismmisDialogButton = (Button) findViewById(R.id.dismmisDialogButton); 35 dismmisDialogButton.setOnClickListener(dismmisDialogOnclick); 36 } 37 private View.OnClickListener dismmisDialogOnclick = new View.OnClickListener() { 38 @Override 39 public void onClick(View v) { 40 dialog.dismiss(); 41 } 42 }; 43 }
(5)设置Dialog控件响应事件
1 /** 2 * 初始化控件事件 3 */ 4 private void initListener() { 5 Button createSecondDialogButton = (Button) findViewById(R.id.createSecondDialogButton); 6 createSecondDialogButton.setOnClickListener(btn_createSecondDialog); 7 8 Button dismmisDialogButton = (Button) findViewById(R.id.dismmisDialogButton); 9 dismmisDialogButton.setOnClickListener(dismmisDialogOnclick); 10 } 11 12 private View.OnClickListener btn_createSecondDialog = new View.OnClickListener() { 13 @Override 14 public void onClick(View v) { 15 XiaoshubaoSecondDialog secondDialog = new XiaoshubaoSecondDialog(context, R.style.XiaoshubaoDialogStyle); 16 secondDialog.setContentView(R.layout.dialog_second); 17 secondDialog.show(); 18 } 19 }; 20 private View.OnClickListener dismmisDialogOnclick = new View.OnClickListener() { 21 @Override 22 public void onClick(View v) { 23 dialog.dismiss(); 24 } 25 };
(6)显示Dialog
1 public void btn_createDialogBtnClick(View v) { 2 mainDialog = new XiaoshubaoFirstDialog(this, R.style.XiaoshubaoDialogStyle); //设置全屏样式 3 mainDialog.setContentView(R.layout.dialog_first); //设置dialog的布局 4 mainDialog.show();//显示dialog界面 5 }
(7)释放Dialog资源
dialog.dismiss();
三、综述
项目最终呈现的效果如上面预览图,重点是给初学Android的朋友了解多屏异显及Dialog全屏显示和事件响应。
DEMO下载地址