I am able to change the color of the text and background of imageview of the row clicked of my recyclerview in my navigation drawer fragment.
But my problem is after clicking the 4th item,the 1st item also gets selected.Likewise after clicking my 5th item the 2nd item is selected.
Like this:
How do i solve this? So that only one item is selected at a time?
FragmentDrawer.java
public class FragmentDrawer extends Fragment {
private static String TAG = FragmentDrawer.class.getSimpleName();
private RecyclerView recyclerView;
private ActionBarDrawerToggle mDrawerToggle;
private DrawerLayout mDrawerLayout;
private NavigationDrawerAdapter adapter;
private View containerView;
private static String[] titles = null;
private FragmentDrawerListener drawerListener;
public FragmentDrawer() {
}
public void setDrawerListener(FragmentDrawerListener listener) {
this.drawerListener = listener;
}
public static List<NavDrawerItem> getData() {
List<NavDrawerItem> data = new ArrayList<>();
int[] icons = {R.drawable.ic_home,
R.drawable.ic_upcoming,
R.drawable.ic_saved,
R.drawable.ic_wehappened,
R.drawable.ic_persons,
R.drawable.ic_music,
R.drawable.ic_parties,
R.drawable.ic_art, R.drawable.ic_network, R.drawable.ic_sports};
// preparing navigation drawer items
for (int i = 0; i < titles.length && i < icons.length; i++) {
NavDrawerItem navItem = new NavDrawerItem();
navItem.setTitle(titles[i]);
navItem.setIcon(icons[i]);
data.add(navItem);
}
return data;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// drawer labels
titles = getActivity().getResources().getStringArray(R.array.nav_drawer_labels);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflating view layout
View layout = inflater.inflate(R.layout.fragment_navigation_drawer, container, false);
recyclerView = (RecyclerView) layout.findViewById(R.id.drawerList);
adapter = new NavigationDrawerAdapter(getActivity(), getData());
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
List<SimpleSectionedRecyclerViewAdapter.Section> sections =
new ArrayList<SimpleSectionedRecyclerViewAdapter.Section>();
//Sections
sections.add(new SimpleSectionedRecyclerViewAdapter.Section(5, "Categories"));
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), recyclerView, new ClickListener() {
#Override
public void onClick(View view, int position) {
NavigationDrawerAdapter.selected_item = position;
recyclerView.getAdapter().notifyDataSetChanged();
drawerListener.onDrawerItemSelected(view, position);
mDrawerLayout.closeDrawer(containerView);
}
#Override
public void onLongClick(View view, int position) {
}
}));
SimpleSectionedRecyclerViewAdapter.Section[] dummy = new SimpleSectionedRecyclerViewAdapter.Section[sections.size()];
SimpleSectionedRecyclerViewAdapter mSectionedAdapter = new
SimpleSectionedRecyclerViewAdapter(getContext(), R.layout.section, R.id.section_text, adapter);
mSectionedAdapter.setSections(sections.toArray(dummy));
//Apply this adapter to the RecyclerView
recyclerView.setAdapter(mSectionedAdapter);
return layout;
}
public void setUp(int fragmentId, DrawerLayout drawerLayout, final Toolbar toolbar) {
containerView = getActivity().findViewById(fragmentId);
mDrawerLayout = drawerLayout;
mDrawerToggle = new ActionBarDrawerToggle(getActivity(), drawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close) {
#Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
getActivity().invalidateOptionsMenu();
}
#Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
getActivity().invalidateOptionsMenu();
}
#Override
public void onDrawerSlide(View drawerView, float slideOffset) {
super.onDrawerSlide(drawerView, slideOffset);
toolbar.setAlpha(1 - slideOffset / 2);
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerLayout.post(new Runnable() {
#Override
public void run() {
mDrawerToggle.syncState();
}
});
}
public static interface ClickListener {
public void onClick(View view, int position);
public void onLongClick(View view, int position);
}
static class RecyclerTouchListener implements RecyclerView.OnItemTouchListener {
private GestureDetector gestureDetector;
private ClickListener clickListener;
public RecyclerTouchListener(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.getChildPosition(child));
}
}
});
}
#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.getChildPosition(child));
}
return false;
}
#Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
public interface FragmentDrawerListener {
public void onDrawerItemSelected(View view, int position);
}
}
NavigationDrawerAdapter.java
public class NavigationDrawerAdapter extends RecyclerView.Adapter<NavigationDrawerAdapter.MyViewHolder> {
List<NavDrawerItem> data = Collections.emptyList();
private LayoutInflater inflater;
private Context context;
public static int selected_item = 0;
public NavigationDrawerAdapter(Context context, List<NavDrawerItem> data) {
this.context = context;
inflater = LayoutInflater.from(context);
this.data = data;
}
public void delete(int position) {
data.remove(position);
notifyItemRemoved(position);
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.nav_drawer_row, parent, false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
if(position == selected_item)
{
holder.title.setTextColor(Color.parseColor("#00aaff"));
holder.imgViewIcon.setBackgroundResource(R.drawable.ic_circle);
}
NavDrawerItem current = data.get(position);
holder.title.setText(current.getTitle());
holder.imgViewIcon.setImageResource(current.getIcon());
}
#Override
public int getItemCount() {
return data.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView title;
public ImageView imgViewIcon;
public MyViewHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.title);
imgViewIcon = (ImageView) itemView.findViewById(R.id.item_icon);
}
}
}
EDIT: SimpleSectionedRecyclerViewAdapter.java
public class SimpleSectionedRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final Context mContext;
private static final int SECTION_TYPE = 0;
private boolean mValid = true;
private int mSectionResourceId;
private int mTextResourceId;
private LayoutInflater mLayoutInflater;
private RecyclerView.Adapter mBaseAdapter;
private SparseArray<Section> mSections = new SparseArray<Section>();
public SimpleSectionedRecyclerViewAdapter(Context context, int sectionResourceId, int textResourceId,
RecyclerView.Adapter baseAdapter) {
mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mSectionResourceId = sectionResourceId;
mTextResourceId = textResourceId;
mBaseAdapter = baseAdapter;
mContext = context;
mBaseAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
#Override
public void onChanged() {
mValid = mBaseAdapter.getItemCount()>0;
notifyDataSetChanged();
}
#Override
public void onItemRangeChanged(int positionStart, int itemCount) {
mValid = mBaseAdapter.getItemCount()>0;
notifyItemRangeChanged(positionStart, itemCount);
}
#Override
public void onItemRangeInserted(int positionStart, int itemCount) {
mValid = mBaseAdapter.getItemCount()>0;
notifyItemRangeInserted(positionStart, itemCount);
}
#Override
public void onItemRangeRemoved(int positionStart, int itemCount) {
mValid = mBaseAdapter.getItemCount()>0;
notifyItemRangeRemoved(positionStart, itemCount);
}
});
}
public static class SectionViewHolder extends RecyclerView.ViewHolder {
public TextView title;
public SectionViewHolder(View view,int mTextResourceid) {
super(view);
title = (TextView) view.findViewById(mTextResourceid);
}
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int typeView) {
if (typeView == SECTION_TYPE) {
final View view = LayoutInflater.from(mContext).inflate(mSectionResourceId, parent, false);
return new SectionViewHolder(view,mTextResourceId);
}else{
return mBaseAdapter.onCreateViewHolder(parent, typeView -1);
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder sectionViewHolder, int position) {
if (isSectionHeaderPosition(position)) {
((SectionViewHolder)sectionViewHolder).title.setText(mSections.get(position).title);
}else{
mBaseAdapter.onBindViewHolder(sectionViewHolder,sectionedPositionToPosition(position));
}
}
#Override
public int getItemViewType(int position) {
return isSectionHeaderPosition(position)
? SECTION_TYPE
: mBaseAdapter.getItemViewType(sectionedPositionToPosition(position)) +1 ;
}
public static class Section {
int firstPosition;
int sectionedPosition;
CharSequence title;
public Section(int firstPosition, CharSequence title) {
this.firstPosition = firstPosition;
this.title = title;
}
public CharSequence getTitle() {
return title;
}
}
public void setSections(Section[] sections) {
mSections.clear();
Arrays.sort(sections, new Comparator<Section>() {
#Override
public int compare(Section o, Section o1) {
return (o.firstPosition == o1.firstPosition)
? 0
: ((o.firstPosition < o1.firstPosition) ? -1 : 1);
}
});
int offset = 0; // offset positions for the headers we're adding
for (Section section : sections) {
section.sectionedPosition = section.firstPosition + offset;
mSections.append(section.sectionedPosition, section);
++offset;
}
notifyDataSetChanged();
}
public int positionToSectionedPosition(int position) {
int offset = 0;
for (int i = 0; i < mSections.size(); i++) {
if (mSections.valueAt(i).firstPosition > position) {
break;
}
++offset;
}
return position + offset;
}
public int sectionedPositionToPosition(int sectionedPosition) {
if (isSectionHeaderPosition(sectionedPosition)) {
return RecyclerView.NO_POSITION;
}
int offset = 0;
for (int i = 0; i < mSections.size(); i++) {
if (mSections.valueAt(i).sectionedPosition > sectionedPosition) {
break;
}
--offset;
}
return sectionedPosition + offset;
}
public boolean isSectionHeaderPosition(int position) {
return mSections.get(position) != null;
}
#Override
public long getItemId(int position) {
return isSectionHeaderPosition(position)
? Integer.MAX_VALUE - mSections.indexOfKey(position)
: mBaseAdapter.getItemId(sectionedPositionToPosition(position));
}
#Override
public int getItemCount() {
return (mValid ? mBaseAdapter.getItemCount() + mSections.size() : 0);
}
}
Change the onBindViewHolder method of your NavigationDrawerAdapter.java into this:
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
if(position == selected_item) {
holder.title.setTextColor(Color.parseColor("#00aaff"));
holder.imgViewIcon.setBackgroundResource(R.drawable.ic_circle);
} else {
holder.title.setTextColor(Color.parseColor("#00000")); //actually you should set to the normal text color
holder.imgViewIcon.setBackgroundResource(0);
}
NavDrawerItem current = data.get(position);
holder.title.setText(current.getTitle());
holder.imgViewIcon.setImageResource(current.getIcon());
}
Simple and Best
Inside Adapter class
int row_index=0;
inside onBindViewHOlder
holder.titleLL.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
row_index=position;
notifyDataSetChanged();
}
});
if (row_index==position) {
holder.title.setTextColor(Color.RED);
} else {
holder.title.setTextColor(Color.BLACK);
}
You can use class for Recycler view TouchListener
class RecyclerTouchListener implements RecyclerView.OnItemTouchListener{
private ClickListener clicklistener;
private GestureDetector gestureDetector;
public RecyclerTouchListener(Context context, final RecyclerView recycleView, 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=recycleView.findChildViewUnder(e.getX(),e.getY());
if(child!=null && clicklistener!=null){
clicklistener.onLongClick(child,recycleView.getChildAdapterPosition(child));
}
}
});
}
#Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child=rv.findChildViewUnder(e.getX(),e.getY());
RecyclerView.ViewHolder viewHolder=rv.findContainingViewHolder(child);
if(child!=null && clicklistener!=null && gestureDetector.onTouchEvent(e)){
clicklistener.onClick(child,rv.getChildAdapterPosition(child),viewHolder);
}
return false;
}
#Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
}
Implement an Interface
public interface ClickListener{
public void onClick(View view, int position,RecyclerView.ViewHolder viewHolder);
public void onLongClick(View view, int position);
}
And in your Main Activity (Here I set Image resource You can set as You like ,Any thing)
Create an arraylist named "selected" as Integer and add following code as OnClickListener
recyclerViewSchedule.addOnItemTouchListener(new RecyclerTouchListener(this,
recyclerViewSchedule, new ClickListener() {
#Override
public void onClick(View view, final int position, RecyclerView.ViewHolder v) {
//Values are passing to activity & to fragment as well
if(!selected.contains(position))
{
selected.add(position);
((ScheduleAdapter.MyHolder) v).txtImage.setBackgroundColor(getResources().getColor(R.color.colorAccent));
}else {
((ScheduleAdapter.MyHolder) v).txtImage.setBackgroundColor(getResources().getColor(R.color.colorTransparent));
selected.remove(new Integer(position));
}
Toast.makeText(ScheduleActivity.this, "Single Click on position :"+position,
Toast.LENGTH_SHORT).show();
}
Toast.makeText(ScheduleActivity.this, "Single Click on position :"+position,
Toast.LENGTH_SHORT).show();
}
#Override
public void onLongClick(View view, int position) {
Toast.makeText(ScheduleActivity.this, "Long press on position :"+position,
Toast.LENGTH_LONG).show();
}
}));
The txtImage I specified here is from RecyclerAdapter,Replace it with Your View
Happy Coding :-)
most of the answers for such a question, are about to Override Onclick in onBindViewHolder or implementing an interface for clicking in recycler view. but as we all know, onBindViewHolder is called as your views are populated during scrolling. Thus, you will have numerous calls to setOnClickListener so it is not an efficient way and also implementing interface is not as easy as the answer I got.
here is how you can access selecting items in recycler view and change its background or do what ever you want when an item is selected .
in your ViewHolder constructor use setOnTouchListener for itemView (the argument of constructor) in this way
itemView.setOnTouchListener((v, event) -> {
if (event.getAction() == MotionEvent.ACTION_UP) {
if (v.getTag() == null) {
v.setTag(true);
v.setBackgroundColor(Color.parseColor("#F31807"));
}
else {
v.setBackgroundColor(Color.TRANSPARENT);
v.setTag(null);
}
}
if (event.getAction() == MotionEvent.ACTION_MOVE) {
//default color
v.setBackgroundColor(Color.TRANSPARENT);
}
return true;
});
We use ACTION_UP for check if user pressed the item and after that we save a boolean in view's flag so that we can press every items how many times we want and see the color is changing. ACTION_MOVE if block is for prevent selecting items when scrolling the recycler view. if you see that selecting one item is affecting another items selection, you can use this answer:
issue : RecyclerView messed up data when scrolling
in the end if you are curious about why we return true in method see this video to understand.
tutorial on OnTouchListener And Motionevent
I have tried many different approaches but in the end, the solution that worked for me is
like first I was doing this
binding.download.setOnClickListener {
binding.download.visibility = View.GONE
binding.saved.visibility = View.VISIBLE
}
this was not working for me but after the below change
Instead of changing the color or visibility in onBindViewHolder, make a function in ViewHolder class and call it from onBindViewHolder
class ViewHolder(var binding: ImageRowBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(uri: Uri, mContext: Context) {
binding.download.setOnClickListener {
binding.download.visibility = View.GONE
binding.saved.visibility = View.VISIBLE
}
}
}
and calling this bind method from onBindViewHolder like this
holder.bind(items[position].uri, mContext)
works best for me
Related
I have the following Adapter :
public class TeambuilderAdapter extends RecyclerView.Adapter<TeambuilderAdapter.ViewHolder> implements ItemTouchHelperAdapter {
private List<PokemonTeam> mData;
private LayoutInflater mInflater;
private ItemClickListener mClickListener;
private Context mContext;
private PokemonFavoritesAdapter pokemonFavoritesAdapter;
private GridLayoutManager gridLayoutManager;
// data is passed into the constructor
public TeambuilderAdapter(Context context, List<PokemonTeam> data) {
this.mInflater = LayoutInflater.from(context);
this.mData = data;
mContext = context;
setHasStableIds(true);
}
#Override
public long getItemId(int position) {
PokemonTeam pokemonTeam = mData.get(position);
return (pokemonTeam.getName()).hashCode();
}
// inflates the row layout from xml when needed
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.list_item_teambuilder, parent, false);
return new ViewHolder(view);
}
// binds the data to the TextView in each row
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
PokemonTeam pokemonTeam = mData.get(position);
gridLayoutManager = new GridLayoutManager(mContext, 6);
pokemonFavoritesAdapter = new PokemonFavoritesAdapter(mContext, pokemonTeam.getPokemonList());
holder.teamSpritesRecyclerView.setAdapter(pokemonFavoritesAdapter);
holder.teamSpritesRecyclerView.setLayoutManager(gridLayoutManager);
String pokemonTeamName = pokemonTeam.getName();
if (pokemonTeamName != null && !pokemonTeamName.isEmpty()) {
holder.teamTitleTextView.setText(pokemonTeam.getName());
}
}
// total number of rows
#Override
public int getItemCount() {
int size = 0;
if (Objects.nonNull(mData)) {
size = mData.size();
}
return size;
}
#Override
public void onItemMove(int fromPosition, int toPosition) {
if (fromPosition < toPosition) {
for (int i = fromPosition; i < toPosition; i++) {
Collections.swap(mData, i, i + 1);
}
} else {
for (int i = fromPosition; i > toPosition; i--) {
Collections.swap(mData, i, i - 1);
}
}
notifyItemMoved(fromPosition, toPosition);
((PokemonTeambuilderActivity) mContext).refreshTeamList();
}
#Override
public void onItemDismiss(int position) {
mData.remove(position);
notifyItemRemoved(position);
((PokemonTeambuilderActivity) mContext).refreshTeamList();
}
// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView teamTitleTextView;
RecyclerView teamSpritesRecyclerView;
CardView pokemonTeambuilderContainer;
ViewHolder(View itemView) {
super(itemView);
teamTitleTextView = itemView.findViewById(R.id.pokemonTeambuilderTitleTextView);
teamSpritesRecyclerView = itemView.findViewById(R.id.pokemonTeambuilderSpritesLayout);
pokemonTeambuilderContainer = itemView.findViewById(R.id.pokemonTeambuilderContainer);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
if (mClickListener != null) {
mClickListener.onItemClick(view, getAdapterPosition());
}
}
}
// convenience method for getting data at click position
public PokemonTeam getItem(int id) {
return mData.get(id);
}
// allows clicks events to be caught
public void setClickListener(ItemClickListener itemClickListener) {
this.mClickListener = itemClickListener;
}
// parent activity will implement this method to respond to click events
public interface ItemClickListener {
void onItemClick(View view, int position);
}
}
In onBindViewHolder method I call another adapter inside this adapter which follows the same OnClickListener structure :
public class PokemonFavoritesAdapter extends RecyclerView.Adapter<PokemonFavoritesAdapter.ViewHolder> {
private Context mContext;
private List<Pokemon> favoritePokemon;
private LayoutInflater mInflater;
private PokemonFavoritesAdapter.ItemClickListener mClickListener;
public PokemonFavoritesAdapter(Context context, List<Pokemon> list) {
this.mInflater = LayoutInflater.from(context);
mContext = context;
favoritePokemon = list;
}
#NonNull
#Override
public PokemonFavoritesAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.list_item_pokemon_favorite, parent, false);
return new PokemonFavoritesAdapter.ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull PokemonFavoritesAdapter.ViewHolder holder, int position) {
Pokemon pokemon = favoritePokemon.get(position);
String pokemonId = pokemon.get_id();
int dominantColor = PokemonUtils.getDominantColorFromPokemon(pokemonId, mContext);
int lighterDominantColor = PokemonUtils.lighterColor(dominantColor, GenericConstants.DARK_FACTOR);
int pokemonImageId = PokemonUtils.getPokemonSugimoriImageById(pokemonId, mContext);
holder.circularImageView.setBorderColor(dominantColor);
holder.circularImageView.setBorderWidth(4);
holder.circularImageView.setCircleColor(lighterDominantColor);
holder.circularImageView.setShadowRadius(6);
Picasso.get().load(pokemonImageId).fit().into(holder.circularImageView);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemCount() {
int size = 0;
if (Objects.nonNull(favoritePokemon) && !favoritePokemon.isEmpty()) {
size = favoritePokemon.size();
}
return size;
}
// convenience method for getting data at click position
public Pokemon getItem(int id) {
return favoritePokemon.get(id);
}
// allows clicks events to be caught
public void setClickListener(PokemonFavoritesAdapter.ItemClickListener itemClickListener) {
this.mClickListener = itemClickListener;
}
// parent activity will implement this method to respond to click events
public interface ItemClickListener {
void onItemClick(View view, int position);
}
// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
CircularImageView circularImageView;
ViewHolder(View view) {
super(view);
circularImageView = view.findViewById(R.id.civ_pokemon_favorite);
view.setOnClickListener(this);
}
#Override
public void onClick(View view) {
if (mClickListener != null) {
mClickListener.onItemClick(view, getAdapterPosition());
}
}
}
}
However I have a problem , my activity can't listen the click events that happens inside my nested adapter :
public class PokemonTeambuilderActivity extends AppCompatActivity implements TeambuilderAdapter.ItemClickListener {
#Override
public void onItemClick(View view, int position) {
}
I don't know how to reach the events that happens within my PokemonFavoritesAdapter in my TeambuilderAdapter , I supose that I must implement the PokemonFavoritesAdapter.OnClickListener interface in my TeambuilderAdapter but I don't know how to do it . Any hint ?
I've got a RecylerView that is displaying a list of data. I need to add dividers or spacers that I need to add two Dividers or spacers too that I can add text to as shown in the image below(with the text DEFAULT or OTHER).
*NOTE Headers are in the image below with the text "DEFAULT" and another that says "OTHER".
The CC's shown are drag and drop items but i don't want the "spaces or headers" marked as default and other to be moved.
I've started adding the divider as shown in the code below but I cannot figure out how to add text.
#Override
public void onViewCreated(#NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ButterKnife.bind(this, view);
LinearLayoutManager mAdapterLayoutManager = new LinearLayoutManager(context);
recyclerView.setLayoutManager(mAdapterLayoutManager);
billingMethodRecyclerViewAdapter = new BillingMethodRecyclerViewAdapter(context, billingMethods, paymentService, ListPaymentMethods.this );
billingMethodRecyclerViewAdapter.setMasterpassService(masterpassService);
billingMethodRecyclerViewAdapter.setChoosePaymentMode(choosePaymentMode);
DividerItemDecoration itemDecor = new DividerItemDecoration(context, mAdapterLayoutManager.getOrientation());
recyclerView.addItemDecoration(itemDecor);
recyclerView.setAdapter(billingMethodRecyclerViewAdapter);
billingMethodRecyclerViewAdapter.clear();
if (!choosePaymentMode) {
setupSwipeListener(billingMethodRecyclerViewAdapter);
}
if (!BuildConfig.SHOW_AVAILABILITY_INRIX) {
parkmobileProAd.setVisibility(View.GONE);
}
if (getArguments() != null) {
isAddPaymentZoneDetails = getArguments().getBoolean(AddPaymentActivity.ADD_PAYMENT_FROM_ZONE_DETAIL);
}
}
and the xml for the recylcerview
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
EDIT
Adapter:
public class BillingMethodRecyclerViewAdapter extends RecyclerView.Adapter<BillingMethodHolder> {
private static final int PENDING_REMOVAL_TIMEOUT = 3000; // in milliseconds
private ArrayList<BillingMethod> billingMethods;
private Handler handler = new Handler(); // handler for running delayed runnables
private HashMap<BillingMethod, Runnable> pendingRunnables = new HashMap<>(); // map of items to pending runnables, so we can cancel a removal if need be
private BillingMethodHolder.BillingMethodListener billingMethodListener;
private PaymentService paymentService;
private MasterpassService masterpassService;
private boolean choosePaymentMode = false;
private Context mContext;
private int maxPaymentMethods = 6;
public BillingMethodRecyclerViewAdapter(Context context, ArrayList<BillingMethod> objects, PaymentService paymentService, BillingMethodHolder.BillingMethodListener billingMethodListener) {
this.billingMethods = objects;
this.billingMethodListener = billingMethodListener;
this.mContext = context.getApplicationContext();
this.paymentService = paymentService;
}
public int getMaxPaymentMethods() {
return maxPaymentMethods;
}
public void setMaxPaymentMethods(int maxPaymentMethods) {
this.maxPaymentMethods = maxPaymentMethods;
}
public void setMasterpassService(MasterpassService masterpassService) {
this.masterpassService = masterpassService;
}
public boolean onItemMove(int fromPosition, int toPosition) {
if (fromPosition < toPosition) {
for (int i = fromPosition; i < toPosition; i++) {
Collections.swap(billingMethods, i, i + 1);
}
} else {
for (int i = fromPosition; i > toPosition; i--) {
Collections.swap(billingMethods, i, i - 1);
}
}
notifyItemMoved(fromPosition, toPosition);
return true;
}
public List<BillingMethod> getBillingMethods() {
return billingMethods;
}
public void setChoosePaymentMode(boolean choosePaymentMode) {
this.choosePaymentMode = choosePaymentMode;
}
#NonNull
#Override
public BillingMethodHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_payment_methods, parent, false);
return new BillingMethodHolder(v);
}
#Override
public void onBindViewHolder(#NonNull BillingMethodHolder holder, final int position) {
holder.bind(getBillingMethods().get(position), billingMethodListener, choosePaymentMode);
}
#Override
public int getItemCount() {
return billingMethods.size();
}
public void pendingRemoval(int position) {
final BillingMethod billingMethod = billingMethods.get(position);
billingMethod.setPendingDeletion(true);
this.notifyItemChanged(position); // redraw row in "undo" state
Runnable pendingRemovalRunnable = () -> {
deleteBillingMethod(position);
};
handler.postDelayed(pendingRemovalRunnable, PENDING_REMOVAL_TIMEOUT);
pendingRunnables.put(billingMethod, pendingRemovalRunnable);
}
public void savePaymentOrder() {
List<BillingMethod> newOrder = new ArrayList<>();
int order = 0;
for (BillingMethod method : billingMethods) {
if (order == 0) {
method.setPreferred(true);
LocalyticsUtil.getInstance(mContext).setPrimaryPaymentMethod(method);
} else {
method.setPreferred(false);
}
method.setSortOrder(order);
newOrder.add(method);
order++;
}
paymentService.setPaymentMethodsOrder(newOrder, new PaymentService.GenericListener() {
#Override
public void onSuccess() {
Log.d("TAG", "Saved");
}
#Override
public void onError(String errorMessage) {
Log.d("TAG", "Saved");
}
});
}
private void deleteBillingMethod(int position) {
BillingMethod method = billingMethods.get(position);
if (method.getBillingType() == BillingType.CREDIT_CARD) {
paymentService.deleteCreditCard(method.getCreditCard().getCardStatus(), new PaymentService.GenericListener() {
#Override
public void onSuccess() {
billingMethods.remove(position);
notifyItemRemoved(position);
}
#Override
public void onError(String errorMessage) {
}
});
} else if (method.getBillingType() == BillingType.PREPAID) {
paymentService.deleteWallet(new PaymentService.GenericListener() {
#Override
public void onSuccess() {
billingMethods.remove(position);
notifyItemRemoved(position);
}
#Override
public void onError(String errorMessage) {
}
});
} else if (method.getBillingType() == BillingType.PAYPAL) {
paymentService.deletePaypal(new PaymentService.GenericListener() {
#Override
public void onSuccess() {
billingMethods.remove(position);
notifyItemRemoved(position);
}
#Override
public void onError(String errorMessage) {
}
});
} else if (method.getBillingType() == BillingType.CHASEPAY) {
paymentService.deleteChasepay(new PaymentService.GenericListener() {
#Override
public void onSuccess() {
billingMethods.remove(position);
notifyItemRemoved(position);
}
#Override
public void onError(String errorMessage) {
}
});
} else if (method.getBillingType() == BillingType.MASTERPASSV7) {
masterpassService.deleteMasterpassV7(String.valueOf(method.getBillingMethodId()), new MasterpassService.GenericListener() {
#Override
public void onSuccess() {
billingMethods.remove(position);
notifyItemRemoved(position);
}
#Override
public void onError(String errorMessage) {
}
});
} else {
notifyDataSetChanged();
}
}
public void clear() {
billingMethods.clear();
notifyDataSetChanged();
}
public void stopRemoval(BillingMethod billingMethod) {
Runnable pendingRemovalRunnable = pendingRunnables.get(billingMethod);
pendingRunnables.remove(billingMethod);
if (pendingRemovalRunnable != null) {
handler.removeCallbacks(pendingRemovalRunnable);
}
billingMethod.setPendingDeletion(false);
this.notifyItemChanged(billingMethods.indexOf(billingMethod));
}
}
I took a bit of time but I was able to do it.
This is the output
1) MainActivity.java
public class MainActivity extends AppCompatActivity implements OnStartDragListener{
RecyclerView recyclerView;
private ItemTouchHelper mItemTouchHelper;
private List<Item> itemList = new ArrayList<>();
private RecyclerViewAdapter mAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
mAdapter = new RecyclerViewAdapter(itemList, MainActivity.this);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.addItemDecoration(new SeparationDecorator());
recyclerView.setAdapter(mAdapter);
ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(mAdapter);
mItemTouchHelper = new ItemTouchHelper(callback);
mItemTouchHelper.attachToRecyclerView(recyclerView);
prepareItemData();
}
private void prepareItemData() {
Item item = new Item("Apple Pay");
itemList.add(item);
item = new Item("1706-XXXX-XXXX-1112");
itemList.add(item);
item = new Item("Google pay");
itemList.add(item);
mAdapter.notifyDataSetChanged();
}
#Override
public void onStartDrag(RecyclerView.ViewHolder viewHolder) {
mItemTouchHelper.startDrag(viewHolder);
}
}
2) OnStartDragListener.java
public interface OnStartDragListener {
void onStartDrag(RecyclerView.ViewHolder viewHolder);
}
3) SimpleItemTouchHelperCallback.java
public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {
private final ItemTouchHelperAdapter mAdapter;
public SimpleItemTouchHelperCallback(ItemTouchHelperAdapter adapter) {
mAdapter = adapter;
}
#Override
public boolean isLongPressDragEnabled() {
return true;
}
#Override
public boolean isItemViewSwipeEnabled() {
return false; // make this true to enable swipe to delete
}
#Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
return makeMovementFlags(dragFlags, swipeFlags);
}
#Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
RecyclerView.ViewHolder target) {
mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
#Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
mAdapter.onItemDismiss(viewHolder.getAdapterPosition());
}
}
4) ItemTouchHelperAdapter.java
public interface ItemTouchHelperAdapter {
void onItemMove(int fromPosition, int toPosition);
void onItemDismiss(int position);
}
5) SeparationDecorator.java
public class SeparationDecorator extends RecyclerView.ItemDecoration {
private int textSize = 50;
private int groupSpacing = 100;
private Paint paint = new Paint();
{
paint.setTextSize(textSize);
}
#Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
for (int i = 0; i < parent.getChildCount(); i++) {
View view = parent.getChildAt(i);
int position = parent.getChildAdapterPosition(view);
if (position == 0) {
c.drawText("DEFAULT", view.getLeft(),
view.getTop() - groupSpacing / 2 + textSize / 3, paint);
} else if(position == 1) {
c.drawText("OTHER", view.getLeft(),
view.getTop() - groupSpacing / 2 + textSize / 3, paint);
}
}
}
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
if (parent.getChildAdapterPosition(view) == 0 || parent.getChildAdapterPosition(view) == 1) {
outRect.set(0, groupSpacing, 0, 0);
}
}
}
6) RecyclerViewAdapter.java
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> implements ItemTouchHelperAdapter{
private List<Item> itemList;
private Context context;
#Override
public void onItemMove(int fromPosition, int toPosition) {
Item prev = itemList.remove(fromPosition);
itemList.add(toPosition > fromPosition ? toPosition - 1 : toPosition, prev);
notifyItemMoved(fromPosition, toPosition);
}
#Override
public void onItemDismiss(int position) {
itemList.remove(position);
notifyItemRemoved(position);
}
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView title;
public MyViewHolder(View view) {
super(view);
title = (TextView) view.findViewById(R.id.title);
}
}
public RecyclerViewAdapter(List<Item> itemList, Context context) {
this.itemList = itemList;
this.context = context;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.view_item, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Item movie = itemList.get(position);
holder.title.setText(movie.getTitle());
}
#Override
public int getItemCount() {
return itemList.size();
}
}
7) Item.java
public class Item {
private String title;
public Item(String title) {
this.title = title;
}
public void setTitle(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
}
This is it. This was able to solve your problem.
I am not able to explain you the complete code, I will take some time in future definitely and explain it.
public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
// other methods..
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
// initialize your other views
if (your condition){
// display header
}else{
// hide header
}
}
}
You can do some thing like this by adding header view to the item and displaying for the required set and making it gone for un necessary items.
Simply coming towards what you need, just add an empty view with layout_height="1dp" and background="#bcbcbc" like:
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#bcbcbc"/>
it'll get a line drawn for you, use it as a divider, while for making format difference just use a change text size for texts.
Hope it'll help you.
i am working on one project in which i have used open source code, but at one point i am stuck, in this code i am using RecyclerView in which onRecycleItemClickListener is already implemented but now i need to implement onItemLongClickListener in existing code
public abstract class BaseRecyclerViewAdapter<T, VH extends BaseClickListenerViewHolder> extends RecyclerView.Adapter<VH> {
private List<T> objectsList;
protected final BaseActivity baseActivity;
protected final LayoutInflater layoutInflater;
protected final Resources resources;
protected QBUser currentQbUser;
// Package private because we need access in BaseViewHolder but not in child classes
OnRecycleItemClickListener<T> onRecycleItemClickListener;
AdapterView.OnItemLongClickListener onItemLongClickListener;
public BaseRecyclerViewAdapter(BaseActivity baseActivity) {
this.baseActivity = baseActivity;
this.layoutInflater = LayoutInflater.from(baseActivity);
resources = baseActivity.getResources();
objectsList = new ArrayList<>();
}
public BaseRecyclerViewAdapter(BaseActivity baseActivity, List<T> objectsList) {
this(baseActivity);
this.objectsList = objectsList;
currentQbUser = AppSession.getSession().getUser();
}
public void setList(List<T> items) {
objectsList = items;
notifyDataSetChanged();
}
public void addItem(T item) {
objectsList.add(item);
notifyItemInserted(objectsList.size() - 1);
}
public void addItem(int position, T item) {
objectsList.add(position, item);
notifyItemInserted(position);
}
public void addAll(Collection<T> collection) {
objectsList.addAll(collection);
notifyItemRangeChanged(objectsList.size() - collection.size(), collection.size());
}
public void removeItem(int position) {
objectsList.remove(position);
notifyItemRemoved(position);
}
public void removeItem(T item) {
int position = objectsList.indexOf(item);
if (position != -1) {
objectsList.remove(item);
notifyItemRemoved(position);
}
}
public void clear() {
objectsList.clear();
notifyDataSetChanged();
}
#Override
public int getItemCount() {
return objectsList.size();
}
public T getItem(int position) {
return objectsList.get(position);
}
public List<T> getAllItems() {
return objectsList;
}
public boolean isEmpty() {
return objectsList.size() == 0;
}
public void setOnRecycleItemClickListener(OnRecycleItemClickListener<T> onRecycleItemClickListener) {
this.onRecycleItemClickListener = onRecycleItemClickListener;
}
protected void displayAvatarImage(String uri, ImageView imageView) {
ImageLoader.getInstance().displayImage(uri, imageView, ImageLoaderUtils.UIL_USER_AVATAR_DISPLAY_OPTIONS);
}
}
You can use this class ItemTouchListenerAdapter in your code to easily add support for both item clicks and long-clicks.
Usage:
recyclerView.addOnItemTouchListener(new ItemTouchListenerAdapter(recyclerView, this));
Code:
public class ItemTouchListenerAdapter extends GestureDetector.SimpleOnGestureListener implements RecyclerView.OnItemTouchListener {
public interface RecyclerViewOnItemClickListener {
void onItemClick(RecyclerView parent, View clickedView, int position);
void onItemLongClick(RecyclerView parent, View clickedView, int position);
}
private RecyclerViewOnItemClickListener listener;
private RecyclerView recyclerView;
private GestureDetector gestureDetector;
public ItemTouchListenerAdapter(RecyclerView recyclerView, RecyclerViewOnItemClickListener listener) {
if (recyclerView == null || listener == null) {
throw new IllegalArgumentException("RecyclerView and Listener arguments can not be null");
}
this.recyclerView = recyclerView;
this.listener = listener;
this.gestureDetector = new GestureDetector(recyclerView.getContext(), this);
}
#Override
public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) {
gestureDetector.onTouchEvent(motionEvent);
return false;
}
#Override
public void onTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) {
}
#Override
public void onShowPress(MotionEvent e) {
View view = getChildViewUnder(e);
if (view != null) {
view.setPressed(true);
}
}
#Override
public boolean onSingleTapUp(MotionEvent e) {
View view = getChildViewUnder(e);
if (view == null) return false;
view.setPressed(false);
int position = recyclerView.getChildPosition(view);
listener.onItemClick(recyclerView, view, position);
return true;
}
public void onLongPress(MotionEvent e) {
View view = getChildViewUnder(e);
if (view == null) return;
int position = recyclerView.getChildPosition(view);
listener.onItemLongClick(recyclerView, view, position);
view.setPressed(false);
}
#Nullable
private View getChildViewUnder(MotionEvent e) {
return recyclerView.findChildViewUnder(e.getX(), e.getY());
}
}
How can handle with this situation -> I have a list of itens in a recyclerView and I want to choose one of those option: green, yellow or red face to get the value of object from list item I chose
So I thought something like bellow, but when I select one of those faces anything happens. I think that button click listener doesn't work. Please someone can drive me to a better suggestion that works, give me an example or could me tell what am I doing wrong?
My adapter
public class LikeListAdapter extends RecyclerView.Adapter<LikeListAdapter.LikeItemViewHolder> {
private List<Goals> goalsList;
private SparseBooleanArray selectedItems;
public LikeListAdapter(List<Goals> goalsList) {
this.goalsList = goalsList;
}
#Override
public LikeItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.recycler_item_like, parent, false);
return new LikeItemViewHolder(view);
}
#Override
public void onBindViewHolder(LikeItemViewHolder holder, int position) {
final Goals goals = goalsList.get(position);
if (goals != null && getItemCount() > 0) {
holder.goalsDescriptionTextView.setText(goals.getDescription());
holder.happyButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.e("fretgr", "get Green Point = " + goals.getGreenPoint());
setToggleSelection(1);
}
});
holder.sosoButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.e("rtret", "get Yellow Point = " + goals.getYellowPoint());
setToggleSelection(2);
}
});
holder.angryButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.e("ewwr", "get Red Point = " + goals.getRedPoint());
setToggleSelection(3);
}
});
}
}
#Override
public int getItemCount() {
return goalsList.size();
}
public class LikeItemViewHolder extends RecyclerView.ViewHolder {
#Bind(R.id.description_goalsTextView)
TextView goalsDescriptionTextView;
#Bind(R.id.happy)
ImageView happyButton;
#Bind(R.id.soso)
ImageView sosoButton;
#Bind(R.id.angry)
ImageView angryButton;
public LikeItemViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
// method to access in activity after updating selection
public List<Goals> getGoalsList() {
return goalsList;
}
public void setToggleSelection(int pointType){
selectedItems = new SparseBooleanArray();
if (selectedItems.get(pointType, false)) {
selectedItems.delete(pointType);
} else {
selectedItems.put(pointType, true);
}
notifyItemChanged(pointType);
}
public int getToggleSelection(){
return 0;
}
}
My Fragment
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
layoutManager.scrollToPosition(0);
assocGoalsRecyclerView.setLayoutManager(layoutManager);
assocGoalsRecyclerView.setHasFixedSize(true);
likeListAdapter = new LikeListAdapter(associateList);
assocGoalsRecyclerView.setAdapter(likeListAdapter);
assocGoalsRecyclerView.addOnItemTouchListener(RecycleTouchListener);
private RecyclerView.OnItemTouchListener RecycleTouchListener = new RecyclerView.OnItemTouchListener() {
#Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child = assocGoalsRecyclerView.findChildViewUnder(e.getX(), e.getY());
if(child!=null && mGestureDetector.onTouchEvent(e)){
final int position = assocGoalsRecyclerView.getChildAdapterPosition(child);
final Goals goals = associateList.get(position);
final Categories c = categoriesList.get(position);
final int type = likeListAdapter.getToggleSelection();
return true;
}
return false;
}
#Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) { }
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { }
};
I found an answer based in another responses and sugestions!!! Android: handling clicks on image view inside recycler's view item using touch framework
In My Fragment
Snippet from fragment:
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
layoutManager.scrollToPosition(0);
assocGoalsRecyclerView.setLayoutManager(layoutManager);
// assocGoalsRecyclerView.addItemDecoration(new SimpleDividerItemDecoration(getActivity()));
assocGoalsRecyclerView.setHasFixedSize(true);
likeListAdapter = new LikeListAdapter(associateList, onItemClickCallback);
assocGoalsRecyclerView.setAdapter(likeListAdapter);
public static class OnItemClickListener implements View.OnClickListener {
private int position;
private OnItemClickCallback onItemClickCallback;
public OnItemClickListener(int position, OnItemClickCallback onItemClickCallback) {
this.position = position;
this.onItemClickCallback = onItemClickCallback;
}
#Override
public void onClick(View view) {
onItemClickCallback.onItemClicked(view, position);
}
public interface OnItemClickCallback {
void onItemClicked(View view, int position);
}
}
private OnItemClickListener.OnItemClickCallback onItemClickCallback = new OnItemClickListener.OnItemClickCallback() {
#Override
public void onItemClicked(View view, int position) {
switch(view.getId()){
case R.id.happy:
Log.e("rtetre", "happy assessed and position is = " + position);
break;
case R.id.soso:
Log.e("rwere", "soso assessed and position is = " + position);
break;
case R.id.angry:
Log.e("dfrefgt", "angry assessed and position is = " + position);
break;
}
}
};
In My adapter
public class LikeListAdapter extends RecyclerView.Adapter<LikeListAdapter.LikeItemViewHolder> {
private List<Goals> goalsList;
private LikeFragment.OnItemClickListener.OnItemClickCallback onItemClickCallback;
public LikeListAdapter(List<Goals> goalsList, LikeFragment.OnItemClickListener.OnItemClickCallback onItemClickCallback) {
this.goalsList = goalsList;
this.onItemClickCallback = onItemClickCallback;
}
#Override
public LikeItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.recycler_item_like, parent, false);
LikeItemViewHolder likeItemViewHolder = new LikeItemViewHolder(view);
return likeItemViewHolder;
}
#Override
public void onBindViewHolder(LikeItemViewHolder holder, int position) {
final Goals goals = goalsList.get(position);
if (goals != null && getItemCount() > 0) {
holder.goalsDescriptionTextView.setText(goals.getDescription());
holder.happyButton.setOnClickListener(new LikeFragment.OnItemClickListener(position, onItemClickCallback));
holder.sosoButton.setOnClickListener(new LikeFragment.OnItemClickListener(position, onItemClickCallback));
holder.angryButton.setOnClickListener(new LikeFragment.OnItemClickListener(position, onItemClickCallback));
}
}
#Override
public int getItemCount() {
return goalsList.size();
}
public static class LikeItemViewHolder extends RecyclerView.ViewHolder {
#Bind(R.id.description_goalsTextView)
TextView goalsDescriptionTextView;
#Bind(R.id.happy)
ImageView happyButton;
#Bind(R.id.soso)
ImageView sosoButton;
#Bind(R.id.angry)
ImageView angryButton;
public LikeItemViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}
So i have a recyclerview on my fragment in a navigation drawer and it works jus fine.
However i would like to add a second recyclerview listing more items.
This is achievable but the hard part is making the whole layout scroll together.
I have google it up an havent found anything helpful.I thought maybe one of you might have a work around.
Is this possible?
FragmentDrawer.java
public class FragmentDrawer extends Fragment {
private static String TAG = FragmentDrawer.class.getSimpleName();
private RecyclerView recyclerView;
private ActionBarDrawerToggle mDrawerToggle;
private DrawerLayout mDrawerLayout;
private NavigationDrawerAdapter adapter;
private View containerView;
private static String[] titles = null;
private FragmentDrawerListener drawerListener;
public FragmentDrawer() {
}
public void setDrawerListener(FragmentDrawerListener listener) {
this.drawerListener = listener;
}
public static List<NavDrawerItem> getData() {
List<NavDrawerItem> data = new ArrayList<>();
int[] icons = {R.drawable.home, R.drawable.ic_upcoming, R.drawable.ic_eventsaved, R.drawable.ic_wehappened, R.drawable.ic_persons};
// preparing navigation drawer items
for (int i = 0; i < titles.length && i < icons.length; i++) {
NavDrawerItem navItem = new NavDrawerItem();
navItem.setTitle(titles[i]);
navItem.setIcon(icons[i]);
data.add(navItem);
}
return data;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// drawer labels
titles = getActivity().getResources().getStringArray(R.array.nav_drawer_labels);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflating view layout
View layout = inflater.inflate(R.layout.fragment_navigation_drawer, container, false);
recyclerView = (RecyclerView) layout.findViewById(R.id.drawerList);
adapter = new NavigationDrawerAdapter(getActivity(), getData());
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), recyclerView, new ClickListener() {
#Override
public void onClick(View view, int position) {
drawerListener.onDrawerItemSelected(view, position);
mDrawerLayout.closeDrawer(containerView);
}
#Override
public void onLongClick(View view, int position) {
}
}));
return layout;
}
public void setUp(int fragmentId, DrawerLayout drawerLayout, final Toolbar toolbar) {
containerView = getActivity().findViewById(fragmentId);
mDrawerLayout = drawerLayout;
mDrawerToggle = new ActionBarDrawerToggle(getActivity(), drawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close) {
#Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
getActivity().invalidateOptionsMenu();
}
#Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
getActivity().invalidateOptionsMenu();
}
#Override
public void onDrawerSlide(View drawerView, float slideOffset) {
super.onDrawerSlide(drawerView, slideOffset);
toolbar.setAlpha(1 - slideOffset / 2);
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerLayout.post(new Runnable() {
#Override
public void run() {
mDrawerToggle.syncState();
}
});
}
public static interface ClickListener {
public void onClick(View view, int position);
public void onLongClick(View view, int position);
}
static class RecyclerTouchListener implements RecyclerView.OnItemTouchListener {
private GestureDetector gestureDetector;
private ClickListener clickListener;
public RecyclerTouchListener(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.getChildPosition(child));
}
}
});
}
#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.getChildPosition(child));
}
return false;
}
#Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
public interface FragmentDrawerListener {
public void onDrawerItemSelected(View view, int position);
}
NavigationDrawerAdapter.java
public class NavigationDrawerAdapter extends RecyclerView.Adapter<NavigationDrawerAdapter.MyViewHolder> {
List<NavDrawerItem> data = Collections.emptyList();
private LayoutInflater inflater;
private Context context;
public NavigationDrawerAdapter(Context context, List<NavDrawerItem> data) {
this.context = context;
inflater = LayoutInflater.from(context);
this.data = data;
}
public void delete(int position) {
data.remove(position);
notifyItemRemoved(position);
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.nav_drawer_row, parent, false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
NavDrawerItem current = data.get(position);
holder.title.setText(current.getTitle());
holder.imgViewIcon.setImageResource(current.getIcon());
}
#Override
public int getItemCount() {
return data.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView title;
public ImageView imgViewIcon;
public MyViewHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.title);
imgViewIcon = (ImageView) itemView.findViewById(R.id.item_icon);
}
}
}
strings.xml
<resources>
<string name="nav_item_home">Home</string>
<string name="nav_item_friends">Upcoming</string>
<string name="nav_item_notifications">Saved</string>
<string name="nav_item_main">weHappened</string>
<string name="nav_item_planners">Event planners</string>
<!-- navigation drawer item labels -->
<string-array name="nav_drawer_labels">
<item>#string/nav_item_home</item>
<item>#string/nav_item_friends</item>
<item>#string/nav_item_notifications</item>
<item>#string/nav_item_main</item>
<item>#string/nav_item_planners</item>
</string-array>
<string name="title_messages">Events saved</string>
<string name="title_friends">Upcoming events</string>
<string name="title_home">Home</string>
<string name="title_happened">Events weHappened</string>
<string name="title_planners">Event planners</string>
</resources>
Use a single RecyclerView if you like to list more items in the same list. There is no point in using 2 different RecyclerViews and you can't make them scroll together if these are one below the other.
If you want to add more items to the list dynamically, build an "update" method in your Adapter and call that method when you'd like to add more items and call notifyItemRangeChanged() (or the most appropriate methods given the the RecyclerView.Adapter class)
EDIT:
Assuming you have a RecyclerView set and you know how to initialize and set it up with a basic LinearLayoutManager, I would like to focus only on the adapter.
So if you'd like to separate 2 categories like "Main options" and "Other options" you may want to consider implementing your adapter for 2 view types. Here is a short code snippet on how to achieve that but this highlights only the idea of how to use multiple view types. You may want to modify it to your needs:
public class DrawerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int VIEW_TYPE_HEADER = 0;
private static final int VIEW_TYPE_REGULAR_ITEM = 1;
private LayoutInflater mInflater;
private List<Object> mItems;
public DrawerAdapter(Context context) {
mInflater = LayoutInflater.from(context);
mItems = new ArrayList<>();
mItems.add("Main options");
mItems.add(new Item("Option1", R.drawable.icons_for_option_1))
mItems.add(new Item("Option2", R.drawable.icons_for_option_2))
mItems.add(new Item("Option2", R.drawable.icons_for_option_2))
mItems.add(new Item("Option3", R.drawable.icons_for_option_3))
mItems.add("Secondary options")
mItems.add(new Item("Option4", R.drawable.icons_for_option_4))
// And so on...whatever the logic is.
}
#Override
public int getItemCount() {
return mItems.size();
}
#Override
public int getItemViewType(int position) {
if (position == 0 || position == 5) { // Assuming that the topmost item and the 5th item are the section headers. This if statement can be simplified too.
return VIEW_TYPE_HEADER;
} else {
return VIEW_TYPE_REGULAR_ITEM;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == VIEW_TYPE_HEADER) {
return new HeaderViewHolder(mInflater.inflate(R.layout.list_item_header, parent, false));
} else {
return new RegularItemViewHolder(mInflater.inflate(R.layout.list_item_regular, parent, false));
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof HeaderViewHolder) {
((HeaderViewHolder) holder).setup(mItems.get(position));
} else if (holder instanceof RegularItemViewHolder) {
((RegularItemViewHolder) holder).setup(mItems.get(position));
}
}
private static class RegularItemViewHolder extends RecyclerView.ViewHolder {
private RegularItemViewHolder(View convertView) {
super(convertView);
// Initialize your views here. Let's say you will have a TextView and an icon here or whatever else.
}
public void setup(Item item) {
// Update your views here, etc.
}
}
private static class HeaderViewHolder extends RecyclerView.ViewHolder {
TextView titleTextView;
private HeaderViewHolder(View convertView) {
super(convertView);
titleTextView = convertView.findViewById(R.id.section_header);
}
public void setup(String sectionHeaderTitle) {
yourTextView.setText(title);
}
}
}
And this would be it. Sorry for eventual mistakes, I didn't test the code.
Cheers!