RecyclerView的item的selected、click以及按键响应操作的简单demo
1、在布局文件中定义 RecyclerView。
<android.support.v17.leanback.widget.HorizontalGridView
android:id="@+id/horizontal_gridView_channel_group"
android:layout_width="match_parent"
android:layout_height="160dp"
android:layout_below="@+id/recyclerView_title"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp">
</android.support.v17.leanback.widget.HorizontalGridView>
HorizontalGridView是一个非常实用的水平方向的RecyclerView,它最大的特点就是焦点项始终是显示在正中间的位置。如下图中的Movies项。
2、定义RecyclerView的适配器
package com.amlogic.dvb_adapter;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.amlogic.DVBPlayer.R;
import com.amlogic.dvb_entity.GroupInfo;
import com.amlogic.dvb_interface.OnRecycleViewItemClickListener;
import com.amlogic.dvb_interface.OnRecycleViewItemSelectListener;
import com.amlogic.dvb_interface.OnRecyclerViewItemKeyListener;
import com.amlogic.dvb_util.ContactsUtil;
import com.amlogic.dvb_util.CornerUtil;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import java.util.ArrayList;
import java.util.List;
import static com.amlogic.DVBPlayer.AndroidNineMainMenu.CHANNEL_GROUP_RECYCLERVIEW_TAG;
import static com.amlogic.DVBPlayer.AndroidNineMainMenu.SETTINGS_HELP;
import static com.amlogic.DVBPlayer.AndroidNineMainMenu.SETTINGS_MYLIBRARY;
import static com.amlogic.DVBPlayer.AndroidNineMainMenu.SETTINGS_SYSTEM_ONLY;
import static com.amlogic.DVBPlayer.AndroidNineMainMenu.SETTINGS_USER_SETUP;
import static com.amlogic.DVBPlayer.AndroidNineMainMenu.TITLE_SETTINGS_ITEM;
public class ChannelGroupHorizontalGridViewAdapter extends RecyclerView.Adapter<ChannelGroupHorizontalGridViewHolder> {
private OnRecycleViewItemSelectListener mOnItemSelectLister;
private OnRecycleViewItemClickListener mOnItemClickLister;
private OnRecyclerViewItemKeyListener mOnKeyListener;
private List<GroupInfo> mGropuInfos;
private Context mContext;
private int current_title_index;
private int[] textViewDefault = {R.drawable.txt_default_blue, R.drawable.txt_default_orange, R.drawable.txt_default_purple, R.drawable.txt_default_red, R.drawable.txt_default_yellow};
private int[] imgViewDefault = {R.drawable.img_default_blue, R.drawable.img_default_orange, R.drawable.img_default_purple, R.drawable.img_default_red, R.drawable.img_default_yellow};
public ChannelGroupHorizontalGridViewAdapter(Context context, List<GroupInfo> groupInfos, int title_index) {
if (mGropuInfos == null) {
mGropuInfos = new ArrayList<>();
}
mGropuInfos.clear();
mGropuInfos.addAll(groupInfos);
current_title_index = title_index;
mContext = context;
}
@NonNull
@Override
public ChannelGroupHorizontalGridViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.channel_recycleview_item, viewGroup, false);
view.setTag(CHANNEL_GROUP_RECYCLERVIEW_TAG);
ChannelGroupHorizontalGridViewHolder holder = new ChannelGroupHorizontalGridViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(@NonNull ChannelGroupHorizontalGridViewHolder viewHolder, final int position) {
ChannelGroupHorizontalGridViewHolder ViewHolder = (ChannelGroupHorizontalGridViewHolder) viewHolder;
TextView textView = (TextView) ViewHolder.item_name;
ImageView imageView = (ImageView) ViewHolder.item_background;
textView.setText(mGropuInfos.get(position).getName());
ContactsUtil.Set_TextView_Typeface(ContactsUtil.contextTypeFace, textView);
if (mOnItemSelectLister != null) {
viewHolder.itemView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean hasFocus) {
mOnItemSelectLister.onItemSelected(view, position, hasFocus);
}
});
}
if (mOnItemClickLister != null) {
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mOnItemClickLister.onItemClick(view, position);
}
});
}
if (mOnKeyListener != null) {
viewHolder.itemView.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
return mOnKeyListener.recyclerViewItemOnKey(v, keyCode, event, position);
}
});
}
Log.d("wujiang", "ChannelGroupHorizontalGridViewAdapter: current_title_index = " + current_title_index);
if (current_title_index == TITLE_SETTINGS_ITEM) {
textView.setBackgroundResource(R.drawable.translucent_background);
switch (position) {
case SETTINGS_HELP:
Glide.with(mContext).load(R.drawable.ic_help).placeholder(R.drawable.ic_help).into(imageView);
break;
case SETTINGS_MYLIBRARY:
Glide.with(mContext).load(R.drawable.ic_my_library).placeholder(R.drawable.ic_my_library).into(imageView);
break;
case SETTINGS_USER_SETUP:
Glide.with(mContext).load(R.drawable.ic_user_setup).placeholder(R.drawable.ic_user_setup).into(imageView);
break;
case SETTINGS_SYSTEM_ONLY:
Glide.with(mContext).load(R.drawable.ic_settings).placeholder(R.drawable.ic_settings).into(imageView);
break;
}
} else {
int index;
if (position == 0) {
index = 0;
} else {
index = position % textViewDefault.length;
}
Glide.with(imageView.getContext()).load(imgViewDefault[index]).placeholder(imgViewDefault[index]).into(imageView);
textView.setBackgroundResource(textViewDefault[index]);
}
}
@Override
public void onViewRecycled(ChannelGroupHorizontalGridViewHolder holder) {
if (holder != null) {
Glide.clear(holder.item_background);
}
super.onViewRecycled(holder);
}
@Override
public int getItemCount() {
return mGropuInfos.size();
}
@Override
public int getItemViewType(int position) {
return 0;
}
public void setOnItemSelectListener(OnRecycleViewItemSelectListener listener) {
mOnItemSelectLister = listener;
}
public void setOnItemClickLister(OnRecycleViewItemClickListener listener) {
mOnItemClickLister = listener;
}
public void setOnKeyListener(OnRecyclerViewItemKeyListener listener) {
mOnKeyListener = listener;
}
public void setGroupInfors(List<GroupInfo> groupInfors, int title_index) {
if (mGropuInfos == null) {
mGropuInfos = new ArrayList<>();
}
mGropuInfos.clear();
mGropuInfos.addAll(groupInfors);
current_title_index = title_index;
notifyDataSetChanged();
}
}
channel_recycleview_item.xml代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="230dp"
android:layout_height="140dp"
android:clipChildren="false"
android:clipToPadding="false"
android:focusable="true"
android:focusableInTouchMode="true"
android:gravity="center"
android:paddingLeft="10dp"
android:paddingTop="10dp">
<RelativeLayout
android:id="@+id/rl_item"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/transparent_yellow_view_selector"
android:duplicateParentState="true"
android:orientation="horizontal">
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="1.3dp"
android:duplicateParentState="true"
android:scaleType="fitXY" />
<TextView
android:id="@+id/textview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:duplicateParentState="true"
android:gravity="bottom|center_horizontal"
android:layout_margin="1.3dp"
android:paddingBottom="6dp"
android:textColor="@drawable/nine_listview_textcolor_selector_02"
android:textSize="20dp" />
</RelativeLayout>
</RelativeLayout>
要让最外层的RelativeLayout拥有获取焦点的权利,于是给它加上android:focusable="true"属性。子控件如果想保持和父控件一样的状态(焦点状态时子控件不是真正获取了焦点),加上android:duplicateParentState="true"属性即可。例如上面id为textview的TextView,它的textColor是一个drawable,它里面定义了有焦点状态和无焦点状态时字体的颜色:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/yellow" android:state_selected="true" />
<item android:color="@color/yellow" android:state_focused="true" />
<item android:color="@color/white" android:state_focused="false" />
<item android:color="@color/white" />
</selector>
ChannelGroupHorizontalGridViewHolder.java代码
package com.amlogic.dvb_adapter;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.amlogic.DVBPlayer.R;
import com.amlogic.dvb_util.CornerUtil;
public class ChannelGroupHorizontalGridViewHolder extends RecyclerView.ViewHolder {
public TextView item_name;
public ImageView item_background;
public ChannelGroupHorizontalGridViewHolder(View view) {
super(view);
item_name = (TextView) view.findViewById(R.id.textview);
item_background = (ImageView) view.findViewById(R.id.image);
//切圆角(在我博客可以找到这个工具类)
CornerUtil.clipViewCornerByDp(item_name, 8);
CornerUtil.clipViewCornerByDp(item_background, 8);
}
}
OnRecycleViewItemClickListener.java代码,item点击事件接口。
package com.amlogic.dvb_interface;
import android.view.View;
public interface OnRecycleViewItemClickListener {
void onItemClick(View view,int position);
}
OnRecycleViewItemSelectListener.java代码,item选中事件接口。
package com.amlogic.dvb_interface;
import android.view.View;
public interface OnRecycleViewItemSelectListener {
void onItemSelected(View view, int position, boolean hasFocus);
}
OnRecyclerViewItemKeyListener.java代码,item按键事件接口。
package com.amlogic.dvb_interface;
import android.view.KeyEvent;
import android.view.View;
//这里特意带上了position,可以做一些位置的判断
public interface OnRecyclerViewItemKeyListener {
boolean recyclerViewItemOnKey(View view, int keyCode, KeyEvent event, int position);
}
3、接口的实现。
上面的代码是我自己项目里的,我们只需要关注焦点选中、点击、按键事件的相关代码。
mChannelGroupHorizontalGridView = getView().findViewById(R.id.horizontal_gridView_channel_group);
mChannelGroupHorizontalGridViewAdapter = new ChannelGroupHorizontalGridViewAdapter(mDVBPlayer, mChannelGroupInfoList, TITLE_MAIN_ITEM);
initChannelGroupHorizontalGridViewListener();
mChannelGroupHorizontalGridView.setAdapter(mChannelGroupHorizontalGridViewAdapter);
initChannelGroupHorizontalGridViewListener中实现了选中、click、按键接口。
private void initChannelGroupHorizontalGridViewListener() {
//item选中事件
mChannelGroupHorizontalGridViewAdapter.setOnItemSelectListener(new OnRecycleViewItemSelectListener() {
@Override
public void onItemSelected(View view, int position, boolean hasFocus) {
mSettingsTitleRecyclerViewCurrentPosition = position;
ObjectAnimator animator1;
ObjectAnimator animator2;
if(hasFocus == true) {
Log.d("wujiang", "initChannelGroupHorizontalGridViewListener onItemSelected: 1 position = " + position);
animator1 = ObjectAnimator.ofFloat(view, "scaleX", 1f, 1.05f);
animator2 = ObjectAnimator.ofFloat(view, "scaleY", 1f, 1.05f);
} else {
Log.d("wujiang", "initChannelGroupHorizontalGridViewListener onItemSelected: 2 position = " + position);
animator1 = ObjectAnimator.ofFloat(view, "scaleX", 1.05f, 1f);
animator2 = ObjectAnimator.ofFloat(view, "scaleY", 1.05f, 1f);
}
AnimatorSet animSet = new AnimatorSet();
animSet.setDuration(200);
animSet.playTogether(animator1, animator2);
animSet.start();
}
});
//按键事件
mChannelGroupHorizontalGridViewAdapter.setOnKeyListener(new OnRecyclerViewItemKeyListener() {
@Override
public boolean recyclerViewItemOnKey(View view, int keyCode, KeyEvent event, int position) {
if (event.getAction() == KeyEvent.ACTION_UP) {
return false;
}
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_DOWN:
return true;
}
return false;
}
return false;
}
});
//item click事件
mChannelGroupHorizontalGridViewAdapter.setOnItemClickLister(new OnRecycleViewItemClickListener() {
@Override
public void onItemClick(View view, int position) {
Log.d("wujiang", "initChannelGroupHorizontalGridViewListener onItemClick: position = " + position);
}
});
}
如果觉得可以,给个赞吧!
THE END