转载请标明原地址: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 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);
}
}
}