VerticalGridView第一行获取焦点后,再次按向上键,上方的控件获取不到焦点解决方案

来源:互联网 发布:vm虚拟机没网络 编辑:程序博客网 时间:2024/05/16 09:05

最近在做项目中,有这么一个需求。点击电视剧某一集进入详情页,并可以点击选集按钮进行选集。于是乎,想到了使用VerticalGridView来实现(VerticalGridView是V17新推出的控件,不熟悉的朋友可以查找资料学习下)。使用VerticalGridView很容易实现了基本的功能,但是遇到一个很棘手的问题。就是当第一行获取焦点后,再次按向上键,上方的控件获取不到焦点。在网上找了好多解决方案,最终也没有解决问题。最后,使用setOnKeyListner方法来实现。虽说解决了问题,带来了新的问题:在第二行按向上键后,第一行先获取到焦点,接着第一行有失去焦点,上方控件获取到焦点了。尼玛,我也是醉了。最终发现onKey方法执行了两次,知道了原因,问题就好解决了。下面,就介绍下实现方案。

本Demo还实现了,获取焦点高亮显示的效果。VerticalGridView的使用不在介绍,不熟悉的可以参考 

android leanback使用详解以及获取焦点高亮

首先,布局页面编写:

(1)主布局页面

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:lb="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="@drawable/index_bg"    android:orientation="vertical">    <LinearLayout        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginTop="@dimen/h_56"        android:orientation="horizontal">        <View            android:id="@+id/btn_pd_play"            style="@style/pd_btn"            android:background="@drawable/pd_play_selector"            android:visibility="visible" />        <View            android:id="@+id/btn_pd_collect"            style="@style/pd_btn.non_starter"            android:background="@drawable/pd_collect_selector"            android:visibility="visible" />        <View            android:id="@+id/btn_pd_xuanji"            style="@style/pd_btn.non_starter"            android:visibility="visible" />    </LinearLayout>    <android.support.v17.leanback.widget.HorizontalGridView        android:id="@+id/hv_tuijian"        android:layout_width="match_parent"        android:layout_height="@dimen/h_400"        android:layout_marginLeft="@dimen/w_145"        android:layout_marginRight="@dimen/w_115"        android:focusable="true"        android:focusableInTouchMode="true"        lb:horizontalMargin="@dimen/w_15"        lb:numberOfRows="1"></android.support.v17.leanback.widget.HorizontalGridView>    <android.support.v17.leanback.widget.VerticalGridView        android:id="@+id/hv_suanji"        android:layout_width="match_parent"        android:layout_height="@dimen/h_480"        android:layout_marginLeft="@dimen/w_145"        android:layout_marginRight="@dimen/w_115"        android:focusable="true"        android:focusableInTouchMode="true"        android:paddingTop="@dimen/h_10"        lb:horizontalMargin="@dimen/w_15"        lb:numberOfColumns="10"        lb:numberOfRows="2"></android.support.v17.leanback.widget.VerticalGridView></LinearLayout>

(2)item布局页面

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/ll_item_search"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:clipChildren="false"    android:clipToPadding="false"    android:focusable="true"    android:focusableInTouchMode="true"    android:orientation="vertical" >    <RelativeLayout        android:id="@+id/rl_scale"        android:layout_width="@dimen/w_220"        android:layout_height="@dimen/h_260"        android:background="@drawable/bg_pic_n" >        <ImageView            android:id="@+id/iv_pic"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:background="@drawable/mid_bottom"            android:scaleType="fitXY" />        <TextView            android:id="@+id/tv_target"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_alignBottom="@id/iv_pic"            android:textColor="@color/search_text"            android:gravity="center"            android:padding="@dimen/w_10"            android:text="更新至"            android:textSize="@dimen/w_30"            android:visibility="gone" />    </RelativeLayout>    <FrameLayout        android:layout_width="@dimen/w_220"        android:layout_height="wrap_content"        android:layout_below="@id/rl_scale"        android:layout_centerHorizontal="true"        android:layout_marginTop="@dimen/h_2" >        <TextView            android:id="@+id/tv_name"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_gravity="center"            android:singleLine="true"            android:textColor="@color/search_text"            android:textSize="@dimen/w_32" />    </FrameLayout></RelativeLayout>

接着,编写通用的适配器:

package cn.chinaiptv.foucedemo.adapter;import android.support.v7.widget.RecyclerView;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import java.util.Collections;import java.util.Comparator;import java.util.List;/** * @author zeng_yong_chang@163.com */public abstract class RvAdapter<T, VH extends RecyclerView.ViewHolder> extends        RecyclerView.Adapter<VH> {    protected List<T> mList;    public RvAdapter(List<T> data) {        setData(data);    }    public List<T> getData() {        return mList;    }    public void setData(List<T> data) {        mList = data;        notifyDataSetChanged();    }    public void sort(Comparator<T> comparator) {        Collections.sort(mList, comparator);        notifyDataSetChanged();    }    protected View inflateView(int itemViewLayoutId, ViewGroup parent) {        return LayoutInflater.from(parent.getContext()).inflate(                itemViewLayoutId, parent, false);    }    @Override    public int getItemCount() {        return mList.size();    }}

其次,VerticalGridView适配器的编写,具体代码如下:
package cn.chinaiptv.foucedemo.adapter;import android.annotation.SuppressLint;import android.content.Context;import android.support.v17.leanback.widget.VerticalGridView;import android.support.v7.widget.RecyclerView.Adapter;import android.view.KeyEvent;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import java.util.List;import cn.chinaiptv.foucedemo.R;import cn.chinaiptv.foucedemo.bean.Content;import cn.chinaiptv.foucedemo.cn.chinaiptv.foucedemo.holder.SearchListViewHolder;import cn.chinaiptv.foucedemo.utils.FocusUtisl;@SuppressLint("InflateParams")public class XuanJiAdapter extends        Adapter<SearchListViewHolder> {    private List<Content> contentList;    private Context context;    private VerticalGridView hv_suanji;    private View btn_pd_xuanji;    public XuanJiAdapter(List<Content> recommenList, VerticalGridView hv_suanji, View btn_pd_xuanji) {        contentList = recommenList;        this.hv_suanji = hv_suanji;        this.btn_pd_xuanji = btn_pd_xuanji;    }    @Override    public int getItemCount() {        return contentList.size();    }    @Override    public void onBindViewHolder(final SearchListViewHolder holder, final int position) {        holder.itemView.setOnClickListener(new FocusUtisl.MyClick(position));        holder.itemView.setOnFocusChangeListener(new FocusUtisl.MyFocuchange(holder.rl_scale, holder.tv_name,                position));        String name = "";        String miniPicURI = "";        Content content = contentList.get(position);        name = content.getName();        miniPicURI = content.getMiniPicURI();        holder.tv_name.setText(name);    }    @Override    public SearchListViewHolder onCreateViewHolder(ViewGroup parent, int arg1) {        View inflate = LayoutInflater.from(parent.getContext()).inflate(                R.layout.item_serialdetail_recomm, null);        SearchListViewHolder holder = new SearchListViewHolder(inflate);        context = parent.getContext();        return holder;    }}

接下来就要在Activity中设置数据了,代码如下:

package cn.chinaiptv.foucedemo;import android.app.Activity;import android.os.Bundle;import android.support.v17.leanback.widget.HorizontalGridView;import android.support.v17.leanback.widget.VerticalGridView;import android.view.View;import java.util.ArrayList;import cn.chinaiptv.foucedemo.adapter.SerialDetailRecommAdapter;import cn.chinaiptv.foucedemo.adapter.XuanJiAdapter;import cn.chinaiptv.foucedemo.bean.Content;/** * 连续剧详情页 */public class MainActivity extends Activity {    private  HorizontalGridView hv_tuijian;    private VerticalGridView hv_suanji;    private  XuanJiAdapter xuanjiAdapter;    private View btn_pd_xuanji;    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_series_detail);        btn_pd_xuanji=findViewById(R.id.btn_pd_xuanji);        initView();    }    private void initView() {        hv_tuijian=(HorizontalGridView)findViewById(R.id.hv_tuijian);        hv_suanji=(VerticalGridView)findViewById(R.id.hv_suanji);        getListRecommen();        getXuanJi();    }    private  ArrayList<Content> recommenList;    private  ArrayList<Content> xuanJiList;    private SerialDetailRecommAdapter recommenResultAdapter;    /**     * 获取可能要找的内容     */    private void getListRecommen() {        recommenList=new ArrayList<Content>();        for(int i=0;i<10;i++){            Content content=new Content();            content.setName("十月风暴"+i);            content.setType("ddd");            recommenList.add(content);        }        recommenResultAdapter = new SerialDetailRecommAdapter(recommenList);        hv_tuijian.setAdapter(recommenResultAdapter);    }    /**     * 获取可能要找的内容     */    private void getXuanJi() {        xuanJiList=new ArrayList<Content>();        for(int i=0;i<20;i++){            Content content=new Content();            content.setName("测试"+i);            content.setType("ddd");            xuanJiList.add(content);        }        xuanjiAdapter = new XuanJiAdapter(xuanJiList,hv_suanji,btn_pd_xuanji);        hv_suanji.setAdapter(xuanjiAdapter);    }}


如果只这样去实现,第一行获取焦点后,再按向上键,上方的控件是获取不到代码的。解决方案如下:
  @Override    public void onBindViewHolder(final SearchListViewHolder holder, final int position) {        holder.itemView.setOnClickListener(new FocusUtisl.MyClick(position));        holder.itemView.setOnFocusChangeListener(new FocusUtisl.MyFocuchange(holder.rl_scale, holder.tv_name,                position));        String name = "";        String miniPicURI = "";        Content content = contentList.get(position);        name = content.getName();        miniPicURI = content.getMiniPicURI();        holder.tv_name.setText(name);        holder.itemView.setOnKeyListener(new View.OnKeyListener() {            @Override            public boolean onKey(View v, int keyCode, KeyEvent event) {                if (event.getAction() == KeyEvent.ACTION_UP) {                    return true;                } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {                    if (position < 10) {                        hv_suanji.setFocusable(false);                        btn_pd_xuanji.requestFocus();                    }                }                return false;            }        });    }
这样上方的控件就可以获取到焦点了。

最后,还有一些获取焦点时,高亮显示的方法,代码如下:

package cn.chinaiptv.foucedemo.utils;import android.view.View;import cn.chinaiptv.foucedemo.R;/** * Created by ddklsy163com on 17/1/13. */public class FocusUtisl {    private static OnItemCallBack onItemCallBack;    public static class MyFocuchange implements View.OnFocusChangeListener {        int position;        View rl_scale;        View tv_name;        /**         * 图片,文字都放缩         *         * @param position         * @param rl_scale         */        public MyFocuchange(View rl_scale, View tv_name, int position) {            this.position = position;            this.rl_scale = rl_scale;            this.tv_name = tv_name;//            Log.e("111111",position);        }        /**         * 仅仅放缩图片         *         * @param position         * @param rl_scale         */        public MyFocuchange(int position, View rl_scale) {            this.position = position;            this.rl_scale = rl_scale;        }        @Override        public void onFocusChange(View v, boolean hasFocus) {            if (hasFocus) {                if (rl_scale != null) {                    rl_scale.animate().scaleX(1.1f).scaleY(1.1f).start();                    rl_scale.setBackgroundResource(R.drawable.bg_pic_s);                }                if (tv_name != null)                    tv_name.animate().scaleX(1.1f).scaleY(1.1f).start();            } else {                if (rl_scale != null) {                    rl_scale.animate().scaleX(1.f).scaleY(1.f).start();                    rl_scale.setBackgroundResource(R.drawable.bg_pic_n);                }                if (tv_name != null)                    tv_name.animate().scaleX(1f).scaleY(1f).start();            }            if (onItemCallBack != null) {                onItemCallBack.onFocusChange(v, hasFocus, position);            }        }    }    public static 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;    }    public interface OnItemCallBack {        public void onFocusChange(View v, boolean hasFocus, int posiotion);        public void onItemClick(View v, int position);    }}

到此,已经完美实现了获取焦点时高亮显示,并且解决了上方控件获取不到焦点的bug,Demo截图如下:



源码点击下载

0 0
原创粉丝点击