CardView as parent in RecyclerView items not showing ripple effect - android

I have a RecyclerView which I'm populating with items as described by the layout below.
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/cv_item_display"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="1dp"
android:clickable="true"
android:foreground="?android:attr/selectableItemBackground">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal"
android:weightSum="9">
.
.
.
</LinearLayout>
</android.support.v7.widget.CardView>
Whenever the CardView referenced by cv_item_display is clicked inside RecyclerView, I see ripple effect on Card BUT when I attach an OnClickListener to the card, I don't get ripple effect any more. Below is the code for ViewHolder where I attach OnClickListener.
public class RosterViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
TextView tvStudentCount, tvRosterName;
ImageView ivDelete, ivView;
CardView cvItemDisplay;
public RosterViewHolder(View itemView) {
super(itemView);
tvStudentCount = (TextView) itemView.findViewById(R.id.tv_question_student_count);
tvRosterName = (TextView) itemView.findViewById(R.id.tv_questionnaire_roster_name);
ivDelete = (ImageView) itemView.findViewById(R.id.iv_delete);
ivView = (ImageView) itemView.findViewById(R.id.iv_view);
cvItemDisplay = (CardView) itemView.findViewById(R.id.cv_item_display);
cvItemDisplay.setOnClickListener(this);
ivDelete.setOnClickListener(this);
ivView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
final int position = getAdapterPosition();
switch (view.getId()) {
case R.id.iv_delete:
mRealm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
mRealm.where(RosterEntry.class).equalTo("rosterId", mRealmResults.get(position).getId()).findAll().deleteAllFromRealm();
mRealmResults.deleteFromRealm(position);
}
});
break;
case R.id.iv_view:
Utils.startRosterItemsActivity(view.getContext(), mRealmResults.get(position).getName(), mRealmResults.get(position).getId(), false);
break;
case R.id.cv_item_display:
startAttendanceActivity(mRealmResults.get(position).getId());
break;
}
}
}
EDIT: I also identified some weird behavior - ripple effect shows in landscape mode but not in portrait mode.

Related

How can I keep track of visibility of my text view in each page in a viewpager2?

So this is my code. I am trying to create what looks like a PPT slideshow of images with their title and description in my application.
I have the below code and I am stuck on how to allow the user to:
When he gets into the slideshow he would get the images, with a title and text "description" for each.
when "ENTER" is pressed set the text on that image to invisible.
When the user navigates to the right, the next view(s) would contain a text and Image.
-When the user navigates back left the text view that he set invisible should still be invisible and the has the option to get it to become visible again by just pressing enter.
The last part is what I am stuck on, as I am not able to figure out how each "Linear Layout" inside my viewpager would remember its visibility and act accordingly. (i.e. gets back to visible once it was invisible and vice versa).
I appreciate your input.
Please find the code below:
My ViewPager XML file:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/fragment_pager_main_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/default_background"
tools:context=".PowerPointActivity">
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/fragment_pager_viewPager2"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
My views XML file:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/fragment_pager_item_parent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/fragment_pager_item_imageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:scaleType="fitXY"/>
<LinearLayout
android:id="#+id/fragment_pager_item_main_child"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="textStart"
android:orientation="vertical"
app:layout_constraintTop_toTopOf="#+id/fragment_pager_item_parent"
app:layout_constraintStart_toStartOf="#+id/fragment_pager_item_parent">
<!-- the linear layout below was not initially here but I was trying to have a layout for each child.-->
<LinearLayout
android:id="#+id/fragment_pager_item_child"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="textStart"
android:orientation="vertical"
app:layout_constraintTop_toTopOf="#+id/fragment_pager_item_parent"
app:layout_constraintStart_toStartOf="#+id/fragment_pager_item_parent">
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/fragment_pager_item_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginStart="10dp"
android:layout_marginTop="5dp"
android:gravity="top"
android:textColor="#FFFFFF"
android:textSize="12dp"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="#+id/fragment_pager_item_child"
app:layout_constraintTop_toTopOf="#+id/fragment_pager_item_child"
app:layout_constraintVertical_bias="0.0"
tools:text="Topic" />
<TextView
android:id="#+id/fragment_pager_item_about"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="top"
android:layout_marginStart="10dp"
android:elegantTextHeight="true"
android:text="#string/about_topic"
android:textColor="#ffffff"
android:textSize="12sp"
app:layout_constraintHorizontal_bias="10"
app:layout_constraintStart_toStartOf="#+id/fragment_pager_item_title"
app:layout_constraintTop_toBottomOf="#id/fragment_pager_item_title"
app:layout_dodgeInsetEdges="left" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
My Adapter Class:
public class PowerpointAdapter extends RecyclerView.Adapter{
private List<Image> mPowerPointList;
static class PagesViewHolder extends RecyclerView.ViewHolder {
private ImageView mViewImageView;
private TextView mTitleView;
private TextView mDescriptionView;
private LinearLayout mLinearLayout;
public PagesViewHolder(#NonNull View itemView) {
super(itemView);
Timber.i("PagesViewHolder");
mViewImageView = itemView.findViewById(R.id.fragment_pager_item_imageView);
mTitleView = itemView.findViewById((R.id.fragment_pager_item_title));
mDescriptionView = itemView.findViewById(R.id.fragment_pager_item_about);
mLinearLayout = itemView.findViewById(R.id.fragment_pager_item_child);
}
}
public PowerpointAdapter(List<Image> mPowerPointList) { this.mPowerPointList = mPowerPointList;}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
Timber.i("onCreateViewHolder");
View mView = LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_pager_item, parent, false);
return new PagesViewHolder(mView);
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
Timber.i("onBindViewHolder");
PagesViewHolder mViewHolder = (PagesViewHolder) holder;
Image powerpoint = mPowerPointList.get(position);
mViewHolder.mViewImageView.setImageResource(powerpoint.getTrialImage());
mViewHolder.mTitleView.setText(powerpoint.getTitle());
mViewHolder.mDescriptionView.setText(powerpoint.getDescription());
mViewHolder.mLinearLayout.setVisibility(View.VISIBLE);
}
#Override
public int getItemCount() {
Timber.i("getItemCount");
return mPowerPointList.size();}
My activity class:
// for a one image display, the image can be treated similarly to a powerpoint.
public class PowerPointActivity extends Activity {
private ViewPager2 viewPager2;
#Override
protected void onCreate(Bundle savedInstanceState) {
Timber.i("onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_pager_main);
ConstraintLayout mLayout = findViewById(R.id.fragment_pager_main_parent);
mLayout.setBackgroundResource(R.color.Transparent_black);
viewPager2 = findViewById(R.id.fragment_pager_viewPager2);
setUpPagerAdapter();
}
/**
* this method will set up the adapter
*/
private void setUpPagerAdapter() {
Timber.i("SetUpPagerAdapter");
PowerpointAdapter pagerAdapter = new PowerpointAdapter(fetchDummyData());
viewPager2.setAdapter(pagerAdapter);
viewPager2.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
}
/**
* #return this method will return dummy data in form of list
*/
private List<Image> fetchDummyData() {
Timber.i("fetchDummyData in Power Point Activity");
List<Image> powerpointList = new ArrayList<>();
String[] dummyArrDescriptions = getResources().getStringArray(R.array.array_str_descriptions_for_powerPoints);
String[] dummyArrTitles = getResources().getStringArray(R.array.array_str_titles_for_powerPoints);
for (int index = 0; index < dummyArrTitles.length; ++index) {
Image image = new Image(dummyArrTitles[index], dummyArrDescriptions[index], R.drawable.ppt_image);
powerpointList.add(image);
}
return powerpointList;
}
/**
* this method handles slideshow navigation
*/
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
Timber.i("OnKeyDown");
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_LEFT: {
viewPager2.setCurrentItem(viewPager2.getCurrentItem() - 1);
Toast.makeText(PowerPointActivity.this, "Left pressed!", Toast.LENGTH_SHORT).show();
break;
}
case KeyEvent.KEYCODE_DPAD_RIGHT: {
viewPager2.setCurrentItem(viewPager2.getCurrentItem() + 1);
Toast.makeText(PowerPointActivity.this, "Right pressed!", Toast.LENGTH_SHORT).show();
break;
}
case KeyEvent.KEYCODE_BACK: {
Toast.makeText(PowerPointActivity.this, "Back pressed!", Toast.LENGTH_SHORT).show();
super.onBackPressed();
break;
}
// todo: Fix the visibility of each page description
case KeyEvent.KEYCODE_ENTER: {
if (findViewById(R.id.fragment_pager_item_child).isShown()) {
Timber.i("It is shown. Setting it to not shown! "+ viewPager2.getCurrentItem() + " now.");
// here this specific child's text should be set to invisible and remembered. findViewById(R.id.fragment_pager_item_child).setVisibility(View.INVISIBLE);
LinearLayout mLayout = findViewById(R.id.fragment_pager_item_child);
Animation outFade = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.fade_out);
mLayout.startAnimation(outFade);
mLayout.startAnimation(outFade);
break;
} else {
Timber.i("It is now not shown. Setting it to shown! " + viewPager2.getCurrentItem() + " now.");
LinearLayout mLayout = findViewById(R.id.fragment_pager_item_child);
Animation aniFade = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.fade_in);
mLayout.startAnimation(aniFade);
mLayout.startAnimation(aniFade);
findViewById(R.id.fragment_pager_item_child).setVisibility(View.VISIBLE);
break;
}
}
}
return false;
}
}
Thank you!
From the Android documentation we can find that the Adapter holds the following responsibilities:
Acts as a bridge between an AdapterView and the underlying data for that view.
Provides access to the data items
Responsible for making a View for each item in the data set.
So basically it's not the View's job to remember the child's visibility and act upon it. It's PowerpointAdapter responsibility.
You need a status field in your Image object and change it when the view visibility is changed. Also, don't forget to set the view visibility according to this status variable.
For example:
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
Timber.i("onBindViewHolder");
PagesViewHolder mViewHolder = (PagesViewHolder) holder;
Image powerpoint = mPowerPointList.get(position);
mViewHolder.mViewImageView.setImageResource(powerpoint.getTrialImage());
mViewHolder.mTitleView.setText(powerpoint.getTitle());
mViewHolder.mDescriptionView.setText(powerpoint.getDescription());
if(powerpoint.isLayoutVisibile){
mViewHolder.mLinearLayout.setVisibility(View.VISIBLE);
}else{
mViewHolder.mLinearLayout.setVisibility(View.GONE);
}
}
And Inside your ClickListener you should change this field and notify the PowerpointAdapter of these changes.

how to turn off parent recycler view onclick response after child view already responded?

I am using a recyclerview that the viewholder entry has an imageview. Both have an onclick listener. If the child image view responded to the onclick, I don't want the recylerview onClick to respond to it. If the clicked location is not on the imageviewer, I want the recyclerview to respond. My research so far shows that usually this situation can be handled by using the same function to respond to both onClick events, but the problem is that recyclerview onclick and its child imageview onClick are different. I don't see how they can be handled in the same function. Right now I have a hacking workaround to use a global variable to indicate that the imageview has already responded to this click, and put up a 200ms delay on recyclerview listener to check the global variable before responding. Is there a more proper way of doing this?
I just noticed that if I add an "onClick" for every type of child views of the recycler view and remove the listener on the recyclerview, that can work. Right now I only have two child views anyway. Although I will be adding a lot more, it's still manageable. If there's no better way, I'll probably just do that.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:paddingLeft="16dp"
android:paddingRight="4dp"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:clickable="true"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical">
<TextView
android:id="#+id/lstItemName"
android:textColor="#color/title"
android:textSize="16dp"
android:textStyle="bold"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="#+id/lstItemReportby"
android:layout_gravity="left"
android:layout_width="0dp"
android:layout_height="wrap_content"
/>
<ImageView
android:id="#+id/lstItemMap"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginRight="2dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"/>
</android.support.constraint.ConstraintLayout>
public class TrackedItemListAdapter extends RecyclerView.Adapter<TrackedItemListAdapter.MyViewHolder>{
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView m_itemName, m_itemDes, m_itemReportedBy, m_itemHiddenText;
public ImageView m_itemMapDrop;
public MyViewHolder(View view) {
super(view);
m_itemName = (TextView) view.findViewById(R.id.lstItemName);
m_itemMapDrop = (ImageView) view.findViewById(R.id.lstItemMap);
}
}
#Override
public void onBindViewHolder(TrackedItemListAdapter.MyViewHolder holder, int position) {
holder.m_itemName.setText(obj.getName());
holder.m_itemMapDrop.setImageResource(R.drawable.ic_img_nomap);
holder.m_itemMapDrop.setOnClickListener(new View.OnClickListener() {
//#Override
public void onClick(View v) {
startMap();
}
});
}
}
m_trackedItemListAdapter = new TrackedItemListAdapter();
m_recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
m_recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
m_recyclerView.setLayoutManager(mLayoutManager);
m_recyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));
m_recyclerView.setItemAnimator(new DefaultItemAnimator());
m_recyclerView.setAdapter(m_trackedItemListAdapter);
m_recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getApplicationContext(), m_recyclerView, new RecyclerTouchListener.ClickListener() {
#Override
public void onClick(View view, int position) {
//a hack to turn off response if the imageview for location already responded
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
popupItemContent();
}
}, 200);
}
}
use this in your ConstraintLayout:
descendantFocusability="blocksDescendants"

Something wrong happens with RecyclerView

New items are added to RecyclerView each time when Adapter have created.
In photo I showed a process where darken dish images appear, though I managed image darking with a condition if(holder.mDish.getPicurl()!=null), but it doest work.
If I go into darken dish image details and go back to list, there will by three darken images. Is it problem with RecyclerView or it is my fault?
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.mDish = DISHES.get(position);
final int id = holder.mDish.getId();
if(holder.mDish.getPicurl()!=null) {
Picasso.with(mContext)
.load(holder.mDish.getPicurl())
.fit()
.transform(new RoundedTransformation(20, 0))
.into(holder.mIvBackground);
holder.mIvBackground.setColorFilter(Color.parseColor("#aaaaaa"), PorterDuff.Mode.MULTIPLY);
} else {
holder.mIvBackground.setImageResource(R.drawable.vector_drawable_dish);
}
holder.mTvName.setText(holder.mDish.getName());
//holder.mTvDescription.setText(holder.mDish.getDescription());
holder.mTvPrice.setText("T " + String.valueOf(holder.mDish.getPrice()));
holder.mBtnAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(mListener!=null){
mListener.onAddToBasketInteraction(id);
}
}
});
holder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mListener.onStartDetailActivity(id);
}
});
}
public void addDishes(List<Dish> dishes){
DISHES.clear();
DISHES.addAll(dishes);
notifyDataSetChanged();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public Dish mDish;
public final View mView;
public final ImageView mIvBackground;
public final TextView mTvName;
//public final TextView mTvDescription;
public final TextView mTvPrice;
public final ImageButton mBtnAdd;
public ViewHolder(View itemView) {
super(itemView);
mView = itemView;
mIvBackground = (ImageView) itemView.findViewById(R.id.dishBackground);
mTvName = (TextView) itemView.findViewById(R.id.name);
//mTvDescription = (TextView) itemView.findViewById(R.id.description);
mTvPrice = (TextView) itemView.findViewById(R.id.price);
mBtnAdd = (ImageButton) itemView.findViewById(R.id.btnAdd);
}
}
xml of item:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="90dp"
android:orientation="horizontal"
android:padding="2dp">
<ImageView
android:id="#+id/dishBackground"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Плов узбекский"
android:textColor="#color/colorAccent2"
android:layout_marginLeft="5dp"
android:layout_marginBottom="5dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:textSize="14sp" />
<TextView
android:id="#+id/price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:layout_marginTop="5dp"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="T 3000"
android:textColor="#android:color/holo_orange_light" />
<ImageButton
android:id="#+id/btnAdd"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:background="#drawable/ic_add_shopping_cart_black_24dp" />
</RelativeLayout>
You don't undo view changes in conditional statement
The culprit is this piece of code:
if(holder.mDish.getPicurl()!=null) {
Picasso.with(mContext)
.load(holder.mDish.getPicurl())
.fit()
.transform(new RoundedTransformation(20, 0))
.into(holder.mIvBackground);
holder.mIvBackground.setColorFilter(Color.parseColor("#aaaaaa"), PorterDuff.Mode.MULTIPLY);
} else {
holder.mIvBackground.setImageResource(R.drawable.vector_drawable_dish);
}
The way RecyclerView works is it reuses the same views with a different data (hence recycler), so the onBindViewHolder method may be called multiple times for each position, but the ViewHolder might have been already created and previously bound to a different piece of data. That way some changes applied to the view inside the onBindViewHolder method might persist through bind calls to different pieces of data.
In your case, the following call:
holder.mIvBackground.setColorFilter(Color.parseColor("#aaaaaa"), PorterDuff.Mode.MULTIPLY);
alters the view with the color filter within one call to onBindViewHolder. Then, when another piece of data is bound to the same ViewHolder, the condition holder.mDish.getPicurl()!=null might be false, but the effect still persists, because there is no removal of this color filter in the else branch of your statement.
Fix
You need to explicitly set and unset any changes to a single view in your RecyclerView for every separate condition you wish to implement:
if(holder.mDish.getPicurl()!=null) {
holder.mIvBackground.setColorFilter(Color.parseColor("#aaaaaa"), PorterDuff.Mode.MULTIPLY);
} else {
holder.mIvBackground.setColorFilter(null); // removes color filter
}
You don't see any problems with your mIvBackground because you set a different one in each branch of your if-else statement, so no unwanted state persists.

Respond to buttons click in RecyclerView

I have a RecyclerView where the user has to click the elements to cast a vote to that specific player.
Current Layout
As it's not that much intuitive, I'd like to add Buttons on the right side of each element to let the user understand that he needs to click if he wants to cast a vote.
Question
How do I make a custom layout like that? Probably using a GridLayout? And mostly, how do I get the Button's element's position when the button (and it only) gets clicked?
Code
list_players.xml | http://pastebin.com/F7Ei07x9
two_line_list_item_horizontal.xml | http://pastebin.com/s8qvwqt4
CourseAdapter.java | http://pastebin.com/qZJeimfe
Replace your CoursesAdapter's onBindViewHolder with this.
#Override
public void onBindViewHolder(CoursesViewHolder holder, int position) {
Player player = mArrayCourses.get(position);
holder.name.setText(player.getName());
holder.counter.setText(String.valueOf(player.getCount()));
holder.voteButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Do your work here
}
});
}
You can use LinearLayout to add button to your Recyclerview item by giving them weight.
You can handle onClicklistener of that button in ViewHolder class and you can get position of clicked button by getAdapterPosition() in ViewHolder class.
As per your request :
XML :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="5">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:text="ABCD"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:text="A"/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Vote"/>
</LinearLayout>
Adapter :
public class Holder extends RecyclerView.ViewHolder{
Button btnVote;
public Holder(View itemView) {
super(itemView);
btnVote = (Button) itemView.findViewById(R.id.btn_vote);
btnVote.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//list.get(getAdapterPosition()); Use for get the data on selected item
}
});
}
}

Android onTouchListener not working, works only at the Padding area

I'm definitely doing something wrong. I have a ReclyclerView and the each cell has a XML home_cells.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:paddingRight="12dp"
android:paddingLeft="12dp"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:clickable="true">
<android.support.v7.widget.CardView
android:id="#+id/home_cv"
android:clickable="true"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
......
android:paddingTop="16dp">
<LinearLayout
....
android:orientation="horizontal">
<ImageView
...
android:src="#drawable/abc_ratingbar_full_material" />
<LinearLayout
......
android:orientation="vertical">
<TextView
.....
android:textStyle="bold" />
<TextView
....
android:textColor="#color/secondaryTextColor" />
</LinearLayout>
<ImageView
....
android:src="#mipmap/ic_chevron_right_black_24dp" />
</LinearLayout>
</RelativeLayout>
</android.support.v7.widget.CardView>
<!--<lay-->
</LinearLayout>
I have an adapter... everything works fine..... no problem at all.
BUT, when i try to implement onClickLister to complete cell view mView IT DOES NOT WORK. If I touch in the corner ( where i have padding) IT WORKS.
I have no idea what is happening. If i set listener to every element in the cell it works... but not the whole cell.
Below is my viewHolder
class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
CardView cv;
ImageView icon;
TextView heading;
TextView subheading;
View mView;
public MyViewHolder(View itemView) {
super(itemView);
Log.d(TAG, "setting images and items");
mView=itemView;
cv = (CardView)itemView.findViewById(R.id.home_cv);
icon =(ImageView) itemView.findViewById(R.id.home_rv_icon);
heading =(TextView) itemView.findViewById(R.id.heading);
subheading =(TextView) itemView.findViewById(R.id.subhead);
icon.setOnClickListener(this); // Working
mView.setOnClickListener(this); // NOT working
mView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
// NOT Working
return true;
}
});
}
#Override
public void onClick(View view) {
//
Log.d(TAG,"on click");
if(clickListener!=null){
Log.d(TAG,"listner notnull");
clickListener.itemClick(view,getAdapterPosition());
}
}
}
public interface RVClickListener{
//OnClick will work, but for better coding standard i made this listener to call the onclick from the fragment it self..
public void itemClick(View view, int position );
}
After few hours of struggle if finally fixed it. Here is the problem.
Since my layout has child views (layouts) the onclicklistener is being captured by them.
So solved it by a simple solution. I turned off the clickable for all the child views and applied the click listener to the parent.
To all the child views:
android:clickable="false"
Remove longClickable = "true" from every child view of the CardView Layout

Categories

Resources