Android TV 开发有关PopupWindow的KeyListener(手机也能用)

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

        }
}



                                      源码地址,点击下载......

展开阅读全文

Git 实用技巧

11-24
这几年越来越多的开发团队使用了Git,掌握Git的使用已经越来越重要,已经是一个开发者必备的一项技能;但很多人在刚开始学习Git的时候会遇到很多疑问,比如之前使用过SVN的开发者想不通Git提交代码为什么需要先commit然后再去push,而不是一条命令一次性搞定; 更多的开发者对Git已经入门,不过在遇到一些代码冲突、需要恢复Git代码时候就不知所措,这个时候哪些对 Git掌握得比较好的少数人,就像团队中的神一样,在队友遇到 Git 相关的问题的时候用各种流利的操作来帮助队友于水火。 我去年刚加入新团队,发现一些同事对Git的常规操作没太大问题,但对Git的理解还是比较生疏,比如说分支和分支之间的关联关系、合并代码时候的冲突解决、提交代码前未拉取新代码导致冲突问题的处理等,我在协助处理这些问题的时候也记录各种问题的解决办法,希望整理后通过教程帮助到更多对Git操作进阶的开发者。 本期教程学习方法分为“掌握基础——稳步进阶——熟悉协作”三个层次。从掌握基础的 Git的推送和拉取开始,以案例进行演示,分析每一个步骤的操作方式和原理,从理解Git 工具的操作到学会代码存储结构、演示不同场景下Git遇到问题的不同处理方案。循序渐进让同学们掌握Git工具在团队协作中的整体协作流程。 在教程中会通过大量案例进行分析,案例会模拟在工作中遇到的问题,从最基础的代码提交和拉取、代码冲突解决、代码仓库的数据维护、Git服务端搭建等。为了让同学们容易理解,对Git简单易懂,文章中详细记录了详细的操作步骤,提供大量演示截图和解析。在教程的最后部分,会从提升团队整体效率的角度对Git工具进行讲解,包括规范操作、Gitlab的搭建、钩子事件的应用等。 为了让同学们可以利用碎片化时间来灵活学习,在教程文章中大程度降低了上下文的依赖,让大家可以在工作之余进行学习与实战,并同时掌握里面涉及的Git不常见操作的相关知识,理解Git工具在工作遇到的问题解决思路和方法,相信一定会对大家的前端技能进阶大有帮助。
©️2020 CSDN 皮肤主题: 书香水墨 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值