Created
July 21, 2018 14:47
-
-
Save mahdi-malv/1fee0f9ef303c982e959f75f6c6ba5b6 to your computer and use it in GitHub Desktop.
RecyclerAdapter to simplify adapting recyclerView
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.content.Context; | |
import android.support.v7.widget.RecyclerView; | |
import android.view.GestureDetector; | |
import android.view.MotionEvent; | |
import android.view.View; | |
public class ListClick implements RecyclerView.OnItemTouchListener { | |
private GestureDetector gestureDetector; | |
private ClickListener clickListener; | |
public ListClick(Context context, final RecyclerView recyclerView, final ClickListener clickListener) { | |
this.clickListener = clickListener; | |
gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { | |
@Override | |
public boolean onSingleTapUp(MotionEvent e) { | |
return true; | |
} | |
@Override | |
public void onLongPress(MotionEvent e) { | |
View child = recyclerView.findChildViewUnder(e.getX(), e.getY()); | |
if (child != null && clickListener != null) { | |
clickListener.onLongClick(child, recyclerView.getChildAdapterPosition(child)); // in case of deprication: use getChildAdapterPosition | |
} | |
} | |
}); | |
} | |
@Override | |
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { | |
View child = rv.findChildViewUnder(e.getX(), e.getY()); | |
if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) { | |
clickListener.onClick(child, rv.getChildAdapterPosition(child)); // in case of deprication: use getChildAdapterPosition | |
} | |
return false; | |
} | |
@Override | |
public void onTouchEvent(RecyclerView rv, MotionEvent e) { | |
} | |
@Override | |
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { | |
} | |
public interface ClickListener { | |
void onClick(View view, int position); | |
/** | |
* to Add support for extension methods you must use Java 8 or above | |
* to do that Add this block to `build.gradle(Module: your module like app)` inside android block | |
compileOptions { | |
targetCompatibility 1.8 | |
sourceCompatibility 1.8 | |
} | |
* This feature makes onLongClick optional | |
*/ | |
default void onLongClick(View view, int position) {} | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.content.Context; | |
import android.content.res.Resources; | |
import android.support.v7.widget.LinearLayoutManager; | |
import android.support.v7.widget.RecyclerView; | |
import android.view.LayoutInflater; | |
import android.view.View; | |
import android.view.ViewGroup; | |
import java.util.List; | |
public class ListConfig<T> { | |
private Context c; | |
private List<T> set; | |
private RecyclerView list; | |
private int resLayout = 0; | |
private RecyclerView.LayoutManager layoutManager; | |
private ListClick.ClickListener onClick; | |
private BindHolder<T> bindHolder; | |
private CreateViewHolder createViewHolder = null; | |
public ListConfig(Context c) { | |
this.c = c; | |
} | |
public ListConfig<T> with(List<T> set) { | |
if (set == null) throw new NullPointerException("List of data can not be null"); | |
else this.set = set; | |
return this; | |
} | |
public ListConfig<T> resLayout(int layout) { | |
this.resLayout = layout; | |
return this; | |
} | |
public ListConfig<T> layoutManager(RecyclerView.LayoutManager layoutManager) { | |
if (layoutManager == null) throw new NullPointerException("If you want to use default, Don't invoke this function."); | |
this.layoutManager = layoutManager; | |
return this; | |
} | |
public ListConfig<T> onBindViewHolder(BindHolder<T> onBind) { | |
bindHolder = onBind; | |
return this; | |
} | |
public ListConfig<T> onClick(ListClick.ClickListener listener) { | |
onClick = listener; | |
return this; | |
} | |
/** | |
* OnCreateView holder can be customized here. This is optional | |
*/ | |
public ListConfig<T> setOnCreateViewHolder(CreateViewHolder onCreateViewHolder) { | |
this.createViewHolder = onCreateViewHolder; | |
return this; | |
} | |
public void into(RecyclerView list) { | |
this.list = list; | |
list.setLayoutManager(layoutManager == null ? new LinearLayoutManager(c) : layoutManager); | |
list.setHasFixedSize(true); | |
list.setAdapter(new Adapter(set, resLayout, bindHolder, createViewHolder)); | |
list.addOnItemTouchListener(new ListClick(c, list, onClick)); | |
} | |
public static class VH extends RecyclerView.ViewHolder { | |
VH(View itemView) { | |
super(itemView); | |
} | |
} | |
public class Adapter extends RecyclerView.Adapter<VH> { | |
private List<T> set; | |
private int resLayout; | |
private BindHolder<T> bindHolder; | |
private CreateViewHolder createViewHolder = null; | |
public Adapter(List<T> set, int resLayout, BindHolder<T> bindHolder, CreateViewHolder createViewHolder) { | |
this.set = set; | |
this.resLayout = resLayout; | |
this.bindHolder = bindHolder; | |
this.createViewHolder = createViewHolder; | |
} | |
@Override | |
public VH onCreateViewHolder(ViewGroup parent, int viewType) { | |
if (createViewHolder == null) { | |
if (resLayout == 0) throw new Resources.NotFoundException("You have not passed the resource or correct resource."); | |
View v = LayoutInflater.from(parent.getContext()).inflate(resLayout, parent, false); | |
return new VH(v); | |
} else { | |
return createViewHolder.onCreateViewHolder(parent, viewType); | |
} | |
} | |
@Override | |
public void onBindViewHolder(VH holder, int position) { | |
bindHolder.onBind(holder, set.get(position), position); | |
} | |
@Override | |
public int getItemCount() { | |
return set.size(); | |
} | |
} | |
//Interfaces | |
public interface BindHolder<T> { | |
void onBind(VH holder, T item, int position); | |
} | |
public interface CreateViewHolder { | |
VH onCreateViewHolder(ViewGroup parent, int viewType); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
new ListConfig<Datum>(context) //pass Context and Generic can be anything | |
.with(set) // List of <Datum> | |
.resLayout(R.layout.layout) // Resource layout | |
.layoutManager(new GridLayouManager(context, 2)) // Optional: default is LinearLayoutManager | |
.onBindViewHolder((holder, item, position) -> { // what happens in onBindViewHolder and also in ViewHolder | |
// Also item is `set.get(position)` | |
TextView title = holder.itemView.findViewById(R.id.name); // Create and instantiate your views here using itemView of holder | |
title.setText(item.getName()); | |
title.setTextColor(color); | |
TextView model = holder.itemView.findViewById(R.id.model); | |
model.setText(item.getModel()); | |
/* Assume you have a Datum class that has name and model (For example) */ | |
}) | |
.onClick((view, position) -> { // onClick - Optional: OnLongClick is also available | |
Toast.makeText(getActivity(), "Item clicked!", Toast.LENGTH_SHORT).show(); | |
}) | |
.into(list); // must be invoked at the end of chain (returns void) - Others can be moved in order |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment