0

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>

Mohammad Elsayed
  • 1,885
  • 1
  • 20
  • 46

4 Answers4

1

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

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);
    }
}
Badr At
  • 658
  • 7
  • 22
1

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);
}}
Shrikant
  • 1,560
  • 1
  • 15
  • 32
  • I have been using rv for 2 years now, but thanks anyway, I knew the answer, the rep for effort, really appreciated – Mohammad Elsayed Feb 27 '19 at 11:23
  • Thanks, if you can mark this correct it shall help fellow members in future. – Shrikant Feb 27 '19 at 12:25
  • its not the solution to my problem, I added the solution down there, the issue is: I was making intensive processing and socket communications in the mainThread, so the soln is to transfer those actions into other thread – Mohammad Elsayed Feb 27 '19 at 12:27
0

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.

Mohammad Elsayed
  • 1,885
  • 1
  • 20
  • 46