Something wrong happens with RecyclerView - android

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.

Related

First item in RecyclerView not clickable

I am currently implementing the ability to click on an item of an RecyclerView in an Android App. Yet I am stuck with some weird bug where I can only register the clicks on all items but the first one.
This is my layout for each item
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="listItemClick">
<TextView
android:id="#+id/spacer2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:text=" "
android:textSize="8sp" />
<TextView
android:id="#+id/headerTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_below="#+id/spacer2"
android:text="[Auftraggeber] - [Ort]"
android:textAppearance="#style/TextAppearance.AppCompat.Body2"
android:textSize="18sp" />
<TextView
android:id="#+id/captionTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_below="#+id/headerTextView"
android:text="Erstellt am 21.05.1999" />
<TextView
android:id="#+id/spacer3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_below="#+id/captionTextView"
android:text=" "
android:textSize="8sp" />
</RelativeLayout>
I'm using the listItemClick in my MainActivity in order to execute code upon clicking on an item. Further more i'm passing data through the tag of one of the textviews (which I assume not to be the problem).
This is listItemClick():
public void listItemClick (View v){
Toast.makeText(getApplicationContext(), ("You clicked: " + v.findViewById(R.id.headerTextView).getTag()), Toast.LENGTH_LONG).show();
System.out.println("Clicked");
}
This is the Adapter I implemented for the RecyclerView:
public class RapportListAdapter extends RecyclerView.Adapter<RapportListAdapter.ViewHolder> {
private ArrayList<RapportStructure> 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 implements View.OnClickListener {
// each data item is just a string in this case
public RelativeLayout mRelativeLayout;
public ViewHolder(RelativeLayout v) {
super(v);
mRelativeLayout = v;
}
#Override
public void onClick(View view) {
System.out.println("WORKS");
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public RapportListAdapter(ArrayList<RapportStructure> myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
#Override
public RapportListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
RelativeLayout rl = (RelativeLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.celllayout, parent, false);
ViewHolder vh = new ViewHolder(rl);
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
TextView headerTextView = (TextView) holder.mRelativeLayout.findViewById(R.id.headerTextView);
TextView captionTextView = (TextView) holder.mRelativeLayout.findViewById(R.id.captionTextView);
RapportStructure rs = this.mDataset.get(position);
headerTextView.setText("ClientID:" + rs.getClientId() + " - " + rs.getPlace());
captionTextView.setText("Erstellt am " + rs.getCreatedOn().toString());
headerTextView.setTag(position);
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return mDataset.size();
}
}
I would like the first list item to be clickable as well. If you need any more information, just ask :)
I too have current problem.
after remove animation, my problem resolved. ):
This bug seems to have killed itself. I don't know why. I can use the first element now to open up a new Activity. Thanks for all the help!

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"

How to change an ImageView, that is part of a list item?

I have a ListView that shows list items (duh). When you click on a list item, another Activity opens. Part of the list item layout is a grey star, an ImageView. When you click on this ImageView, I don't want to open another Activity, but I want to change the color of the star to green (= mark the item as favourite) or back (= mark it as not favourite). I managed to do that with an OnClickListener, loading another ImageView on Click, and refreshing the adapter. But for the ImageView to change, after clicking it I need to leave the Activity and enter again. It doesn't refresh instantly. Why, and how can I change that? I've tried lots of different versions, so far nothing works. My ListViewAdapter extends BaseAdapter. Thank you!
public class ListViewAdapterKeysAToZ extends BaseAdapter {
private ArrayList<KeyTagIntern> keyTags;
private ObservableArrayList<KeyTagIntern> list;
private Context context;
TextView name;
TextView place;
ImageView star, favoriteStar;
public ListViewAdapterKeysAToZ(Context context, ObservableArrayList<KeyTagIntern> list)
{
this.context = context;
this.list = list;
keyTags = new ArrayList<>();
for (KeyTagIntern keytag : list) {
keyTags.add(keytag);
}
//(....)
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
KeyTagIntern key = (KeyTagIntern) getItem(position);
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.list_item_keys, parent, false);
}
name = (TextView) convertView.findViewById(R.id.text_keylist_item);
name.setText(key.getName());
place = (TextView) convertView.findViewById(R.id.text_keylist_item_place);
place.setText(key.getPlace());
star = (ImageView) convertView.findViewById(R.id.right_icon_keylist_item);
favoriteStar = (ImageView) convertView.findViewById(R.id.right_icon_keylist_item_favorite);
if (key.isFavorite())
{
star.setVisibility(View.INVISIBLE);
favoriteStar.setVisibility(View.VISIBLE)
favoriteStar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// This makes key.isFavourite() = false for the next time
Paper.book().delete(FAVORIT + String.valueOf(key.getKeyTagID()));
//Since notifyDataSetChanged() didn't work for me, I tried this - but no change
int index = list.indexOf(key);
list.remove(index);
list.add(index, key);
keyTags = new ArrayList<>();
for (KeyTagIntern keytag : list) {
keyTags.add(keytag);
}
notifyDataSetChanged();
}
});
}
// Then do the opposite for if (!key.isFavourite())
Und hier das xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/list_item_keys"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#color/MiddleDarkGrey">
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/btn_list_item_keys"
android:layout_width="match_parent"
android:layout_height="#dimen/height_list_item"
android:layout_marginBottom="3dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="3dp"
android:background="#drawable/white_list_item"
android:paddingLeft="13dp"
android:paddingRight="10dp">
<ImageView
android:id="#+id/icon_keylist_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:visibility="visible"
app:srcCompat="#drawable/ic_key" />
<ImageView
android:id="#+id/icon_reserved"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/chb_add_key"
android:layout_centerVertical="true"
android:visibility="invisible"
app:srcCompat="#drawable/ic_reservate_orange" />
<ImageView
android:id="#+id/icon_taken"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/chb_add_key"
android:layout_centerVertical="true"
android:visibility="invisible"
app:srcCompat="#drawable/ic_taken_red" />
<TextView
android:id="#+id/text_keylist_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:layout_toEndOf="#+id/icon_keylist_item"
android:layout_toRightOf="#+id/icon_keylist_item"
android:gravity="center_vertical"
android:layout_centerVertical="true"
android:text="Text"
android:textColor="#color/DarkGrey"
android:textSize="#dimen/text_list_item" />
<TextView
android:id="#+id/text_keylist_item_place"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/text_keylist_item"
android:layout_alignLeft="#+id/text_keylist_item"
android:layout_marginLeft="2dp"
android:layout_marginBottom="5dp"
android:text="Where is the key?"
android:textColor="#color/DarkGrey"
android:textSize="#dimen/text_list_item_sub" />
<ImageView
android:id="#+id/right_icon_keylist_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
app:srcCompat="#drawable/ic_fav_green" />
<ImageView
android:id="#+id/right_icon_keylist_item_favorite"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="#drawable/ic_fav_chosen"
android:visibility="invisible"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
</RelativeLayout>
I think your approach should be something like this.
rather hiding and displaying an image just change source of it!
if (key.isFavorite())
{
favoriteStar.setImageResource(R.drawable.aaa);
favoriteStar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
favoriteStar.setImageResource(R.drawable.bbb);
// and vice-versa
and I don't thing you will be needing notifyDataSetChanged(); as you are making no changes in the Listdata actually!
In the end the answer was rather stupid, as it is so often, and you guys couldn't have helped me since I excluded the code at the beginning of my adapter class (added it now). It actually worked the whole time, but I didn't see it, since the listitem at the very end of the list was changed, not the selected one. This was due to me declaring the variables at the beginning of the adapter class, rather than inside the getView method.
I changed it to this and now it works perfectly:
public class ListViewAdapterKeysAToZ extends BaseAdapter {
private ArrayList<KeyTagIntern> keyTags;
private ObservableArrayList<KeyTagIntern> list;
private Context context;
public ListViewAdapterKeysAToZ(Context context, ObservableArrayList<KeyTagIntern> list) {
this.context = context;
this.list = list;
keyTags = new ArrayList<>();
for (KeyTagIntern keytag : list) {
keyTags.add(keytag);
}
// (...)
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
KeyTagIntern key = (KeyTagIntern) getItem(position);
TextView name;
TextView place;
ImageView star, favoriteStar;
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.list_item_keys, parent, false);
}
name = (TextView) convertView.findViewById(R.id.text_keylist_item);
name.setText(key.getName());
place = (TextView) convertView.findViewById(R.id.text_keylist_item_place);
place.setText(key.getPlace());
star = (ImageView) convertView.findViewById(R.id.right_icon_keylist_item);
favoriteStar = (ImageView) convertView.findViewById(R.id.right_icon_keylist_item_favorite);
if (key.isFavorite()) {
star.setVisibility(View.INVISIBLE);
favoriteStar.setVisibility(View.VISIBLE);
}else {
star.setVisibility(View.VISIBLE);
favoriteStar.setVisibility(View.INVISIBLE);
}
star.setOnClickListener(v -> {
key.setFavorite(true);
Paper.book().write(FAVORIT + String.valueOf(key.getKeyTagID()), true);
notifyDataSetChanged();
});
favoriteStar.setOnClickListener(v -> {
key.setFavorite(false);
Paper.book().delete(FAVORIT + String.valueOf(key.getKeyTagID()));
notifyDataSetChanged();
});

Check Box listener on RecyclerView with DataBinding

im trying to populate a list of note/message with check box in the item view.
Ive tried set listener unto the checkbox. sadly upon check box click nothing happens.
if i set listener unto the parent view. its able to trigger onClick method. but this will be triggered each time user click the whole item in the list.
my objectives is more on setting listener for checkbox.
so ill know that user has selected note(s) from the list.
heres my code adapter class together with view holder inner class
public class BroadcastRVA extends RecyclerView.Adapter<BroadcastRVA.BroadcastVH>{
private Context mContext;
private ObservableArrayList<MNote> notes;
private LayoutInflater inflater;
public BroadcastRVA(Context mContext, ObservableArrayList<MNote> notes, LayoutInflater inflater) {
this.mContext = mContext;
this.notes = notes;
this.inflater = LayoutInflater.from(mContext);
}
#Override
public BroadcastRVA.BroadcastVH onCreateViewHolder(ViewGroup parent, int viewType) {
NoteListitemBinding binding = NoteListitemBinding.inflate(inflater);
View view = LayoutInflater.from(parent.getContext()).inflate(
R.layout.note_listitem, null);
BroadcastVH viewHolder = new BroadcastVH(binding, view);
// create a new view
return viewHolder;
}
#Override
public void onBindViewHolder(BroadcastVH holder, final int position) {
final MNote note = notes.get(position);
holder.cbox.setChecked(note.isSelected());
holder.cbox.setTag(note);
holder.vBinding.setNote(note);
holder.cbox.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
CheckBox cb = (CheckBox) v;
MNote note = (MNote) cb.getTag();
note.setIsSelected(cb.isChecked());
notes.get(position).setIsSelected(cb.isChecked());
Toast.makeText(
v.getContext(),
"Clicked on Checkbox: " + cb.getText() + " is "
+ cb.isChecked(), Toast.LENGTH_LONG).show();
}
});
}
public ObservableArrayList<MNote> getNotes() {
return notes;
}
/**
* Returns the total number of items in the data set hold by the adapter.
*
* #return The total number of items in this adapter.
*/
#Override
public int getItemCount() {
if (notes != null)
return notes.size();
else return 0;
}
public class BroadcastVH extends RecyclerView.ViewHolder {
NoteListitemBinding vBinding;
TextView uuid;
CheckBox cbox;
public BroadcastVH(NoteListitemBinding binding, View view) {
super(binding.getRoot());
this.vBinding = binding;
this.uuid = (TextView) view.findViewById(R.id._UUID);
this.cbox = (CheckBox) view.findViewById(R.id.deleteNote);
}
}
}
note_list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="note"
type="com.pbasolutions.android.model.MNote" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:weightSum="1">
<TableLayout android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<CheckBox
android:layout_width="30dp"
android:layout_height="wrap_content"
android:id="#+id/deleteNote"
android:clickable="true"/>
<TextView
android:layout_width="270dp"
android:layout_height="wrap_content"
android:id="#+id/textViewNote"
android:layout_column="1"
android:layout_marginLeft="5dp"
android:text="#{note.textMsgs}"
android:editable="false"
android:textSize="22sp"/>
<TableLayout android:layout_column="1">
<TableRow>
<TextView
android:layout_width="80dp"
android:layout_height="wrap_content"
android:id="#+id/textViewNoteDate"
android:layout_column="0"
android:text="#{note.date}"
android:editable="false"
android:textSize="15sp"/>
</TableRow>
</TableLayout>
<TextView
android:layout_width="270dp"
android:layout_height="wrap_content"
android:id="#+id/_UUID"
android:layout_marginLeft="5dp"
android:text="#{note._UUID}"
android:visibility="invisible"/>
</TableRow>
</TableLayout>
<View style="#style/Line" />
</LinearLayout>
</layout>
what is NoteListitemBinding ? generally speaking ,onClick method must be triggered when you click the checkbox,when you click the view,the viewgroup will receive the touch event first and then pass the event to its child but if the viewgroup prevent the event,the event will consumed,and child cannot get the event, its onClick method will not be triggered.
thanks to #ljl5241861 for mentioning on DataBinding, i realized there small silly mistake in my code.. in order to get the child view responds onClick in need to get the view from databinding.getRoot() not the recycler specific one item group view. after change the ViewHolder constructor, by getting the item view via binding.getRoot, i able to trigger the click listener.. hope this helps others as well!!
public BroadcastVH(NoteListitemBinding binding, View view) {
super(binding.getRoot());
this.vBinding = binding;
View bindView = binding.getRoot();
this.uuid = (TextView) bindView.findViewById(R.id._UUID);
this.cbox = (CheckBox) bindView.findViewById(R.id.deleteNote);
}

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