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
- VerticalGridView第一行获取焦点后,再次按向上键,上方的控件获取不到焦点解决方案
- android控件焦点的获取(解决一开始加载顶部广告获取不到焦点的问题)
- ListViewItem获取不到焦点
- 让获取不到焦点
- 获取 拥有焦点的控件
- Android WebView 文本框获取焦点后自动放大的解决方案
- 记录EditText获取焦点后无法编辑 的解决方案
- 按Enter键获取下一个控件的焦点
- android控件获取焦点
- Android控件获取焦点
- Unity嵌入Android后Android视图获取不到事件焦点
- RecycleView添加HeaderView宽度不能撑满,第一次加载HeaderView的子控件获取不到焦点
- Asp .NET控件获取焦点的常见问题
- Delphi获取焦点所在的控件名
- ListView item项中包含某些可以抢焦点的控件导致无法获取焦点问题的解决方案
- java GUI中JTextField的requestFocus()方法获取不到焦点
- Android解决自定义View获取不到焦点的情况
- Android之ListView的item获取不到焦点问题
- 工业物联网平台记录,汇总一下联网平台
- Android如何修改屏幕最低的亮度值
- The Lazy Cow(前缀和)
- 什么,Base64 算法你用的哪个?不就一种算法实现吗
- beans.xml配置文件中注入对象的集合
- VerticalGridView第一行获取焦点后,再次按向上键,上方的控件获取不到焦点解决方案
- Android NFC开发
- Github优秀web前端资源收集
- 获取屏幕高宽,在代码中设置控件大小的方法
- C++学习笔记之类的构造函数
- 云计算期末报告无图 kmeans和最短路径算法hadoop实现详解
- iOS常用框架总结
- 集合框架_ArrayList集合嵌套HashMap集合的案例
- 【jzoj3853】【帮助Bsny】【状态压缩动态规划】