天天看点

androidTV中使用recyclerview并使其item在获取焦点后获取边框,并伴随放大,凸显效果

第一次开发androidTV端,虽然页面很简单,但心中还是难免有些忐忑呢!还好有众多大神帮助,现已见成效啦!androidTV端与android手机端整体上是一致的,唯一不同的地方在于TV端存在焦点,视图的选取需要先将焦点移到这个view上,当界面出现的时候,焦点是默认在电视端的最上方的,当然首先你需要在xml中设置focusable=true,这样这个view才有获取焦点的能力:

<ImageView
        android:id="@+id/login"
        android:layout_width="@dimen/width_login_iv"
        android:layout_height="@dimen/height_login_iv"
        android:layout_marginLeft="@dimen/marginLeft_login_iv"
        android:layout_marginTop="@dimen/marginTop_login_iv"
        android:background="@drawable/login_selector"
        android:focusable="true"
        android:onClick="logIn1"/>
           

所以大家没必要太惧怕哈!闲话不说先上效果图:

androidTV中使用recyclerview并使其item在获取焦点后获取边框,并伴随放大,凸显效果
androidTV中使用recyclerview并使其item在获取焦点后获取边框,并伴随放大,凸显效果

这次我使用图片的根布局是recyclerview,item的根布局是cardview,究其原因主要是我在开发前期不知从哪听来的电视端recyclerview和cardview是标配,其实用什么都好啦,毕竟时间有限,速速码字哈!

险些跑题,我是来将获取焦点突出,放大,加item边框的好么!

首先一定要在recyclerview中设置focusable=true!这样你里面的item才有能力获取焦点,下面问题来了,当获取焦点时,效果怎么出来呢?首先讲一下放大效果:

在android5.0以后才出现的Z轴的概念,所以我直接一步到位,在recyclerview的adapter中onBindViewHolder下:

holder.itemView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
       //获取焦点时变化
        if (hasFocus) {
            if(Build.VERSION.SDK_INT>=21){
                ViewCompat.animate(v).scaleX(1.17f).scaleY(1.17f).translationZ(1).start();
	
	}
           

这样就可以完美的解决item叠加的问题( 我说的是改变z轴)

都怪google出z轴出的太晚了,现在电视端使用的盒子大多都在5.0以下,我在使用5.0以下版本的盒子的时候出现了item叠加的问题,如图(全是泪):

androidTV中使用recyclerview并使其item在获取焦点后获取边框,并伴随放大,凸显效果

我们知道出现item叠加的愿意是因为系统绘制也是一个一个绘制的先画的左上一,其他在他后面画的,所以当先画的出现放大效果的时候,如果在5.0之前没有z轴的概念且选中item附近有在其之后绘制的情况下,那么该放大item就会在其他item下面展现放大效果,着实蛋疼。说完就打脸,又想到了在网上得到广泛使用的view.bringToFront();试了一下,未果,原因不详。苦苦思寻好久,没办法了,只好改变其绘制顺序了,问题得以解决:

首先在是主界面绑定

rvMain.setChildDrawingOrderCallback(adapter);
rvMain.setAdapter(adapter);
           

随后在主界面实现:

public class MainRecyclerViewAdapter extends RecyclerView.Adapter<MainRecyclerViewAdapter.Holder> implements RecyclerView.ChildDrawingOrderCallback {
           

随后系统会让你重写一个方法:

@Override
    public int onGetChildDrawingOrder(int childCount, int i) {
        focusedChild = mainInterface.rvMain.getFocusedChild();
        focusViewIndex = mainInterface.rvMain.indexOfChild(focusedChild);
        if (focusViewIndex == -1) {
            return i;
        }
        if (focusViewIndex == i) {
            focusid = i;
            return childCount - 1;
        } else if (i == childCount - 1) {
            return focusid;
        } else {
            return i;
        }

    }
           

childCount是可见的item数量,i是你要绘制item的序号,里面的逻辑是调换可见childCount里最后绘制的item和焦点选中item的绘制顺序。例如里面有10个item可见的话,childCount是10,i会走10遍(0-9);我写的focusViewIndex就是焦点选中的序号,如果焦点选中第3个,focusViewIndex=2,当i=2传入的时候(我要让这个item最后一个绘制

androidTV中使用recyclerview并使其item在获取焦点后获取边框,并伴随放大,凸显效果

),此时我换回原本最后绘制的item;而当我传入原本最后绘制item需要的i时,我要返回我焦点所在的item的i。

最后在item获焦事件里写道:

//获取焦点时变化
                    if (hasFocus) {
                        if(Build.VERSION.SDK_INT>=21){
                            ViewCompat.animate(v).scaleX(1.17f).scaleY(1.17f).translationZ(1).start();
                        }else {
                            ViewCompat.animate(v).scaleX(1.17f).scaleY(1.17f).start();
                            ViewGroup parent = (ViewGroup) v.getParent();
                            parent.requestLayout();
                            parent.invalidate();

                        }
           

好了,我所理解的item获取焦点后放大的效果就是这个样子啦,另外那个背景框的问题呢就是我在item根布局里写了一个background,如图:

android:background="@drawable/item_bg_focus"
           
<pre name="code" class="html"><?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_focused="true" android:drawable="@drawable/item_boder"/>
</selector>
           
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
    <corners android:radius="5dp"/>
    <stroke android:color="@color/coloritembackgroud" android:width="5dp" />
</shape>
           

我想做到的就是尽量简单,一定会有一些地方考虑不周啦!欢迎大家一起讨论呐!

继续阅读