美文网首页Android TVAndroid TV开发技术 | 实践
针对Android Tv的自定义RecyclerView2.0横

针对Android Tv的自定义RecyclerView2.0横

作者: wenju_song | 来源:发表于2017-01-22 15:03 被阅读2290次

    版权声明:本文为博主原创文章,转载请注明出处。

    推荐:
    欢迎关注我创建的Android TV 简书专题,会定期给大家分享一些AndroidTv相关的内容:
    http://www.jianshu.com/c/37efc6e9799b


    前言:在上一篇针对Android Tv的自定义RecyclerView文章中介绍了横向的RecyclerView一些用法和实现方法。在上一篇的基础上,来实现RecyclerView横向和纵向的连动效果。

    首先上效果图:

    ezgif.com-gif-maker.gif

    新的版本在上一个版本的基础上添加了一些内容以及读者反馈的bug.具体添加的内容如下:
    1.添加了垂直的RecyclerView,并实现了可以控制横向recyclerView的效果。
    2.左右箭头点击后RecyclerView的条目不会获得焦点,解决了滑动冲突。
    3.横向RecyclerView5.0以下版本之后条目放上之后会出现被压盖的情况,这里修复了该bug。
    4.在RecyclerView内部不再提供类似于放大抬高z轴的操作,这里只提供了focus状态的接口,具体的逻辑在RecyclerView使用处提供回调。

    实现

    下面具体来分析一下。
    1.这里竖直的RecyclerView是在popupWindow中展示的。

      View popupView = getLayoutInflater().inflate(R.layout.list_menu_popwindow, null, false);
      mPopRecyclerView = (CustomRecyclerView)  popupView.findViewById(R.id.recycler_view);
      mUpArr = (ImageButton) popupView.findViewById(R.id.up_arrow);
      mDownArr = (ImageButton) popupView.findViewById(R.id.down_arrow);
      mPopupWindow = new PopupWindow(popupView, 404, 1920);
      mPopupWindow.setBackgroundDrawable(new ColorDrawable(Color.parseColor("#F8F8F8")));
      mPopupWindow.setFocusable(true);
      mPopupWindow.setOutsideTouchable(true);
      mPopupWindow.update();
    

    注意:popupWindow要设置背景。
    在popupWindow进入的时候我添加了一个进入的动画:

      mPopRecyclerView.setLayoutAnimation(PopLayoutAnimation.orderAnimation());
    

    PopLayoutAnimation相关代码如下:

    public class PopLayoutAnimation {
        private static Animation transAnim, alphaAnim;
        static LayoutAnimationController controller;
    
        public static LayoutAnimationController orderAnimation() {
            LayoutAnimationController controller;
            Animation transAnim, alphaAnim;
            AnimationSet set = new AnimationSet(false);
            transAnim = new TranslateAnimation(0, 0, -50, 0);
            transAnim.setDuration(167);
            transAnim.setFillEnabled(true);
            transAnim.setFillAfter(true);
    
            alphaAnim = new AlphaAnimation(0, 1);
            alphaAnim.setDuration(167);
            alphaAnim.setFillAfter(true);
            set.addAnimation(transAnim);
            set.addAnimation(alphaAnim);
            controller = new LayoutAnimationController(set, 1);
            controller.setDelay(0.33f);
            return controller;
        }
    
        public static LayoutAnimationController reserverAnimation(){
            AnimationSet set = new AnimationSet(false);
            transAnim = new TranslateAnimation(0, 0,50, 0);
            transAnim.setDuration(167);
            transAnim.setFillEnabled(true);
            transAnim.setFillAfter(true);
            // transAnim.setFillBefore(true);
            alphaAnim = new AlphaAnimation(0,1);
            alphaAnim.setDuration(167);
            alphaAnim.setFillAfter(true);
            set.addAnimation(transAnim);
            set.addAnimation(alphaAnim);
            controller = new LayoutAnimationController(set, 1);
            controller.setDelay(0.33f);
             controller.setOrder(LayoutAnimationController.ORDER_REVERSE);
            return controller;
        }
        public static boolean isNullAnimation(){
            if (controller==null||controller.isDone()){
                return true;
            }
            else{
                return false;
            }
        }
        public static void resetAnimation(){
            controller.start();
        }
    }
    

    2.横向的RecyclerView在使用的过程中发现在滚动的时候,鼠标放到Item上RecyclerView为了响应item获取焦点事件会停止滚动,达不到翻页的效果。这里处理了item响应时机。在RecyclerView处于idle状态时去响应。

     holder.itemView.setOnHoverListener(new View.OnHoverListener() {
                    @Override
                    public boolean onHover(View v, MotionEvent event) {
                        int what = event.getAction();
                        switch (what) {
                            case MotionEvent.ACTION_HOVER_ENTER:
                                RecyclerView recyclerView = (RecyclerView) holder.itemView.getParent();
                                int[] location = new int[2];
                                recyclerView.getLocationOnScreen(location);
                                int x = location[0];
    //                            LogUtil.i("swj","GalleryAdapter.onHover.x="+x +",width = "+(recyclerView.getWidth()+x));
                                //为了防止滚动冲突,在滚动时候,获取焦点为了显示全,会回滚,这样会导致滚动停止
                                if (recyclerView.getScrollState() == RecyclerView.SCROLL_STATE_IDLE) {
                                    //当超出RecyclerView的边缘时不去响应滚动
                                    if (event.getRawX() > recyclerView.getWidth() + x || event.getRawX() < x) {
                                        return true;
                                    }
                                    //鼠标进入view,争取到焦点
                                    v.requestFocusFromTouch();
                                    v.requestFocus();
    //                                LogUtil.i(this,"HomeTvAdapter.onHover.position:"+position);
                                    focusStatus(v, position);
                                }
                                break;
                            case MotionEvent.ACTION_HOVER_MOVE:  //鼠标在view上移动
                                break;
                            case MotionEvent.ACTION_HOVER_EXIT:  //鼠标离开view
                                normalStatus(v, position);
                                break;
                        }
                        return false;
                    }
                });
    

    3.横向RecyclerView在Android5.0以后的系统,item在hover态时是抬高z轴,5.0以下版本之后条目放上之后会出现被压盖的情况,这里调整了一下布局。达到了兼容。

    结束:

    这里的RecyclerView用法和普通的RecyclerView用法类似,至于布局的显示,可以根据自己的项目去定义。
    项目的地址:https://github.com/songwenju/CustomTvRecyclerView
    如果对你有帮助,欢迎star和fork。如有问题,欢迎反馈交流。


    推荐:
    欢迎关注我创建的Android TV 简书专题,会定期给大家分享一些AndroidTv相关的内容:
    http://www.jianshu.com/c/37efc6e9799b

    版权声明:本文为博主原创文章,转载请注明出处。

    相关文章

      网友评论

      • ddcb8f910f13: /**
        * Use with {@link #focusSearch(int)}. Move focus to the left.
        */
        public static final int FOCUS_LEFT = 0x00000011;

        /**
        * Use with {@link #focusSearch(int)}. Move focus up.
        */
        public static final int FOCUS_UP = 0x00000021;

        /**
        * Use with {@link #focusSearch(int)}. Move focus to the right.
        */
        public static final int FOCUS_RIGHT = 0x00000042;

        /**
        * Use with {@link #focusSearch(int)}. Move focus down.
        */
        public static final int FOCUS_DOWN = 0x00000082;


        我重写了上下的监听,发现没有对应的fouces——down和up的事件,这两个属性和左右不一样
        /**
        * Use with {@link #focusSearch(int)}. Move focus to the left.
        */
        public static final int FOCUS_LEFT = 0x00000011;

        /**
        * Use with {@link #focusSearch(int)}. Move focus up.
        */
        public static final int FOCUS_UP = 0x00000021;

        /**
        * Use with {@link #focusSearch(int)}. Move focus to the right.
        */
        public static final int FOCUS_RIGHT = 0x00000042;

        /**
        * Use with {@link #focusSearch(int)}. Move focus down.
        */
        public static final int FOCUS_DOWN = 0x00000082;

        这个东西左右和上下不一样,你有解决方案么?
      • JS_WANGSHA:大神,请教一个问题,如果你右侧的recycleview用语音操作,让其滑动,滑动过程中,左侧如果是listview,会抢焦点,这个怎么解决
        wenju_song:@YHHLWTV 谁抢谁的焦点?
      • 064b9db7d22c:大神,我下载你的案列·运行在我的as上,显示不完全,是不是因为不适配,怎么解决啊???
        wenju_song:@转眼即逝的流年 这里的显示是我根据我们55寸电视适配的,关键在RecyclerView 它不依赖具体的UI实现。你可以单独做一套UI。

      本文标题:针对Android Tv的自定义RecyclerView2.0横

      本文链接:https://www.haomeiwen.com/subject/ybtgbttx.html