最近公司有个电视端的项目,对于从未接触过TV端开发的我来说是一种跳转,同时也是一个机遇。TV端开发和手机端开发最大的 不同是焦点的处理以及获取焦点时的酷炫效果。本例子主要实现了利用HorizontalGridView来实现水平滑动的gridview以及获取焦点时的特效。

刚拿到效果时,感觉so easy!可真正到动手写代码时,却卡到了获取焦点时的特效了。上网查了好多资料,但是有关TV端的开发却非常少。于是,自己就尝试分析实现方式。获取焦点时的具体需求是这样的:获取焦点时,整个图片在原来的基础上放大到1.15倍,并在外层有种选中时带有阴影的高亮的图片。通过分析,使用动画来实现较为简单。经过尝试,放大实现了,但是达不到预期效果。经过多次尝试,终于实现了最终效果。基本效果图如下(由于是测试内容,UI比较丑,请见谅偷笑):

接下来就一步一步介绍具体的实现方案。

由于项目中使用了HorizontalGridView,所以要引入依赖

compile 'com.android.support:leanback-v17:24.2.1'

此外使用HorizontalGridView还需要在清单文件中进行声明下

    <uses-feature
        android:name="android.software.leanback"
        android:required="false" />

到此,准备工作就完毕了,接下来就开始写布局文件了。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:background="@drawable/index_bg"
    android:layout_height="match_parent">

    <android.support.v17.leanback.widget.HorizontalGridView
        android:id="@+id/horizontalgridview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="10dp"
        app:numberOfRows="2" />
</RelativeLayout>

接下来,就需要在JAVA代码去实现了。

        horizontalgridview=(HorizontalGridView) findViewById(R.id.horizontalgridview);
        horizontalgridview.requestFocus();
        for (int i=0;i<50;i++)
            mdatas.add("这是测试的"+i);
        MyAdapter adapter=new MyAdapter(this,mdatas);
        horizontalgridview.setAdapter(adapter);

最为关键的就是Adapter的,在这里面要完成获取焦点时的特效,以及通过接口实现Item点击时的处理。

首先,我们自定义一个接口,完成item点击和获取焦点的回调:

public interface OnItemCallBack {
    public void onFocusChange(View v, boolean hasFocus, int posiotion);

    public void onItemClick(View v, int position);
}

接下来,自定义一个内部类,完成点击事件的处理,具体代码如下:

 private class MyClick implements View.OnClickListener {

        int position;

        public MyClick(int position) {
            this.position = position;
        }

        @Override
        public void onClick(View v) {
            if (onItemCallBack != null) {
                onItemCallBack.onItemClick(v, position);
            }
        }

    }
    public void setOnItemCallBack(OnItemCallBack onItemCallBack) {
        this.onItemCallBack = onItemCallBack;
    }

然后,在定义一个处理获取焦点的内部类,完成获取交单时的处理,具体代码如下:

 private class MyFocusChange implements View.OnFocusChangeListener {

        int position;
        MyViewHolder holder;

        public MyFocusChange(int position, MyViewHolder holder) {
            this.position = position;
            this.holder = holder;
        }

        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if (hasFocus) {
                holder.rl_scale.animate().scaleX(1.15f).scaleY(1.15f).start();
                holder.rl_scale.setBackgroundResource(R.drawable.bg_pic_s);
            } else {
                holder.rl_scale.animate().scaleX(1f).scaleY(1f).start();
                holder.rl_scale.setBackgroundResource(R.drawable.bg_pic_n);
            }
            if (onItemCallBack != null) {
                onItemCallBack.onFocusChange(v, hasFocus, position);
            }
        }

    }

到此,整个功能就实现了,最后粘上Adapter的整个代码:

package cn.chinaiptv.horiziengridviewdemo;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import java.util.ArrayList;

/**
 * Created by Administrator on 2016/12/9.
 */

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
    private Context context;
    private ArrayList<String> mdatas;
    private OnItemCallBack onItemCallBack;
    public MyAdapter(Context context, ArrayList<String> mdatas) {
        this.context = context;
        this.mdatas = mdatas;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View inflate = LayoutInflater.from(context).inflate(
                R.layout.item, null);
        MyViewHolder holder = new MyViewHolder(inflate);
        return holder;
    }

    @Override
    public void onBindViewHolder(MyAdapter.MyViewHolder holder, int position) {
        holder.tv_text.setText(mdatas.get(position));
        holder.itemView.setOnClickListener(new MyClick(position));
        holder.itemView.setOnFocusChangeListener(new MyFocusChange(position,
                holder));
    }

    @Override
    public int getItemCount() {
        return mdatas.size();
    }

    class MyViewHolder extends RecyclerView.ViewHolder{
        public ImageView iv_pic;
        public TextView tv_text;
        public RelativeLayout rl_scale;
        public MyViewHolder(View itemView) {
            super(itemView);
            iv_pic=(ImageView) itemView.findViewById(R.id.iv_pic);
            tv_text=(TextView) itemView.findViewById(R.id.tv_text);
            rl_scale=(RelativeLayout) itemView.findViewById(R.id.rl_scale);
        }
    }


    private class MyFocusChange implements View.OnFocusChangeListener {

        int position;
        MyViewHolder holder;

        public MyFocusChange(int position, MyViewHolder holder) {
            this.position = position;
            this.holder = holder;
        }

        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if (hasFocus) {
                holder.rl_scale.animate().scaleX(1.15f).scaleY(1.15f).start();
                holder.rl_scale.setBackgroundResource(R.drawable.bg_pic_s);
            } else {
                holder.rl_scale.animate().scaleX(1f).scaleY(1f).start();
                holder.rl_scale.setBackgroundResource(R.drawable.bg_pic_n);
            }
            if (onItemCallBack != null) {
                onItemCallBack.onFocusChange(v, hasFocus, position);
            }
        }

    }

    private class MyClick implements View.OnClickListener {

        int position;

        public MyClick(int position) {
            this.position = position;
        }

        @Override
        public void onClick(View v) {
            if (onItemCallBack != null) {
                onItemCallBack.onItemClick(v, position);
            }
        }

    }
    public void setOnItemCallBack(OnItemCallBack onItemCallBack) {
        this.onItemCallBack = onItemCallBack;
    }
}

到此,就完美实现了此功能。以上仅是自己的见解,如有不足之处欢迎讨论。


版权声明:本文为dongdengke123789原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/dongdengke123789/article/details/53541833