I do the processing of click in the Activity.
#Override
public void onClick(View view) {
switch (view.getId()) {
final RecyclerView avaRecycler = (RecyclerView) view2.findViewById(R.id.ava_recycler);
avaRecycler.setLayoutManager(new GridLayoutManager(PersonEditActivity.this, 3));
avaRecycler.setHasFixedSize(true);
final AvaChooseRecyclerAdapter avaChooseRecyclerAdapter = new AvaChooseRecyclerAdapter(PersonEditActivity.this, new AvaChooseRecyclerAdapter.AvaViewHolder.MyClickListener() {
#Override
public void onAvaClickListener(int position) {
Toast.makeText(view2.getContext(), "Выбрана ава " + position, Toast.LENGTH_SHORT).show();
chosenId = (int) avaRecycler.getAdapter().getItemId(position);
avaRecycler.getAdapter().notifyItemChanged(position);
}
});
avaRecycler.setAdapter(avaChooseRecyclerAdapter);
Layout of the item
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/ava_item"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/ava_item_imageview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
app:srcCompat="#drawable/avatars_man" />
<ImageView
android:id="#+id/ava_badge_yes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|right"
android:layout_marginRight="0dp"
android:layout_marginTop="0dp"
android:visibility="invisible"
app:layout_constraintRight_toRightOf="#+id/ava_item_imageview"
app:layout_constraintTop_toTopOf="#+id/ava_item_imageview"
app:srcCompat="#drawable/avatars_yes" />
I can not figure out how to change the visibility of ava_badge_yes by clicking on ava_item_imageview.
Edit.
My Adapter for recyclerview
public class AvaChooseRecyclerAdapter extends RecyclerView.Adapter<AvaChooseRecyclerAdapter.AvaViewHolder> {
private static final String TAG = "AvaChooseAdapter";
Context context;
private AvaChooseRecyclerAdapter.AvaViewHolder.MyClickListener myClickListener;
List<Integer> resourceIds = Arrays.asList(
R.drawable.avatars_01, R.drawable.avatars_02, R.drawable.avatars_03,
R.drawable.avatars_04, R.drawable.avatars_05, R.drawable.avatars_06,
R.drawable.avatars_07, R.drawable.avatars_08, R.drawable.avatars_09,
R.drawable.avatars_10, R.drawable.avatars_11, R.drawable.avatars_12,
R.drawable.avatars_13, R.drawable.avatars_14, R.drawable.avatars_15,
R.drawable.avatars_16, R.drawable.avatars_17, R.drawable.avatars_18,
R.drawable.avatars_19, R.drawable.avatars_20, R.drawable.avatars_21,
R.drawable.avatars_22, R.drawable.avatars_23, R.drawable.avatars_24,
R.drawable.avatars_25, R.drawable.avatars_26, R.drawable.avatars_27,
R.drawable.avatars_28, R.drawable.avatars_29, R.drawable.avatars_30,
R.drawable.avatars_31, R.drawable.avatars_32, R.drawable.avatars_33,
R.drawable.avatars_34, R.drawable.avatars_35, R.drawable.avatars_36,
R.drawable.avatars_37, R.drawable.avatars_38, R.drawable.avatars_39,
R.drawable.avatars_40, R.drawable.avatars_41, R.drawable.avatars_42,
R.drawable.avatars_43, R.drawable.avatars_44, R.drawable.avatars_45,
R.drawable.avatars_46, R.drawable.avatars_47, R.drawable.avatars_48,
R.drawable.avatars_49, R.drawable.avatars_50, R.drawable.avatars_51,
R.drawable.avatars_52, R.drawable.avatars_53, R.drawable.avatars_54,
R.drawable.avatars_55, R.drawable.avatars_56, R.drawable.avatars_57,
R.drawable.avatars_58, R.drawable.avatars_59, R.drawable.avatars_60,
R.drawable.avatars_61, R.drawable.avatars_62, R.drawable.avatars_63,
R.drawable.avatars_64, R.drawable.avatars_65, R.drawable.avatars_66);
public AvaChooseRecyclerAdapter(Context context, AvaChooseRecyclerAdapter.AvaViewHolder.MyClickListener m) {
this.context = context;
myClickListener = m;
}
public static class AvaViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
protected MyClickListener myClickListener;
protected ImageView iv;
public AvaViewHolder(View itemView, MyClickListener myClickListener) {
super(itemView);
this.myClickListener = myClickListener;
iv = (ImageView) itemView.findViewById(R.id.ava_item_imageview);
iv.setOnClickListener(this);
}
#Override
public void onClick(View view) {
if (myClickListener != null) myClickListener.onAvaClickListener(getLayoutPosition());
}
public interface MyClickListener {
void onAvaClickListener(int position);
}
}
#Override
public long getItemId(int position) {
return resourceIds.get(position);
}
#Override
public AvaChooseRecyclerAdapter.AvaViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
context = parent.getContext();
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.ava_item, parent, false);
v.setPadding(14, 14, 14, 14);
return new AvaViewHolder(v, myClickListener);
}
#Override
public void onBindViewHolder(AvaViewHolder holder, int position) {
holder.iv.setImageResource(resourceIds.get(position));
Log.d(TAG, "onBindViewHolder position: " + position + " | " + holder.toString());
}
#Override
public int getItemCount() {
return resourceIds.size();
}
public getItem(int position){
}
}
And i want to understand.
On the forums write 3 options for processing clicks in the recyclerview
1. in ViewHolder
2. in OnBindViewHolder
3. With the use of the interface and the transfer of click processing in the activity. (I used this option)
But I don't understand the principle of choosing the place of treatment of pressing. In which cases to choose this or that method?
I would be very grateful if you explain. Highly.
Modify the onclick in Adapter & see if , click item change the color
#Override
public void onClick(View view) {
if (myClickListener != null) myClickListener.onAvaClickListener(getLayoutPosition());
AvaViewHolder.iv.setBackgroundColor(Color.rgb(100, 100, 50));
}
}
Related
I have implemented a RecyclerView inside a ConstraintLayout. I am having one child image element inside the layout. But when I click the child image, it always returns the ConstraintLayout, not the clicked image.
Could you please tell me why this is happening, what is the solution for this ?
I separately did bind listener to image, it is working but not able to get the RecyclerItem object. I need RecyclerItem object for the position to proceed.
I implemented it by binding elements via onBindViewholder method in Adapter. Below are the codes
customAdapter = new GridViewAdapter(recyclerItems, 1, this.getContext().getPackageName(),
new GridViewAdapter.OnItemClickListener(){
#Override
public void onItemClick(RecyclerItem item) {
CommonUtil.addFragment("REP", Constants.CONTAINER_HOME,
new ModifyFragment(), getActivity(), null);
}
}, R.layout.rec_view_item_stock, Constants.V_SPAN_LIST_8);
RecyclerView recyclerView = view.findViewById(R.id.stockListRecView);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setLayoutManager(new GridLayoutManager(this.getContext(), 1));
recyclerView.setAdapter(customAdapter);
//Adapter
public class GridViewAdapter extends RecyclerView.Adapter<GridViewAdapter.ViewHolder>{
private List<RecyclerItem> dataItems;
private int hSpan = 1;
private String packageName;
private final OnItemClickListener listener;
private int inflator;
private int vSpan;
public interface OnItemClickListener {
void onItemClick(RecyclerItem item);
}
public static class ViewHolder extends RecyclerView.ViewHolder {
private final ConstraintLayout constraintLayout;
private final TextView textView;
private final ImageView imageView;
private Object obj;
public ViewHolder(View view) {
super(view);
constraintLayout = (ConstraintLayout) view.findViewById(R.id.rec_content_layout);
textView = constraintLayout.findViewById(R.id.recTextView);
imageView = constraintLayout.findViewById(R.id.recImage);
}
public void bind(final RecyclerItem item, final OnItemClickListener listener) {
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
listener.onItemClick(item);
}
});
}
public TextView getTextView() {
return textView;
}
public ImageView getImageView() {
return imageView;
}
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
}
public GridViewAdapter(List<RecyclerItem> items, int spanCount, String packageName, OnItemClickListener listener,
int inflator, int vSpan) {
dataItems = items;
this.hSpan = spanCount;
this.packageName = packageName;
this.listener = listener;
this.inflator = inflator;
this.vSpan = vSpan;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int gridType) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(inflator, viewGroup, false);
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
layoutParams.width = (viewGroup.getResources().getDisplayMetrics().widthPixels / hSpan) - 24;
if(Constants.V_SPAN_GRID == vSpan) {
layoutParams.height = layoutParams.width;
} else {
layoutParams.height = (viewGroup.getResources().getDisplayMetrics().widthPixels / vSpan);
}
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
viewHolder.getTextView().setText(dataItems.get(position).getText());
int imgId = viewHolder.getImageView().getResources().getIdentifier(
dataItems.get(position).getImageName(), "drawable", packageName);
viewHolder.getImageView().setImageResource(imgId);
viewHolder.setObj(dataItems.get(position));
viewHolder.bind(dataItems.get(position), listener);
}
#Override
public int getItemCount() {
return dataItems.size();
}
//item layout
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/rec_content_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:layout_marginTop="8dp"
android:layout_marginLeft="4dp"
android:padding="8dp"
android:background="#drawable/border_top_bottom" >
<androidx.constraintlayout.widget.Guideline
android:id="#+id/viewstock_gline_1_v"
android:layout_width="1dp"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.6"/>
<ImageView
android:id="#+id/recImage"
android:background="#color/colorPrimaryDark"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp" />
<TextView
android:id="#+id/recTextView"
app:layout_constraintLeft_toRightOf="#+id/recImage"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp" />
<ImageView
android:id="#+id/editstock_image"
android:src="#drawable/ic_edit_stock"
android:background="#color/colorPrimaryDark"
app:layout_constraintRight_toLeftOf="#+id/deletestock_image"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp" />
<ImageView
android:id="#+id/deletestock_image"
android:src="#drawable/ic_delete_stock"
android:background="#color/colorPrimaryDark"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp" />
</androidx.constraintlayout.widget.ConstraintLayout>```
Try this!
public void bind(final RecyclerItem item, final OnItemClickListener listener, TextView itemTextView) {
itemTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
listener.onItemClick(item);
}
});
}
Pass every item text view instance from the view holder or fro onBindViewHolder itself implement onclick listener
I making a list of usernames and call buttons, each username has a call button next to it, when I click the call button the code inside the call button does not get executed in all clicks, I tried to make the whole item clickable so that if the user clicks on the button, the username or any part in the layout_item the code gets executed but no change happened.
Here is how I am implementing the adapter:
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View mView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.freind_list_item, parent,false);
return new MyViewHolder(mView);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
Friend friend = friends.get(position);
holder.btnInitCallHandler(friend.getUsername(), friend.get_id());
holder.setUsername(friend.getUsername());
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView txtUsername;
Button btnInitCallWithFriend;
RelativeLayout rlInsteadOfButtonHandler;
MyViewHolder(View itemView) {
super(itemView);
txtUsername = itemView.findViewById(R.id.txt_friend_item);
btnInitCallWithFriend = itemView.findViewById(R.id.btnInitCallWithFriendNormal);
friendState = itemView.findViewById(R.id.onlineState);
signedAsGlasses = itemView.findViewById(R.id.signedInAsGlasses);
signedAsLaptop = itemView.findViewById(R.id.signedInAsLaptop);
rlInsteadOfButtonHandler = itemView.findViewById(R.id.rlInsteadButtonHandler);
}
void setUsername(String username) {
txtUsername.setText(username);
}
void btnInitCallHandler(String username, String userId) {
btnInitCallWithFriend.setOnClickListener((view) -> {
Timber.tag("KingArmstringNormalUserCall").d("normal user call button clicked from the adapter");
viewAccessor.initCall(username, userId);
});
rlInsteadOfButtonHandler.setOnClickListener((v) -> {
viewAccessor.initCall(username, userId);
});
}
}
the viewAccessor is just an interface implemented by the activity, and have only one method (initCall)
the initCall(username, userId) in the Activity has only a toast and a log
EDIT:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="100dp"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal"
android:background="#android:color/black"
android:padding="10dp">
<TextView
android:id="#+id/txt_friend_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/txt_friend_name_placeholder"
android:textSize="30sp"
android:layout_gravity="center"
android:gravity="center"
android:textColor="#color/colorAccent"/>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
<RelativeLayout
android:id="#+id/rlInsteadButtonHandler"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
<!--<at.markushi.ui.CircleButton-->
<!--android:id="#+id/btnInitCallWithFriend"-->
<!--android:layout_width="70dp"-->
<!--android:layout_height="40dp"-->
<!--android:src="#drawable/ic_video_call"-->
<!--android:layout_marginStart="10dp"-->
<!--android:layout_gravity="center"-->
<!--android:focusable="false"-->
<!--android:focusableInTouchMode="false"-->
<!--app:cb_color="#fff"-->
<!--android:layout_alignParentEnd="true"/>-->
<Button
android:id="#+id/btnInitCallWithFriendNormal"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_gravity="center"
android:layout_marginStart="10dp"
android:layout_marginTop="0dp"
android:layout_marginBottom="0dp"
android:focusable="true"
android:text="call" />
</RelativeLayout>
use below code on constructor of MyViewHolder class. This code makes an item clickable.
itemView.setClickable(true);
Also set onClickLiester on MyViewHolder class. Then use getAdapterPostion() method to determine which item clicked.
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dataList.get(getAdapterPosition()); //this code will return the clicked item object.
});
First remove btnInitCallHandler() function from your ViewHolder, then set the clickListener directly in your viewHolder, you can get the current item from your list by calling getAdapterPosition() for exemple:
btnInitCallWithFriend.setOnClickListener((view) -> {
Timber.tag("KingArmstringNormalUserCall").d("normal user call button clicked from the adapter");
viewAccessor.initCall(friends.get(getAdapterPosition).getUsername(), friends.get(getAdapterPosition).get_id());
});
so this your new adapter class:
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View mView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.freind_list_item, parent,false);
return new MyViewHolder(mView);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
//do your stuff
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView txtUsername;
Button btnInitCallWithFriend;
RelativeLayout rlInsteadOfButtonHandler;
MyViewHolder(View itemView) {
super(itemView);
txtUsername = itemView.findViewById(R.id.txt_friend_item);
btnInitCallWithFriend = itemView.findViewById(R.id.btnInitCallWithFriendNormal);
friendState = itemView.findViewById(R.id.onlineState);
signedAsGlasses = itemView.findViewById(R.id.signedInAsGlasses);
signedAsLaptop = itemView.findViewById(R.id.signedInAsLaptop);
rlInsteadOfButtonHandler = itemView.findViewById(R.id.rlInsteadButtonHandler);
btnInitCallWithFriend.setOnClickListener((view) -> {
Timber.tag("KingArmstringNormalUserCall").d("normal user call button clicked from the adapter");
viewAccessor.initCall(friends.get(getAdapterPosition).getUsername(), friends.get(getAdapterPosition).get_id());
});
rlInsteadOfButtonHandler.setOnClickListener((v) -> {
viewAccessor.initCall(friends.get(getAdapterPosition).getUsername(), friends.get(getAdapterPosition).get_id());
});
}
void setUsername(String username) {
txtUsername.setText(username);
}
}
Following is a simple yet powerful implementation of RecylcerView. Try to read out the basics of recycler view and why viewholder is used. Hope this helps you out.
public class TestActivity extends Activity implements TestAdapter.ItemClickListener {
TestAdapter adapter;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_layout);
ArrayList<String> testNames = new ArrayList<>();
testNames.add("Horse");
testNames.add("Cow");
testNames.add("Camel");
testNames.add("Sheep");
testNames.add("Goat");
RecyclerView recyclerView = findViewById(R.id.testList);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new TestAdapter(this, testNames);
adapter.setClickListener(this);
recyclerView.setAdapter(adapter);
}
#Override
public void onItemClick(View view, int position) {
Toast.makeText(this, "You clicked " + adapter.getItem(position) + " on row number " + position, Toast.LENGTH_SHORT).show();
}}
Following is adapter class implementation
public class TestAdapter extends RecyclerView.Adapter<TestAdapter.MyViewHolder> {
private ItemClickListener mClickListener;
private List<String> mData;
private Activity mActivity;
public TestAdapter(TestActivity testActivity, ArrayList<String> testNames) {
this.mData = testNames;
this.mActivity = testActivity;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View mView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.test_row, parent, false);
return new MyViewHolder(mView);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
String animal = mData.get(position);
holder.txtUsername.setText(animal);
}
#Override
public int getItemCount() {
return mData.size();
}
public String getItem(int position) {
return mData.get(position);
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView txtUsername;
Button btnInitCallWithFriend;
MyViewHolder(View itemView) {
super(itemView);
txtUsername = itemView.findViewById(R.id.txt_friend_item);
btnInitCallWithFriend = itemView.findViewById(R.id.btnInitCallWithFriendNormal);
//friendState = itemView.findViewById(R.id.onlineState);
//signedAsGlasses = itemView.findViewById(R.id.signedInAsGlasses);
//signedAsLaptop = itemView.findViewById(R.id.signedInAsLaptop);
btnInitCallWithFriend.setOnClickListener((View view) -> {
Toast.makeText(mActivity, "You clicked call " + getAdapterPosition() + " position", Toast.LENGTH_SHORT).show();
});
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (mClickListener != null) {
mClickListener.onItemClick(itemView, getAdapterPosition());
}
}
});
}
}
// allows clicks events to be caught
void setClickListener(ItemClickListener itemClickListener) {
this.mClickListener = itemClickListener;
}
// parent activity will implement this method to respond to click events
public interface ItemClickListener {
void onItemClick(View view, int position);
}}
I have finally figured out whats happening, I have been handling lots of things in the foreground, I have transferred lots of them to other threads, now it worked, u might don't believe me, but many really experienced people said to me, that they encountered a very similar situations.
I'm trying to set an onClickListener on one of my image on my recyclerview but the click doesn't work.
It looks like it doesn't seems to see there is a onClickListener, because when I set a "point" for the debugger on my listener it doesn't go to the point.
What I have done wrong ?
public class Item_List_Adapter extends RecyclerView.Adapter<Item_List_Adapter.MyViewHolder> {
// declare array
private String[] mDataset;
private Context mContext;
public static class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
public TextView itemName;
public ImageView mAddBtn;
public MyViewHolder(View v){
super(v);
itemName = (TextView) v.findViewById(R.id.item_name);
mAddBtn = (ImageView) v.findViewById(R.id.action_add);
}
#Override
public void onClick(View v) {
System.out.println("TEST: ");
switch (v.getId()) {
case R.id.action_add:
System.out.println("TEST2: ");
break;
default:
break;
}
}
}
// constructor
public Item_List_Adapter(Context context, String[] myDataset) {
mDataset = myDataset;
mContext = context;
}
#Override
public int getItemCount() {
return mDataset.length;
}
#Override
public Item_List_Adapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, parent, false);
MyViewHolder nv = new MyViewHolder(v);
return nv;
}
#Override
public void onBindViewHolder(Item_List_Adapter.MyViewHolder holder, final int position) {
holder.itemName.setText(mDataset[position]);
holder.mAddBtn.setOnClickListener(holder);
}
}
and my XML file the one inflate in the recycler view
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="10dp"
android:paddingBottom="10dp">
<LinearLayout
android:id="#+id/list_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginEnd="15dp"
android:layout_marginStart="15dp">
<ImageView
android:id="#+id/action_check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_action_check"
android:alpha="0.3"
/>
<TextView
android:id="#+id/item_name"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight=".2"
android:hint="Wine"
android:alpha="0.3"
android:gravity="start|center"
android:paddingStart="5dp"
android:paddingLeft="5dp"/>
<ImageView
android:id="#+id/action_remove"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_action_remove_green"
android:onClick="item_remove"
/>
<ImageView
android:id="#+id/action_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_action_add_blue"
/>
<ImageView
android:id="#+id/action_chart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_action_chart"
android:scaleType="centerInside"
android:onClick="chart_detail"
/>
</LinearLayout>
</LinearLayout>
Thanks in advance
you should use Log to output to the console
Log.d("TAG","TEST: );
for experimentation sake try this out in your ViewHolder constructor
mAddBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.d("TAG","TEST: );
}
});
If it doesn't work then something is blocking the click, this could be simply setting clickable="true" in the xml, or figuring out what is on front of the view
The following is how I used in my Adapter. Hope this help:
public class EventArrayAdapter extends RecyclerView.Adapter<ViewHolder> {
private OnItemClickListener onItemClickListener;
public OnItemClickListener getOnItemClickListener() {
return onItemClickListener;
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
public interface OnItemClickListener {
public void onItemClick(View view, int position);
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
//Add your viewHolder.button.setOnClickListener here as normal
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int arg1) {
// TODO Auto-generated method stub
View v = LayoutInflater.from(context).inflate(
R.layout.layout_item_event, parent, false);
final EventViewHolder holder = new EventViewHolder(v);
v.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
onItemClickListener.onItemClick(v, holder.getAdapterPosition());
}
});
return holder;
}
}
update your constructor like this and try. It will work.
public MyViewHolder(View v){
super(v);
itemName = (TextView) v.findViewById(R.id.item_name);
mAddBtn = (ImageView) v.findViewById(R.id.action_add);
mAddBtn.setOnClickListener(this);
}
Basically assign onClick listener to your Imageview
I've got a RecyclerView which populates from an ArrayList. The output is a CardView layout.
In the Cardview, there are 2 buttons amongst other Views.
They only have to read the current value of a TextView, which by default is 1, and increase or decrease it.
The Arraylist contains 8 items.
When I run the app the UI works fine. Trouble is when I try to modify the value of the TextView.
The value is correctly increased and decreased on the CardView I'm working on, but ALSO the value is modified on another CardView. And in that second CardView, modifying its TextView value, also modifies the first one.
So, what am I doing wrong?
This is my Fragment:
public class Fragment_rosas extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.layout_rosas,container,false);
RecyclerView recyclerview_rosas;
RecyclerView.Adapter adaptador_rv_rosas;
RecyclerView.LayoutManager lm_rosas;
List rosas = new ArrayList();
rosas.add(new Tropa(1,R.drawable.minibarbaro, getResources().getString(R.string.barbaro),7,1));
recyclerview_rosas = (RecyclerView) view.findViewById(R.id.recyclerView_tropasRosas);
recyclerview_rosas.setHasFixedSize(true);
lm_rosas = new LinearLayoutManager(getContext());
recyclerview_rosas.setLayoutManager(lm_rosas);
adaptador_rv_rosas = new AdaptadorTropa(rosas);
recyclerview_rosas.setAdapter(adaptador_rv_rosas);
return view;
}
}
And here the part of code on my Adapter:
#Override
public void onBindViewHolder(final TropaViewHolder viewHolder, int i) {
viewHolder.imagen.setImageResource(items.get(i).getImagen());
viewHolder.nombre.setText(items.get(i).getNombre());
viewHolder.maxnivel.setText(String.valueOf(items.get(i).getNivelMax()));
viewHolder.espacioencamp.setText((String.valueOf(items.get(i).getEspacioEnCamp())));
final String nombre = items.get(i).getNombre();
final int maxnivel = items.get(i).getNivelMax();
viewHolder.nivelmas.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String niveltemp = viewHolder.nivel.getText().toString();
String nivelmaxtemp = viewHolder.maxnivel.getText().toString();
int nivel = Integer.parseInt(niveltemp);
int maxxnivel = Integer.parseInt(nivelmaxtemp);
int nuevonivel = nivel+1 ;
if (nuevonivel<=maxxnivel) {
viewHolder.txtv_nivel.setText(String.valueOf(nuevonivel));
}
}
});
My OnCreateViewHolder (nothing really happens here):
#Override
public TropaViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.cardview, viewGroup, false);
return new TropaViewHolder(v);
}
Here is the solution, as mentioned in the comment above, it addresses two problems:
1. positiontoValueMap - saves current value for each position
2. onclicklistener is passed to the ViewHolder in onCreateViewHolder
Adapter Class
public class MyAdapter extends RecyclerView.Adapter {
private Context context;
private List<String> dataList;
private Map<Integer, Integer> positionToValueMap = new HashMap<>();
public MyAdapter(Context context, List<String> dataList) {
this.context = context;
this.dataList = dataList;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.recycler_view_item, null, false);
return new MyViewHolder(view, new OnRecyclerItemClickListener());
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((MyViewHolder) holder).onRecyclerItemClickListener.updatePosition(position);
((MyViewHolder) holder).position.setText("" + position);
((MyViewHolder) holder).title.setText(dataList.get(position));
int valueToDisplay = 1;
if(positionToValueMap.containsKey(position)) {
valueToDisplay = positionToValueMap.get(position);
} else {
positionToValueMap.put(position, valueToDisplay);
}
((MyViewHolder) holder).valueView.setText("value: " + valueToDisplay);
}
#Override
public int getItemCount() {
return dataList.size();
}
private class MyViewHolder extends RecyclerView.ViewHolder {
private OnRecyclerItemClickListener onRecyclerItemClickListener;
private TextView position;
private TextView title;
private TextView valueView;
public MyViewHolder(View itemView, OnRecyclerItemClickListener onRecyclerItemClickListener) {
super(itemView);
itemView.setOnClickListener(onRecyclerItemClickListener);
this.onRecyclerItemClickListener = onRecyclerItemClickListener;
this.position = (TextView) itemView.findViewById(R.id.position);
this.title = (TextView) itemView.findViewById(R.id.title);
this.valueView = (TextView) itemView.findViewById(R.id.value_view);
}
}
private class OnRecyclerItemClickListener implements View.OnClickListener {
private int position = -1;
public void updatePosition(int position) {
this.position = position;
}
#Override
public void onClick(View v) {
int oldValue = positionToValueMap.get(position); // get current value
oldValue++; // increment
positionToValueMap.put(position, oldValue); // save current value
notifyItemChanged(position); // update clicked view so that it picks up the new saved value from the positionToValueMap in onBindViewHolder
}
}
}
RecyclerView item layout
<TextView
android:id="#+id/position"
android:layout_width="30dp"
android:layout_height="50dp"
android:textColor="#android:color/white"
android:gravity="center"
android:background="#android:color/holo_green_light"
android:layout_alignParentLeft="true"/>
<TextView
android:id="#+id/title"
android:layout_width="50dp"
android:layout_height="50dp"
android:textColor="#android:color/white"
android:gravity="center"
android:background="#android:color/holo_green_dark"
android:layout_toRightOf="#id/position" />
<TextView
android:id="#+id/value_view"
android:layout_width="match_parent"
android:layout_height="50dp"
android:textColor="#android:color/white"
android:gravity="center"
android:background="#android:color/holo_green_light"
android:layout_toRightOf="#id/title"
android:layout_alignParentRight="true"/>
</RelativeLayout>
And Activity to test it out
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
recyclerView.setAdapter(new MyAdapter(getApplicationContext(), getSampleData()));
}
private static List<String> getSampleData() {
List<String> dataList = new ArrayList<>();
dataList.add("zero");
dataList.add("one");
dataList.add("two");
dataList.add("three");
dataList.add("four");
dataList.add("five");
dataList.add("six");
dataList.add("seven");
dataList.add("eight");
dataList.add("nine");
dataList.add("ten");
dataList.add("eleven");
dataList.add("twelve");
dataList.add("thirteen");
dataList.add("fourteen");
dataList.add("fifteen");
dataList.add("sixteen");
dataList.add("seventeen");
dataList.add("eighteen");
dataList.add("nineteen");
dataList.add("twenty");
return dataList;
}
}
activity layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/root_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"/>
</RelativeLayout>
Here is my recyclerview item_courses.xml:
<android.support.v7.widget.CardView
android:id="#+id/card_view"
android:layout_width="fill_parent"
android:layout_height="150dp"
android:layout_margin="5dp"
card_view:cardCornerRadius="2dp"
card_view:contentPadding="20dp">
<TableLayout
android:layout_width="match_parent"
android:layout_height="121dp"
android:stretchColumns="*">
<TableRow
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="#+id/textView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:layout_column="0"
android:textColor="#color/testcolor"
android:textSize="18sp"
android:textStyle="bold"
android:layout_span="30"
android:text="Course Name"
android:paddingBottom="40dp"
android:paddingRight="20dp"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:src="#drawable/btn_course_menu"
android:layout_span="3"
android:id="#+id/person_photo"
android:onClick="CreatePopupMenu"
android:layout_column="28" />
</TableRow>
<TableRow
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="#+id/textView2"
android:text="10 students"
android:layout_gravity="left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/testcolor"
android:layout_column="0"
android:layout_span="13"
android:paddingTop="0dp"
android:paddingBottom="0dp"
/>
<TextView
android:id="#+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="right"
android:textColor="#color/testcolor"
android:layout_span="13"
android:layout_column="20" />
</TableRow>
</TableLayout>
</android.support.v7.widget.CardView>
Here is my recyclerview adapter
public class MyRecyclerViewAdapter extends RecyclerView
.Adapter<MyRecyclerViewAdapter
.DataObjectHolder> {
private static String LOG_TAG = "MyRecyclerViewAdapter";
private ArrayList<Person> mDataset;
private static MyClickListener myClickListener;
public static class DataObjectHolder extends RecyclerView.ViewHolder
implements View
.OnClickListener {
TextView subject;
TextView studentno;
TextView classno;
public DataObjectHolder(View itemView) {
super(itemView);
subject = (TextView) itemView.findViewById(R.id.textView);
studentno = (TextView) itemView.findViewById(R.id.textView2);
classno = (TextView) itemView.findViewById(R.id.textView3);
Log.i(LOG_TAG, "Adding Listener");
itemView.setOnClickListener(this);
}
#Override
public void onClick(final View v) {
myClickListener.onItemClick(getPosition(), v);
}
}
public void setOnItemClickListener(MyClickListener myClickListener) {
this.myClickListener = myClickListener;
}
public MyRecyclerViewAdapter(ArrayList<Person> myDataset) {
mDataset = myDataset;
}
#Override
public DataObjectHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_courses, parent, false);
DataObjectHolder dataObjectHolder = new DataObjectHolder(view);
return dataObjectHolder;
}
#Override
public void onBindViewHolder(DataObjectHolder holder, int position) {
holder.subject.setText(mDataset.get(position).getmText1());
holder.studentno.setText(mDataset.get(position).getmText2());
holder.classno.setText(mDataset.get(position).getmText3());
}
public void addItem(Person dataObj, int index) {
mDataset.add(index, dataObj);
notifyItemInserted(index);
}
public void deleteItem(int index) {
mDataset.remove(index);
notifyItemRemoved(index);
}
#Override
public int getItemCount() {
return mDataset.size();
}
public interface MyClickListener {
public void onItemClick(int position, View v);
}
}
Suppose their is only one item named in popum menu (named : popup_menu.xml).
menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/option1"
android:title="Option 1" />
So when it was clicked on option1. how to determine on which recyclerview item it was clicked ?
Popup menu anchored to an ImageView (star) in a RecyclerView item:
Position of RecyclerView item displayed when a popup menu item is selected:
To achieve this we need to modify your DataObjectHolder to do two things:
Anchor a popup menu to the image view when it is clicked.
Handle popup menu item click.
We use a custom listener, PopupMenuListener to pass the RecyclerView item, its position in the adapter to be specific, hosting the popup menu that was just clicked.
Modified DataObjectHolder:
public static class DataObjectHolder extends RecyclerView.ViewHolder implements View
.OnClickListener, PopupMenu.OnMenuItemClickListener {
private final MyClickListener myClickListener;
private final PopupMenuListener popupMenuListener;
TextView subject;
TextView studentno;
TextView classno;
View imageView;
public interface MyClickListener {
void onItemClick(int position, View v);
}
public interface PopupMenuListener {
void onPopupMenuClicked(MenuItem menuItem, int adapterPosition);
}
public DataObjectHolder(View itemView, MyClickListener myClickListener, PopupMenuListener popupMenuListener) {
super(itemView);
this.myClickListener = myClickListener;
this.popupMenuListener = popupMenuListener;
subject = (TextView) itemView.findViewById(R.id.textView);
studentno = (TextView) itemView.findViewById(R.id.textView2);
classno = (TextView) itemView.findViewById(R.id.textView3);
imageView = itemView.findViewById(R.id.person_photo);
// Configure image view to show a popup menu when it is clicked:
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
showPopupMenu(view);
}
});
Log.i(LOG_TAG, "Adding Listener");
itemView.setOnClickListener(this);
}
#Override
public void onClick(final View v) {
myClickListener.onItemClick(getAdapterPosition(), v);// IMPORTANT: 'getPosition()' is deprecated.
}
private void showPopupMenu(View view) {
PopupMenu popup = new PopupMenu(view.getContext(), view);
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.popup_menu, popup.getMenu());
popup.setOnMenuItemClickListener(this);
popup.show();
}
/*
* Popup menu callback.
*/
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.option1:
// Call popup menu listener passing the menu item that was clicked as well as the recycler view item position:
popupMenuListener.onPopupMenuClicked(item, getAdapterPosition());
return true;
default:
return false;
}
}
}
Just implement PopupMenuListener and pass it to DataObjectHolder's constructor and we're good to go!
public class MyAdapter extends RecyclerView.Adapter<MyAdapter. XInfoHolder > {
public MyAdapter(Context ctx,ArrayList<Data> dataInfo) {
..........
........
}
#Override
public PersonInfoHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
//* creating view from the layout for child element in the listview by using inflater*//*
View itemView = ........
return new ViewHolder(itemView);
}
#Override
public void onBindViewHolder(PersonInfoHolder personInfoHolder, int i) { ...
....
}
#Override
public int getItemCount() {
return data.size();
}
public class XInfoHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
protected ImageView popupMenu;
public XInfoHolder(View itemView) {
super(itemView);
popupMenu = (ImageView) itemView.findViewById(R.id.pop_up);
popupMenu.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (getLayoutPosition() == 0/something else && v.getId() == R.id.pop_up) {
//show your popup all other place view is invisible
//do whatever else here
}
}
}
}
}
This is how i solved this problem for my project. Thanks and best of luck.