简体   繁体   中英

Make recycler view clickable inside a card view

  <android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/home_subscribe_card"
    android:layout_width="match_parent"
    android:layout_height="72dp"
    android:onClick="@{vm.onGoalPress}"
    card_view:cardCornerRadius="4dp">

<android.support.v7.widget.RecyclerView
                android:id="@+id/feeds_list"
                android:layout_width="200dp"
                android:layout_height="30dp"
                android:layout_marginTop="6dp" />

</CardView>

The card view on Click is working .But the region of recycler view is not clickable. How can it be made clickable so that the event of card view is captured.

For recylerview you need to set adapter order to use clickable like listview. You can refer following link : https://developer.android.com/training/material/lists-cards.html You can take a look another question here : Why doesn't RecyclerView have onItemClickListener()? And how RecyclerView is different from Listview?

 protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.my_activity);
    mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);

    // use this setting to improve performance if you know that changes
    // in content do not change the layout size of the RecyclerView
    mRecyclerView.setHasFixedSize(true);

    // use a linear layout manager
    mLayoutManager = new LinearLayoutManager(this);
    mRecyclerView.setLayoutManager(mLayoutManager);

    // specify an adapter (see also next example)
    mAdapter = new MyAdapter(myDataset);
    mRecyclerView.setAdapter(mAdapter);
}
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private String[] mDataset;

// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class ViewHolder extends RecyclerView.ViewHolder {
    // each data item is just a string in this case
    public TextView mTextView;
    public ViewHolder(TextView v) {
        super(v);
        mTextView = v;
    }
}

// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(String[] myDataset) {
    mDataset = myDataset;
}

// Create new views (invoked by the layout manager)
@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                               int viewType) {
    // create a new view
    View v = LayoutInflater.from(parent.getContext())
                           .inflate(R.layout.my_text_view, parent, false);
    // set the view's size, margins, paddings and layout parameters
    ...
    ViewHolder vh = new ViewHolder(v);
    return vh;
}

// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    // - get element from your dataset at this position
    // - replace the contents of the view with that element
    holder.mTextView.setText(mDataset[position]);

}

// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
    return mDataset.length;
}

}

//something like this //holder.mTextView.setOnClickListener(onClick);

You need to set click listeners within the viewholder of the recyclerview Adapter. Within Viewholder you have access to all the element of every view, Viewgroup of the layoyt that recyclerview inflates. I hope that makes sense.

Alternatively you can set the onclick listener in your onBind() method.

You can take a look at this question

If your cardview is outside recycler view then there is no direct way to access it. Use call backs or event bus from your recycler view to the activity /fragment where you are inflating your card view and then update your card view with the new values

public class InterceptTouchCardView extends CardView {

public InterceptTouchCardView(Context context) {
    super(context);
}

public InterceptTouchCardView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public InterceptTouchCardView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

/**
 * Intercept touch event so that inner views cannot receive it.
 * 
 * If a ViewGroup contains a RecyclerView and has an OnTouchListener or something like that,
 * touch events will be directly delivered to inner RecyclerView and handled by it. As a result, 
 * parent ViewGroup won't receive the touch event any longer.
 */
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    return true;
}

}

The solution with InterceptTouchCardView has a problem when items of the RecyclerView have some clickable views (ie a button) themselves. Those clickable views then never receive any touch events. Better solution is to extend the RecyclerView and override its onInterceptTouchEvent and onTouchEvent , so they both just return false like this (Kotlin syntax):

class ClickThroughRecyclerView : RecyclerView {

    constructor(context: Context) : super(context)

    constructor(context: Context, attr: AttributeSet?) : super(context, attr)

    constructor(context: Context, attr: AttributeSet?, defStyle: Int) : super(context, attr, defStyle)

    override fun onInterceptTouchEvent(e: MotionEvent): Boolean {
        return false
    }

    override fun onTouchEvent(e: MotionEvent): Boolean {
        return false
    }

}

By using ClickThroughRecyclerView inside the layout file ensures, that touch events not consumed by the RecyclerView 's items (like buttons, ...) are propagated to the RecyclerView 's parent view.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM