3

I am trying to separate handle OnClick Button and OnClick Row inside Fragment with interface..

so far, this is what I have tried :

Inside Fragment

if (recyclerView.getTag().toString().equals("Grid")) {
            adapter = new RVAdapter(ListOfdataAdapter, getContext(), 
                    RVAdapterChannel.ViewType.GRID_LIST_LAYOUT, new ClickListener() {
                @Override
                public void OnClick(int position, View view) {
                    //THIS ALWAYS RETURN ROW CLICKED
                    if (view.findViewById(R.id.imageLike).getId() == view.getId()){
                        Toast.makeText(getContext(), "IMAGE LIKE CLICKED",Toast.LENGTH_SHORT).show();
                        OpenDialog();
                    }
                    if (view.findViewById(R.id.layoutRelative).getId() == view.getId()){
                        Toast.makeText(getContext(), "ROW CLICKED", Toast.LENGTH_SHORT).show();
                        OpenDatabase();
                    }

                    //THIS MAKES APP CRASH
                    if (view.findViewById(R.id.imageLike).performClick){
                        Toast.makeText(getContext(), "IMAGE LIKE CLICKED",Toast.LENGTH_SHORT).show();
                        OpenDialog();
                    }
                    if (view.findViewById(R.id.layoutRelative).performClick){
                        Toast.makeText(getContext(), "ROW CLICKED", Toast.LENGTH_SHORT).show();
                        OpenDatabase();
                    }
                    // ANOTHER TRY
                }

                @Override
                public void onLongClicked(int position, View view) {
                }
            });

            recyclerView.setAdapter(adapter);
            if (getPreferenceValue().equals("on")) {
                AnimBottomToTop();
            }
        }

at the moment only one is in line with my expectation, that is, if I place If - Else inside the adapter.. but if I do, I cannot open OpenDialog (), OpenDatabase (), etc. If it can only be done through an adapter, how can I open OpenDialog();, OpenDatabase();, etc? and if possible I want to place it in fragments not in adapters.

Inside Adapter

public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener{
        RelativeLayout Container;
        ImageView ImageLike;
        //...//
        private WeakReference<ClickListener> listenerRef;


        public ViewHolder(View itemView, ClickListener listener) {

            super(itemView);

            listenerRef = new WeakReference<>(listener);;
            ImageLike = (ImageView) itemView.findViewById(R.id.imageLike) ;
            //...//

            //itemView.setOnClickListener(this);
            itemView.setOnClickListener(this);
            Container.setOnClickListener(this);
            ImageLike.setOnClickListener(this);
            ImageLike.setOnLongClickListener(this);
        }

        // onClick Listener for view
        @Override
        public void onClick (View view) {
            //THIS WILL RETURN TOAST ON IMAGELIKE CLICK
            if (view.getId() == ImageLike.getId()) {
                Toast.makeText(view.getContext(), "IMAGE LIKE CLICKED = " + String.valueOf(getAdapterPosition()), Toast.LENGTH_SHORT).show();
            } //THIS WILL RETURN TOAST ON ROW CLICK
             else {
                Toast.makeText(view.getContext(), "ROW CLICKED = " + String.valueOf(getAdapterPosition()), Toast.LENGTH_SHORT).show();
            }
            listenerRef.get().OnClick(getAdapterPosition(), itemView);
        }

        //onLongClickListener for view
        @Override
        public boolean onLongClick(View view) {

            final AlertDialog.Builder builder = new AlertDialog.Builder(view.getContext());
            builder.setTitle("Hello Dialog")
                    .setMessage("LONG CLICK DIALOG WINDOW FOR ICON " + String.valueOf(getAdapterPosition()))
                    .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {

                        }
                    });

            builder.create().show();
            listenerRef.get().onLongClicked(getAdapterPosition(), itemView);
            return true;
        }
    }

I use this method from here Onclick for each button inside RecyclerView items

And from here RecyclerView onClick i think this not suit my needs to (not trying all answers)

until now I have not found an answer according to my needs.

forgive me if my question is difficult to understand. thanks for your response.

Espada
  • 173
  • 1
  • 10

3 Answers3

1

You can take OnClickListeners using the adapters constructor instead. Therefore, you can set each click listener separately.

class Adapter : RecyclerView.Adapter<ViewHolder> {

   OnClickListener buttonClick, rowClick;

   public Adapter(List<Data> data, OnClickListener buttonClick, OnClickListener rowClick) {
    this.buttonClick = buttonClick;
    this.rowClick = rowClick;
   }

   public void onBindViewHolder(ViewHolder v, int pos) {
      v.button.setOnClickListener(buttonClick);
      v.itemView.setOnClickListener(rowClick); // itemView is the whole view
      // other codes
   }
   // other parts of adapter
}

Then when you make the adapter, you can pass ClickListeners to it.

// when you make this list, like in the fragment

View.OnClickListener buttonListener = new View.OnClickListener {

   public void onClick(View v) {
       // button was clicked
   }
}

View.OnClickListener rowListener = new View.OnClickListener {

   public void onClick(View v) {
       // row was clicked
   }
}

Adapter adapter = new Adapter(listOfData, buttonListener, rowListener);
recyclerView.setAdapter(adapter);

TL; DR

Pass two OnClickListeners as the adapter constructor param, and set the for views in onBindViewHolder.

Mahdi-Malv
  • 16,677
  • 10
  • 70
  • 117
1

Instead of itemView

listenerRef.get().OnClick(getAdapterPosition(), itemView);
listenerRef.get().onLongClicked(getAdapterPosition(), itemView);

return view from your onClick and onLongClick listener like below:

listenerRef.get().OnClick(getAdapterPosition(), view);  
listenerRef.get().onLongClicked(getAdapterPosition(), view);

And then inside your fragment, do like this

@Override
public void OnClick(int position, View view) {

    if (R.id.imageLike == view.getId()){
        Toast.makeText(getContext(), "IMAGE LIKE CLICKED",Toast.LENGTH_SHORT).show();
        OpenDialog();
    }

    if (R.id.layoutRelative == view.getId()){
        Toast.makeText(getContext(), "ROW CLICKED", Toast.LENGTH_SHORT).show();
        OpenDatabase();
    }
}
Md. Asaduzzaman
  • 14,963
  • 2
  • 34
  • 46
  • wow .. thank you very much. I did not expect such a small change to be able to realize my wish ... can you explain more the difference between `itemView` and `view` in this case? – Espada Dec 02 '19 at 06:19
0

On your adapter : Create interface for callback like bellow:

public interface OnAdapterListener{
    void onImageLikeClicked();
    void onRowClicked();
    //Create more methods as per your need
}

Declare listener globally:

OnAdapterListener mListener;

Create method for initialize listener:

public void setOnClickListener(OnAdapterListener listener){
    mListener = listener;
}

OnClick method:

// onClick Listener for view
@Override
public void onClick (View view) {
    //THIS WILL RETURN TOAST ON IMAGELIKE CLICK
    if (view.getId() == ImageLike.getId()) {
        Toast.makeText(view.getContext(), "IMAGE LIKE CLICKED = " + String.valueOf(getAdapterPosition()), Toast.LENGTH_SHORT).show();
        if(mListener != null){
            mListener.onImageLikeClicked();
        }
    } //THIS WILL RETURN TOAST ON ROW CLICK
    else {
        if(mListener != null){
            mListener.onRowClicked();
        }
        Toast.makeText(view.getContext(), "ROW CLICKED = " + String.valueOf(getAdapterPosition()), Toast.LENGTH_SHORT).show();
    }
}

From activity :

    adapter.setOnClickListener(new OnAdapterListener() {
        @Override
        public void onImageLikeClicked() {
            OpenDialog();
        }

        @Override
        public void onRowClicked() {
            OpenDatabase();
        }
    });
SADIKUL BARI
  • 126
  • 1
  • 6
  • thanks.. but, for me its hard to follow. Like `OnHomeAdapterListener` and `OnAdapterListener`, i already have interface called 'ClickListener'. – Espada Dec 02 '19 at 06:10
  • It was just a demo you can replace name of the interface OnAdapterListener with your interface and its best practice to solve your problem. Thanks – SADIKUL BARI Dec 02 '19 at 06:34