转载请标明原地址:Android TV 开发有关PopupWindow的KeyListener(手机也能用)_高磊的专栏-CSDN博客

现在这个公司主要是做智能电视视频方面。有硬件电视盒子,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 herereturn 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() {@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stubmPopupWindow.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() {@Overridepublic boolean onKey(View v, int keyCode, KeyEvent event) {// TODO Auto-generated method stubswitch (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(手机也能用)相关推荐

  1. Android TV开发总结(三)构建一个TV app的焦点控制及遇到的坑

    原文:Android TV开发总结(三)构建一个TV app的焦点控制及遇到的坑 版权声明:我已委托"维权骑士"(rightknights.com)为我的文章进行维权行动.转载务必 ...

  2. 【Android TV 开发】焦点处理 ( 父容器与子组件焦点获取关系处理 | 不同电视设备上的兼容问题 | 触摸获取焦点 | 按键获取焦点 )

    Android TV 开发系列文章目录 [Android TV 开发]安卓电视调试 ( 开启网络远程调试 ) [Android TV 开发]焦点处理 ( 父容器与子组件焦点获取关系处理 | 不同电视设 ...

  3. android tv 菜单键,Android TV开发总结(三)构建一个TV app的焦点控制及遇到的坑

    前言:关于<TV Metro界面(仿泰捷视频TV版)源码解析>由于都是相关代码,就不发公众号了,有兴趣的可以看链接:http://blog.csdn.net/hejjunlin/artic ...

  4. android tv 云播放器,Android TV开发总结(六)构建一个TV app的直播节目实例

    近年来,Android TV的迅速发展,传统的有线电视受到较大的冲击,在TV上用户同样也可以看到各个有线电视的直播频道,相对于手机,这种直播节目,体验效果更佳,尤其是一样赛事节目,大屏幕看得才够痛快, ...

  5. 聊聊真实的 Android TV 开发技术栈

    智能电视越来越普及了,华为说四月发布智能电视跳票了,一加也说今后要布局智能电视,在智能电视方向,小米已经算是先驱了.但是还有不少开发把智能电视简单的理解成手机屏幕的放大,其实这两者并不一样. 一.序 ...

  6. android 仿 tv 菜单,Android TV 开发之仿泰捷视频最新 TV 版 Metro UI 效果

    Some Android TV related Sample 更多TV相关,欢迎关注公众号: Android TV开发交流群:135622564 1.Imitation of tai jie late ...

  7. android 按键分析,Android TV开发按键与焦点深入分析(四)

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? 前面三篇都是从源码的角度分析按键事件.焦点变换的原理,作为应用层的开发者, 分析源码都是带着实际的开发困惑的,要不然谁没 ...

  8. Android TV开发:APP安装、ICON图标问题

    使用AndroidX版本的Android Studio开发的面向TV的APK,安装后,在电视默认主屏没有显示该APP的ICON,是怎么回事? 一开始没有注意到电视的Android版本,安装APK时出现 ...

  9. Android TV 开发 (1)

    本文来自网易云社区 作者:孙有军 前言 这里主要记录几个TV问题的解决方案,如果对这个不感兴趣的其实就不用往下看了. 这几天有一个需求就是要求出一个TV版本的app,之前没有具体的了解Tv版的app有 ...

最新文章

  1. boost::endian模块实现udt转换的测试程序
  2. 数据库表及字段命名、设计规范
  3. mongodb2.2.1安装
  4. jQuery之过滤选择器
  5. SAP CRM 产品主数据搜索alternative ID type下拉菜单的渲染逻辑
  6. php 去除字符前空格,php中删除字符串前导空格的函数是什么?
  7. 【常用技巧】标准模板库(STL)
  8. 《中国人工智能学会通讯》——10.25 跨姿态和光照变化的低分辨率人脸识别
  9. C++安全方向(三):3.8 openssl单项散列章节总结
  10. 谷歌大脑发布神经架构搜索新方法:提速1000倍
  11. 基于报文大小的策略路由
  12. 吴恩达神经网络和深度学习-学习笔记-2-激活函数
  13. Android添加gdb symbols
  14. java太大太重_Java 编码最容易疏忽的 10 大问题!
  15. 五分钟看懂快速幂算法
  16. java实现消息推送_java实现后台服务器消息推送
  17. jQuery根据纬度经度查看地图
  18. 大学为什么没有UI设计专业
  19. 基于STC89C52单片机实现简易计算器
  20. 【大数据之Linux】

热门文章

  1. 党建统领 科学谋划|农发行江西峡江支行全力推进国际结算业务
  2. React框架新手入门
  3. 【转】PADS生成PDF文件提示:发生严重的运行错误
  4. 最懂中文的人工智能聊天机器人 ChatGPT 国内用户注册攻略(内附万能接码神技)...
  5. 依赖倒置原则(Dependence Inversion Principle)
  6. 2021年空气净化器行业发展研究报告
  7. successful note
  8. matlab图像最暗,一种暗图像的亮度增强方法与流程
  9. 煤矿皮带撕裂识别系统 YOLOv5架构
  10. 狮子鱼独立版_好多鱼?找不同?瑞典科学家涉嫌学术不端