本文来自网易云社区

作者:孙有军

最后我们再来看看好友界面,改界面本地是没有xml的,因此我们直接来看看代码:

这里将使用到数据bean,与数据源的代码也贴出来如下:

public class Contact implements Parcelable {

    private String phone;

    private int headResId;

    private String name;

    public String getPhone() {
        return phone;
    }     public void setPhone(String phone) {
        this.phone = phone;
    }     public int getHeadResId() {
        return headResId;
    }     public void setHeadResId(int headResId) {
        this.headResId = headResId;
    }     public String getName() {
        return name;
    }     public void setName(String name) {
        this.name = name;
    }     public Contact() {     }     public Contact(Parcel in) {
        phone = in.readString();
        headResId = in.readInt();
        name = in.readString();
    }     public int describeContents() {
        return 0;
    }     @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(phone);
        dest.writeInt(headResId);
        dest.writeString(name);
    }     @Override
    public String toString() {
        StringBuilder sb = new StringBuilder(200);
        sb.append("Contact{");
        sb.append("phone='" + phone + '\'');
        sb.append(", headResId='" + headResId + '\'');
        sb.append(", name='" + name + '\'');
        sb.append('}');
        return sb.toString();
    }     public static final Creator CREATOR = new Creator() {
        public Contact createFromParcel(Parcel in) {
            return new Contact(in);
        }         public Contact[] newArray(int size) {
            return new Contact[size];
        }
    };
} //////
public class ContactProvider {     private static List<Contact> contactList;
    private static Context sContext;     private static int[] head = {R.drawable.avater1, R.drawable.avater2, R.drawable.avater3, R.drawable.avater4, R
            .drawable.avater5, R.drawable.avater6, R.drawable.avater7, R.drawable.avater8, R.drawable.avater9, R
            .drawable.avater10, R.drawable.avater11, R.drawable.avater12};     private static String[] names = {"梦洁", "雅静", "韵寒", "莉姿", "沛玲", "欣妍", "歆瑶", "凌菲", "靖瑶", "瑾萱", "芳蕤", "若华"};     private static String[] phones = {"18618188630", "18158103936", "18620145337", "15116333186", "18618188630",
            "18158103936", "18620145337", "15116333186", "18618188630", "18158103936", "18620145337", "18767106408"};     public static void setContext(Context context) {
        if (sContext == null)
            sContext = context;
    }     public static List<Contact> getContactList() {
        buildContact();
        return contactList;
    }     public static List<Contact> buildContact() {
        if (null != contactList) {
            return contactList;
        }
        contactList = new ArrayList<Contact>();
        for (int i = 0; i < 12; ++i) {
            contactList.add(buildContactInfo(phones[i], names[i], head[i]));
        }
        return contactList;
    }     private static Contact buildContactInfo(String phone, String name, int resId) {
        Contact contact = new Contact();
        contact.setPhone(phone);
        contact.setName(name);
        contact.setHeadResId(resId);
        return contact;
    }
}
/*
 * VerticalGridFragment shows a grid of videos
 */
public class VerticalGridFragment extends android.support.v17.leanback.app.VerticalGridFragment {
    private static final String TAG = "VerticalGridFragment";     private static final int DEFAULT_COLUMNS = 4;     private int numColumns = DEFAULT_COLUMNS;     private ArrayObjectAdapter mAdapter;     @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.d(TAG, "onCreate");
        super.onCreate(savedInstanceState);
        //setTitle(getString(R.string.vertical_grid_title));
        getParams();
        setupFragment();
    }     @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View root = super.onCreateView(inflater, container, savedInstanceState);
        return root;
    }     private void setupFragment() {
        VerticalGridPresenter gridPresenter = new VerticalGridPresenter(FocusHighlight.ZOOM_FACTOR_NONE);
        gridPresenter.setNumberOfColumns(numColumns);
        //gridPresenter.setShadowEnabled(false);
        setGridPresenter(gridPresenter);         mAdapter = new ArrayObjectAdapter(new ContactPresenter());         List<Contact> contacts = ContactProvider.getContactList();
        mAdapter.addAll(0, contacts);         setAdapter(mAdapter);         setOnItemViewClickedListener(new ItemViewClickedListener());
        setOnItemViewSelectedListener(new ItemViewSelectedListener());
    }     public void getParams() {
        if (getArguments() != null) {
            numColumns = getArguments().getInt(Extra.COLUMNS);
        }
    }     private final class ItemViewClickedListener implements OnItemViewClickedListener {
        @Override
        public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item, RowPresenter.ViewHolder
                rowViewHolder, Row row) {             if (item instanceof Contact) {
                Contact contact = (Contact) item;
                // TODO
            }
        }
    }     private final class ItemViewSelectedListener implements OnItemViewSelectedListener {
        @Override
        public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item, RowPresenter.ViewHolder
                rowViewHolder, Row row) {
        }
    } }

在Fragment中我们自己实现了一个ContactPresenter,该Presenter是仿照官方的CardPresenter,但是CardPresenter中使用的ImageCardView是系统support包中提供的控件,而ContactPresenter中使用的是自己自定义的控件, 代码如下:

public class ContactPresenter extends Presenter {
    private static final String TAG = "CardPresenter";
    private static int sSelectedBackgroundColor;
    private static int sDefaultBackgroundColor;     @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent) {
        Log.d(TAG, "onCreateViewHolder");         sDefaultBackgroundColor = parent.getResources().getColor(R.color.white_35_transparent);
        sSelectedBackgroundColor = parent.getResources().getColor(R.color.white_60_transparent);         ContactView contactView = new ContactView(parent.getContext()) {
            @Override
            public void setSelected(boolean selected) {
                updateCardBackgroundColor(this, selected);
                super.setSelected(selected);
            }
        };         contactView.setFocusable(true);
        contactView.setFocusableInTouchMode(true);
        updateCardBackgroundColor(contactView, false);
        return new ViewHolder(contactView);
    }     private static void updateCardBackgroundColor(ContactView view, boolean selected) {
        int color = selected ? sSelectedBackgroundColor : sDefaultBackgroundColor;
        view.setBackgroundColor(color);
        //view.findViewById(R.id.info_field).setBackgroundColor(color);
    }     @Override
    public void onBindViewHolder(ViewHolder viewHolder, Object item) {
        Contact contact = (Contact) item;
        ContactView contactView = (ContactView) viewHolder.view;
        Log.d(TAG, "onBindViewHolder");
        contactView.setHead(contact.getHeadResId());
        contactView.setName(contact.getName());
        contactView.setPhone(contact.getPhone());     }     @Override
    public void onUnbindViewHolder(ViewHolder viewHolder) {
        Log.d(TAG, "onUnbindViewHolder");
        ContactView contactView = (ContactView) viewHolder.view;
        // Remove references to images so that the garbage collector can free up memory
        contactView.setHead(0);
    }
}

ContactView是一个继承自LinearLayout的自定义控件,包含了一个ImageView和两个TextView。

到此整个界面的代码就完成了,接下来我们来看看遇到的问题。

问题列表

问题1:控件遥控器不能选中,不能导航

出现这种问题往往是控件没有设置android:focusable="true"属性,只有默认能够选中焦点的才不需要设置改属性,比如Button,EditText。

问题2:控件选中后,看不出选中效果

由于默认选中是没有视觉效果的,因此你需要对控件设置选中效果,比如说背景图片,以前在手机上可能只需要设置selector中的pressed属性,或者selected属性,现在针对TV你必须要设置focused属性,比如拨号键盘选中后会出现一个圆形的选中背景框,

要实现上述效果,因此对每一键盘输入按钮添加如下的selector。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">     <item android:drawable="@drawable/key_board_hover" android:state_focused="true"></item>
    <item android:drawable="@drawable/key_board_hover" android:state_pressed="true"></item>
    <item android:drawable="@drawable/key_board_hover" android:state_checked="true"></item>
    <item android:drawable="@color/transparent"></item> </selector> key_board_hover.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="oval">
    <solid android:color="@color/white_35_transparent"></solid>
    <size
        android:width="40dp"
        android:height="40dp"/>
</shape>

网易云免费体验馆,0成本体验20+款云产品!

更多网易研发、产品、运营经验分享请访问网易云社区

相关文章:
【推荐】 30分钟,让你彻底明白Promise原理
【推荐】 【网易严选】iOS持续集成打包(Jenkins+fastlane+nginx)
【推荐】 接口文档神器Swagger(上篇)

Android TV 开发(4)的更多相关文章

  1. Android TV开发总结(六)构建一个TV app的直播节目实例

    请尊重分享成果,转载请注明出处:http://blog.csdn.net/hejjunlin/article/details/52966319 近年来,Android TV的迅速发展,传统的有线电视受 ...

  2. Android TV开发总结(五)TV上屏幕适配总结

    前言:前面几篇总结一些TV上的小Sample,开源到GitHub:https://github.com/hejunlin2013/TVSample, 点击链接,可以持续关注.今天总结下TV上屏幕适配. ...

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

    转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52835829 前言:上篇中,&l ...

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

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

  5. Android TV开发总结(七)构建一个TV app中的剧集列表控件

    原文:Android TV开发总结(七)构建一个TV app中的剧集列表控件 版权声明:我已委托"维权骑士"(rightknights.com)为我的文章进行维权行动.转载务必转载 ...

  6. Android TV开发中所有的遥控器按键监听及注意事项,新增home键监听

    原文:Android TV开发中所有的遥控器按键监听及注意事项,新增home键监听 简单记录下android 盒子开发遥控器的监听 ,希望能帮到新入门的朋友们 不多说,直接贴代码 public cla ...

  7. Android TV开发总结(四)通过RecycleView构建一个TV app列表页(仿腾讯视频TV版)

    转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52854131 前言:昨晚看锤子手 ...

  8. Android TV开发总结(二)构建一个TV Metro界面(仿泰捷视频TV版)

    前言:上篇是介绍构建TV app前要知道的一些事儿,开发Android TV和手机本质上没有太大的区别,屏大,焦点处理,按键处理,是有别于有手机和Pad的实质区别.今天来介绍TV中Metro UI风格 ...

  9. Android TV 开发 (1)

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

  10. Android TV开发总结(一)构建一个TV app前要知道的事儿

    转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52792562 前言:近年来,智能 ...

随机推荐

  1. echarts使用中的那些事儿(一)

    近来由于有几个小项目要用到echarts里的一些图,不得不使用,可是要完全按照自己的意愿来,要对它有些了解,要翻阅资料,遂有以下小结: 1.最开始第一步是把数据调出来就行,能在图上显示就成,以下是最开 ...

  2. vc++ 6.0编译后生成的文件

    程序在编译后,在目标路径下会生成多个文件    Debug文件夹(*.exe,*.ilk,*.obj,*.pch,*.pdb,*.idb,*,pdb),*.cpp,*.dsp,*.ncb,*.plg  ...

  3. sublimetext3安装配置

    官网:http://www.sublimetext.com/ 中文官网:http://www.sublimetextcn.com/ 包管理器:https://packagecontrol.io/ins ...

  4. Neo4j-3.0.3 (Debian 8)

    平台: Ubuntu 类型: 虚拟机镜像 软件包: neo4j-3.0.3 basic software database graph database infrastructure neo4j op ...

  5. Coursera_Learn how to learn笔记

    番茄工作法,隔20分钟休息一次. 构建组块步骤:1.集中注意力. 2.理解基本概念. 3.进行练习. 获得专业知识的第一步是创建概念组块,能够将分散的信息集合到一起. Recall(回顾)比反复阅读更 ...

  6. 8. String to Integer

    Implement atoi to convert a string to an integer. Hint: Carefully consider all possible input cases. ...

  7. vue组件 $children,$refs,$parent的使用

    如果项目很大,组件很多,怎么样才能准确的.快速的寻找到我们想要的组件了?? 1)$refs 首先你的给子组件做标记.demo :<firstchild ref="one"&g ...

  8. python_65_生成器1

    # map()函数 # map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回. # 例 ...

  9. yield 生成器的运行机制

    yield 生成器的运行机制 当你问生成器要一个数时,生成器会执行,直至出现 yield 语句,生成器把 yield 的参数给你,之后生成器就不会往下继续运行. 当你问他要下一个数时,他会从上次的状态 ...

  10. 2013.10.26工作Fighting(1)

    1.今天虽然花费了六个小时来解决一个功能,最后用一行代码来搞定了. ----遇到问题,解决的办法总是比问题多. 2.给你分配有难度的任务,应该是激动.这样才能挑战自我,学得到很多兴奋的新东西. --- ...