b101
b101

Reputation: 379

RecyclerView and Admob Items: Problems with onClickListener

I've added a NativeExpressAdView inside my RecyclerView ItemList but now the onClickListener is interfering with the NativeExpressAdView. My "normal" Items consist of text and one larger Image. When the larger Image gets clicked on, a DialogFragment gets opened and shows detailed information of the Item. However, the NativeExpressAdView shouldn't run into this onClickListener. The App keeps crashing because it tries to open the not existing detailed View of the NativeExpressAdView ...

MainActivity

...
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    ......

    recyclerView.addOnItemTouchListener(new ItemAdapter.RecyclerTouchListener(getApplicationContext(), recyclerView, new ItemAdapter.ClickListener() {
        @Override
        public void onClick(View view, final int position) {
            final Bundle bundle = new Bundle();
            bundle.putSerializable("events", events);
            bundle.putInt("position", position);
            final Event event = events.get(position);

            detailView = (ImageView) view.findViewById(R.id.item_thumbnail);
            detailView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    android.support.v4.app.FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
                    SlideshowDialogFragment newFragment = SlideshowDialogFragment.newInstance();
                    newFragment.setArguments(bundle);
                    newFragment.setCancelable(true);
                    newFragment.show(ft, "slideshow");
                }
            });
           ....
           some other button onClickListener()...
           ....
        }

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

ItemAdapter

public class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{

private List<Event> events;
private Context mContext;

public ItemAdapter(Context context, List<Event> events){
    mContext = context;
    this.events = events;
}

public static class MyViewHolder extends RecyclerView.ViewHolder{ // implements View.OnClickListener {
    public ImageView thumbnail;
    public TextView event_name;
    public TextView event_date;
    public TextView event_descr;
    public TextView event_attending;
    public TextView event_maybe;

    public MyViewHolder(android.view.View view){
        super(view);
        thumbnail = (ImageView) view.findViewById(R.id.item_thumbnail);
        event_name = (TextView) view.findViewById(R.id.tV_event_name);
        event_date = (TextView) view.findViewById(R.id.tV_event_date);
        event_descr = (TextView) view.findViewById(R.id.tV_event_descr);
        event_attending = (TextView) view.findViewById(R.id.tV_attending_count);
        event_maybe = (TextView) view.findViewById(R.id.tV_maybe_count);
    }
}

public static class ViewHolderAdMob extends RecyclerView.ViewHolder {
    public NativeExpressAdView nativeExpressAdView;
    public ViewHolderAdMob(View view) {
        super(view);
        nativeExpressAdView = (NativeExpressAdView) view.findViewById(R.id.ad_nativeAdOne);
        AdRequest adRequest = new AdRequest.Builder()
                .addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
                .addTestDevice("228****************************")
                .build();
        nativeExpressAdView.loadAd(adRequest);
    }
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
    RecyclerView.ViewHolder viewHolder = null;
    LayoutInflater inflater = LayoutInflater.from(parent.getContext());
    //View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.rv_items, parent, false);

    switch (viewType){
        case 1:{
            View itemView = inflater.inflate(R.layout.rv_items, parent, false);
            viewHolder = new MyViewHolder(itemView);
            break;
        }
        case 2:{
            View itemView = inflater.inflate(R.layout.native_ad_one, parent, false);
            viewHolder = new ViewHolderAdMob(itemView);
            break;
        }
    }

    return viewHolder;
}


@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position){
    Event event = events.get(position);

    switch (holder.getItemViewType()){
        case 1:{
            MyViewHolder viewHolder = (MyViewHolder) holder;
            viewHolder.event_name.setText(event.getEventName());
            viewHolder.event_date.setText(event.getEventDate());
            viewHolder.event_descr.setText(event.getEventDescription());
            viewHolder.event_attending.setText(event.getEventAttending());
            viewHolder.event_maybe.setText(event.getEventMaybeComming());

            Glide.with(mContext).load(event.getEventImage())
                    .thumbnail(0.9f)
                    .crossFade()
                    //.diskCacheStrategy(DiskCacheStrategy.ALL)
                    .fitCenter()
                    .into(viewHolder.thumbnail);
            break;
        }
        case 2:{
            break;
        }
    }


}

@Override
public int getItemCount(){
    return events.size();
}

@Override
public int getItemViewType(int position) {
    return  events.get(position).getViewType();
}

public interface ClickListener {
    void onClick(View view, int position);

    void onLongClick(View view, int position);
}

public static class RecyclerTouchListener implements RecyclerView.OnItemTouchListener {

    private GestureDetector gestureDetector;
    private ItemAdapter.ClickListener clickListener;

    public RecyclerTouchListener(final Context context, final RecyclerView recyclerView, final ItemAdapter.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){

    }
}
}

I kind of see where the problem stems from, since the the RecyclerView is listening for input and naturally reacts to it but I kind of thought that by defining inside my MainActivity that detailView = (ImageView) view.findViewById(R.id.item_thumbnail); it will only react to "normal" items since R.id.item_thumbnail is an element of my "normal" items xml whereas the NativeExpressAdView doesn't have such an element. How can I fix this problem and get the proper functionality ??

Upvotes: 0

Views: 560

Answers (2)

ataulm
ataulm

Reputation: 15334

Set the click listener in onBindViewHolder, in your adapter, depending on the view type.

public static class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private final MyListClickListener clickListener;

    public ItemAdapter(MyListClickListener clickListener) {
        this.clickListener = clickListener;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (getItemViewType(position) == ADVERT_VIEW_TYPE) {
            // do whatever you do for adverts
        } else {
            // do what you do for items and set the click listener
            holder.itemView.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View view) {
                    clickListener.onShowDetailViewClicked(); // pass the parameters you need to identify this particular item
                }
            });
        }
    }

    public interface MyListClickListener {

        void onShowDetailViewClicked();
    }
}

Upvotes: 1

ucsunil
ucsunil

Reputation: 7504

You are setting the onItemTouchListener{...} to the entire RecyclerView. It assumes that no matter where you touch, there is the detail view. But you have different types of rows in your RecyclerView. The best option would be to add touch listeners to each individual item in your ViewHolder classes.

Upvotes: 0

Related Questions