ListView is familiar on Android, but it cannot be scrolled horizontally. So we'll create a listview-like widget that inherits from RecyclerView and scrolls horizontally.
A widget that nicely displays multiple views. It's pretty flexible, so you can do most things with it. For details, see [Android] Basic implementation of RecyclerView.
HorizontalListView.java
import android.content.Context;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
public class HorizontalListView extends RecyclerView{
public interface OnItemClickListener{
void onItemClick(View view, int position);
}
public HorizontalListView(Context context){
super(context);
initialize(context);
}
public HorizontalListView(Context context, AttributeSet set){
super(context, set);
initialize(context);
}
public HorizontalListView(Context context, AttributeSet set, int defaultAttr){
super(context, set, defaultAttr);
initialize(context);
}
private void initialize(Context context){
LinearLayoutManager manager = new LinearLayoutManager(context);
manager.setOrientation(LinearLayoutManager.HORIZONTAL);
setLayoutManager(manager);
}
private OnItemClickListener mListener;
public void setOnItemClickListener(OnItemClickListener listener){
mListener = listener;
Adapter adapter = getAdapter();
if ( adapter instanceof ArrayAdapter ){
ArrayAdapter a = (ArrayAdapter)adapter;
a.mListener = this.mListener;
}
}
@Override
public void setAdapter(RecyclerView.Adapter adapter){
super.setAdapter(adapter);
if ( adapter instanceof ArrayAdapter ){
ArrayAdapter a = (ArrayAdapter)adapter;
a.mListener = this.mListener;
}
}
@Override
protected void onDetachedFromWindow(){
super.onDetachedFromWindow();
setOnItemClickListener(null);
setAdapter(null);
setLayoutManager(null);
}
private static class SimpleViewHolder extends ViewHolder{
private SimpleViewHolder(View view){
super(view);
}
}
public static abstract class ArrayAdapter<E> extends RecyclerView.Adapter<ViewHolder> {
public ArrayAdapter(List<E> list){
mDataList = new ArrayList<>(list.size());
mViews = new ArrayList<>(list.size());
mDataList.addAll(list);
}
private List<E> mDataList;
private OnItemClickListener mListener;
private List<View> mViews;
/**
*Instantiate a View that is a list element
* @param parent
* @return null not acceptable
*/
public abstract View getView(ViewGroup parent);
/**
*Reflect the data displayed in the list in View
* @param view View of reflection destination
* @param data Data to be reflected{@link #getItem(int)}But can be obtained
* @param position Position on the list
*/
public abstract void onBindView(View view, E data, int position);
@Override
public final ViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
return new SimpleViewHolder(getView(parent));
}
@Override
public final void onBindViewHolder(final ViewHolder holder, int position){
final View view = holder.itemView;
E data = getItem(position);
onBindView(view, data, position);
mViews.add(holder.itemView);
holder.itemView.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v){
if ( mListener != null ){
mListener.onItemClick(view, holder.getAdapterPosition());
}
}
});
}
@Override
public void onDetachedFromRecyclerView(RecyclerView recyclerView){
super.onDetachedFromRecyclerView(recyclerView);
for ( View view : mViews ) view.setOnClickListener(null);
mViews = null;
mListener = null;
mDataList = null;
}
@Override
public final int getItemCount(){
return mDataList.size();
}
public E getItem(int position){
return mDataList.get(position);
}
}
}
All you have to do is set the LinearLayoutManager with the horizontal orientation to RecyclerView.
private void initialize(Context context){
LinearLayoutManager manager = new LinearLayoutManager(context);
manager.setOrientation(LinearLayoutManager.HORIZONTAL);
setLayoutManager(manager);
}
Like ListView, RecyclerView requires an adapter to manage the data and the View to display. Therefore, we prepared HorizontalListView.ArrayAdapter by inheriting RecyclerView.Adapter. The following two should be implemented at the time of use.
public abstract View getView(ViewGroup parent);
public abstract void onBindView(View view, E data, int position);
Inflate the View used for display with getView (ViewGroup), and reflect the contents of data E in View with onBindView (View, E, int). When using ListView, I gave it a similar API so that it can be operated in the same way as customizing the layout with an adapter that inherits android.widget.ArrayAdapter.
Like ListView, I want a callback that notifies me when an element of the list is clicked. Let's make it.
public interface OnItemClickListener{
void onItemClick(View view, int position);
}
Notifies the clicked View and display position. As an implementation, set OnClickListener to the View that the HorizontalListView.ArrayAdapter created earlier gets and displays with getView (ViewGroup), and relays the received callback. However, note that it will not work unless the adapter set with RecyclerView # setAdapter () is HorizontalListView.ArrayAdapter.
Recommended Posts