Mohammad Elsayed
Mohammad Elsayed

Reputation: 2066

buttons and don't get clicked in recyclerview in adapter

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>

Upvotes: 0

Views: 524

Answers (4)

Mohammad Elsayed
Mohammad Elsayed

Reputation: 2066

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.

Upvotes: 0

Shrikant
Shrikant

Reputation: 1580

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);
}}

Upvotes: 1

Badr At
Badr At

Reputation: 718

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);
    }
}

Upvotes: 1

Shahadat Hossain Shaki
Shahadat Hossain Shaki

Reputation: 806

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.
        });

Upvotes: 1

Related Questions