Android TV 开发有关PopupWindow的KeyListener(手机也能用)
来源:互联网 发布:淘宝招募令 编辑:程序博客网 时间:2024/05/22 00:12
转载请标明原地址:http://blog.csdn.net/gaolei1201/article/details/38586851
现在这个公司主要是做智能电视视频方面。有硬件电视盒子,APP开发,源码二次开发、Launcher开发等。这几天做了一个播放界面弹出设置菜单效果,过程挺曲折的,也挺实用的,就和大家分享一下!如图,点击遥控器上下键使蓝框可以上下移动,点击左右键可以改变内容,按菜单键显示此窗口,再按菜单键和返回键退出,UI效果够酷吧。
磊磊很自然的想到了用PopupWindow,但是问题来了,Activity的pulib void onKeyDown()方法已经被占用,写了许多切换频道等逻辑。因为有多个播放界面需要此功能,所以要把它独立出来写一个类。如何获取此PopupWindow的焦点是一个问题,在网上搜了不少有关知识,都是针对手机的,没有理想的有关监听PopupWindow的上下左右,还有菜单键,返回键的KeyListener,但是在搜索的过程中也找到了思路。PopupWindow父类不是View,因此没有KeyListener。那怎么办呢?方方法总会有的(其实最后发现PopupWindow不太好用,像这个功能直接在xml中多添加一个布局就行,让她显示或隐藏,So Easy)。
我们可以获取PopupWindow里面View的焦点,然后监听它的KeyListener,如"画面比例"这个TextView。
共有两种方法:
一、自定义TextView,让这个TextView获取焦点及KeyListener.部分代码如下:
public class CustomTextView extends TextView { // 自定义TextView让它获取焦点,监听它的KeyListener,相当于是PopupWindow的KeyListener// 选择任意一个子控件设置它的焦点,并且不能设置父控件如LinearLayout焦点,因为这样会使子控件焦点无效// android:focusable="true" // android:focusableInTouchMode="true" private static String TAG = "CustomTextView"; private static int ratioflag = 0, bitratesflag = 0, focusflag = 0; private static String[] display_ratios_array = new String[] { "全屏", "4:3", "16:9" }; private static String[] display_bitrates_array = new String[] { "标清", "高清" }; private static ImageView image_focus; private static TextView display_ratios, display_bitrates, text_display_scale, text_display_bitrates; private static Animation focus_down_anim; private static Animation focus_up_anim; public CustomTextView(Context context) { super(context); // TODO Auto-generated constructor stub } public CustomTextView(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } public static void InitMenuPopupWindow(Context context, PopupWindow mPopupWindow, View popup_view) { focus_down_anim = AnimationUtils.loadAnimation(context, R.anim.popup_menu_sub_layout_focus_down); focus_up_anim = AnimationUtils.loadAnimation(context, R.anim.popup_menu_sub_layout_focus_up); /* 设置触摸外面时消失 */ mPopupWindow.setOutsideTouchable(true); /* 设置系统动画 */ mPopupWindow.setAnimationStyle(android.R.style.Animation_Toast); mPopupWindow.setFocusable(true); display_ratios = (TextView) popup_view.findViewById(R.id.display_scale); display_bitrates = (TextView) popup_view .findViewById(R.id.display_bitrates); text_display_scale = (TextView) popup_view .findViewById(R.id.text_display_scale); text_display_bitrates = (TextView) popup_view .findViewById(R.id.text_display_bitrates); text_display_scale.requestFocus(); image_focus = (ImageView) popup_view.findViewById(R.id.image_focus); } public boolean onKeyDown(int keyCode, KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_DPAD_UP: if (focusflag == 1) { image_focus.startAnimation(focus_up_anim); } focusflag = focusflag - 1; if (focusflag < 0) { focusflag = 0; } return true; case KeyEvent.KEYCODE_DPAD_DOWN: if (focusflag == 0) { image_focus.startAnimation(focus_down_anim); } focusflag = focusflag + 1; if (focusflag > 1) { focusflag = 1; } return true; case KeyEvent.KEYCODE_DPAD_LEFT: if (focusflag == 0) { ratioflag--; if (ratioflag >= 0) { display_ratios.setText(display_ratios_array[ratioflag]); } else { ratioflag = 0; } } else { bitratesflag--; if (bitratesflag >= 0) { display_bitrates .setText(display_bitrates_array[bitratesflag]); } else { bitratesflag = 0; } } return true; case KeyEvent.KEYCODE_DPAD_RIGHT: if (focusflag == 0) { ratioflag++; if (ratioflag <= display_ratios_array.length - 1) { display_ratios.setText(display_ratios_array[ratioflag]); } else { ratioflag = display_ratios_array.length - 1; } } else { bitratesflag++; Log.d(TAG, "bitratesflag -----------right----------------" + bitratesflag); if (bitratesflag <= display_bitrates_array.length - 1) { display_bitrates .setText(display_bitrates_array[bitratesflag]); } else { bitratesflag = display_bitrates_array.length - 1; } } return true; case KeyEvent.KEYCODE_BACK: Log.d(TAG, "back---------------------------"); if (MainActivity.mPopupWindow != null) { MainActivity.mPopupWindow.dismiss(); } return true; case KeyEvent.KEYCODE_MENU: Log.d(TAG, "menu---------------------------"); if (MainActivity.mPopupWindow != null) { MainActivity.mPopupWindow.dismiss(); } return true; default: // do nothing here return false; } }}
二、监听PopupWindow里面任意一个View的KeyListener, 部分代码如下:
public class MainActivity extends Activity { private String TAG = "MainActivity"; private ImageView image_focus; private TextView display_ratios, display_bitrates, text_display_scale, text_display_bitrates; private LinearLayout popup_menu_display_scale, popup_menu_display_bitrates; private Animation focus_down_anim, focus_up_anim; private String[] display_bitrates_array = new String[] { "标清", "高清","流畅" }; private String[] display_ratios_array = new String[] { "全屏", "4:3", "16:9" }; private int ratioflag = 0, bitratesflag = 0, focusflag = 0; private Button button; private PopupWindow mPopupWindow;// public static ArrayList<String> bitratesList = new ArrayList<String>();// public static ArrayList<String> ratiosList = new ArrayList<String>(); protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); View popup_view = LayoutInflater.from(this).inflate( R.layout.popup_layout, null); button = (Button) findViewById(R.id.show); image_focus = (ImageView) popup_view.findViewById(R.id.image_focus); display_ratios = (TextView) popup_view.findViewById(R.id.display_scale); display_bitrates = (TextView) popup_view .findViewById(R.id.display_bitrates); text_display_scale = (TextView) popup_view .findViewById(R.id.text_display_scale); //text_display_scale.requestFocus(); text_display_bitrates = (TextView) popup_view .findViewById(R.id.text_display_bitrates); focus_down_anim = AnimationUtils.loadAnimation(this, R.anim.popup_menu_sub_layout_focus_down); focus_up_anim = AnimationUtils.loadAnimation(this, R.anim.popup_menu_sub_layout_focus_up); popup_menu_display_scale = (LinearLayout) popup_view .findViewById(R.id.popup_menu_display_scale); // for (int i = 0; i < display_ratios_array.length; i++) {// ratiosList.add(display_ratios_array[i]);// }// for (int i = 0; i < display_bitrates_array.length; i++) {// bitratesList.add(display_bitrates_array[i]);// } button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub mPopupWindow.showAtLocation(findViewById(R.id.show), Gravity.CENTER, 0, 0); } }); // 这里主要针对Android TV开发 ,只有遥控器,所以Key监听事件用的比较多,和手机不一样。 //这个地方最关键必须是设置popup_view里面的一个控件KeyListener,不能是布局如popup_menu_display_scale, //也不能是popup_view(网上许多这样说法,是行不通的), text_display_bitrates.setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { // TODO Auto-generated method stub switch (keyCode) { case KeyEvent.KEYCODE_DPAD_UP: if (focusflag == 1) { image_focus.startAnimation(focus_up_anim); } focusflag = focusflag - 1; if (focusflag < 0) { focusflag = 0; } return true; case KeyEvent.KEYCODE_DPAD_DOWN: if (focusflag == 0) { image_focus.startAnimation(focus_down_anim); } focusflag = focusflag + 1; if (focusflag > 1) { focusflag = 1; } return true; case KeyEvent.KEYCODE_DPAD_LEFT: if (focusflag == 0) { ratioflag--; if (ratioflag >= 0) { display_ratios.setText(display_ratios_array[ratioflag]); } else { ratioflag = 0; } } else { bitratesflag--; if (bitratesflag >= 0) { display_bitrates .setText(display_bitrates_array[bitratesflag]); } else { bitratesflag = 0; } } return true; case KeyEvent.KEYCODE_DPAD_RIGHT: if (focusflag == 0) { ratioflag++; if (ratioflag <= display_ratios_array.length - 1) { display_ratios.setText(display_ratios_array[ratioflag]); } else { ratioflag = display_ratios_array.length - 1; } } else { bitratesflag++; if (bitratesflag <= display_bitrates_array.length - 1) { display_bitrates .setText(display_bitrates_array[bitratesflag]); } else { bitratesflag = display_bitrates_array.length - 1; } } return true; case KeyEvent.KEYCODE_BACK: if (mPopupWindow != null) { mPopupWindow.dismiss(); } return true; case KeyEvent.KEYCODE_MENU: showMenuWindow(); return true; } return false; } }); mPopupWindow = new PopupWindow(popup_view, 700, 400); mPopupWindow.setFocusable(true); mPopupWindow.setAnimationStyle(android.R.style.Animation_Toast); }// @Override// public boolean onMenuOpened(int featureId, Menu menu) { // 截获菜单事件// // TODO Auto-generated method stub// showMenuWindow();// return false; // 返回为true 则显示系统menu// // }//// @Override// public boolean onCreateOptionsMenu(Menu menu) {// // TODO Auto-generated method stub//// menu.add("menu");// 必须创建一项// return super.onCreateOptionsMenu(menu);// // } public boolean onKeyDown(int kCode, KeyEvent kEvent) { switch (kCode) { case KeyEvent.KEYCODE_BACK: MainActivity.this.finish(); return true; } return false; } private void showMenuWindow() { if (mPopupWindow.isShowing()) { mPopupWindow.dismiss(); }else{ mPopupWindow.showAtLocation(findViewById(R.id.show), Gravity.CENTER, 0, 0); } }}
源码地址,点击下载......
- Android TV 开发有关PopupWindow的KeyListener(手机也能用)
- Android TV常用动画的效果,View选中变大且有阴影(手机也能用)
- Android Bootstrap 开发也能用模板
- 【android开发】手机应用管理器的实现之实现popupWindow类对话框(二)
- 【android开发】手机应用管理器的实现之实现popupWindow类对话框(二)
- 手机也能用的在线pdf转换成word方法
- Android TV开发总结(一)构建一个TV app前要知道的事儿
- Android TV开发总结(一)构建一个TV app前要知道的事儿
- Android TV开发总结(六)构建一个TV app的直播节目实例
- Android开发之TV端APP在手机上运行
- android TV 开发 (二) 处理电视的硬件
- Android Bootstrap:开发也能用模板,省时又省力!
- Android Bootstrap:开发也能用模板,省时又省力!
- Android Bootstrap:开发也能用模板,省时又省力!
- 关于Android TV应用开发的心得体会
- 关于android TV开发的若干心得
- Android TV开发经验总结---初识TV开发
- Android TV开发经验总结---初识TV开发
- SQL Server 2008 ADO连接数据库慢的解决方法
- 动态添加删除Option达到二级联动
- 翻译www.djangobook.com之第四章:Django模板系统
- 编程过程中字符编码乱码问题汇总
- 一个关于SQL Server memory计数器的系列讲座(很详细)
- Android TV 开发有关PopupWindow的KeyListener(手机也能用)
- Eclipse添加SVN(eclipse 3.7 + subclipse1.8)
- IOS(CGContent画曲线)
- 在一个页面显示多个iChart报表
- 企业应用架构模式 (简单笔记)
- POJ 3671 (n log n,LIS)
- 一道面试题:求出这10000个数字中最大的500个
- Java Servlet与Web容器之间的关系
- java轻量级Http Server