[JAVA] [Android] I want to get the listener from the button in ListView

Introduction

If you are developing an Android application, you will definitely meet "Hell to bite a custom Adapter into a ListView"

It wouldn't be possible once it was implemented. This time, I'd like to go further and put a Button inside the ListView.

Surprisingly, there are many scenes like this, right? A checkBox, a Button for editing or deleting.

This time I would like to do my best to make the UI below. It's a substitute for a personal memo.

click.gif

Make a caller for the time being

MainActivity.java


public class MainActivity extends AppCompatActivity {
  private static final String[] countries = {
    "America",
    "Japan",
    "China",
    "Korea",
    "British",
    "German"
  };

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ListView listView = (ListView) findViewById(R.id.listView);
    CustomAdapter adapter = new CustomAdapter(getApplicationContext(), R.layout.row_item, countries);
    listView.setAdapter(adapter);
    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
      @Override
      public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        switch (view.getId()) {
          case R.id.edit:
            Toast.makeText(MainActivity.this, countries[position] + "Edit button was pressed", Toast.LENGTH_SHORT).show();
            break;
          case R.id.delete:
            Toast.makeText(MainActivity.this, countries[position] + "The delete button was pressed", Toast.LENGTH_SHORT).show();
            break;
          }
       }
    });
  }
}

main_activity.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              tools:context="hiroto.myapplication.MainActivity">

  <ListView
    android:id="@+id/listView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:divider="@color/gray"
    android:dividerHeight="1dp"/>

</LinearLayout>

This time, only ListView is prepared for MainActivity. We are configuring a custom ListView that displays the text with two buttons by biting the ListView with the custom Adapter introduced below.

The caveat here is to give the ListView a SetOnItemClickListener to get the click event from the Adapter side. Don't forget ...

To determine which button the acquired event is, it is implemented by specifying the id in the switch statement.

Prepare a custom Adapter

CustomAdapter.java


class CustomAdapter extends BaseAdapter {
  private LayoutInflater inflater;
  private int resourcedId;
  private String[] items;

  static class ViewHolder {
    Button editButton;
    TextView textView;
    Button deleteButton;
  }

  CustomAdapter(Context context, int resourcedId, String[] items) {
    this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    this.resourcedId = resourcedId;
    this.items = items;
  }

  @Override
  public View getView(final int position, View convertView, final ViewGroup parent) {
    ViewHolder holder;
    if (convertView == null) {
      convertView = inflater.inflate(resourcedId, parent, false);

      holder = new ViewHolder();
      holder.editButton = convertView.findViewById(R.id.edit);
      holder.textView = convertView.findViewById(R.id.text);
      holder.deleteButton = convertView.findViewById(R.id.delete);
      convertView.setTag(holder);
   } else {
      holder = (ViewHolder) convertView.getTag();
   }

    holder.textView.setText(items[position]);

    holder.editButton.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
        ((ListView) parent).performItemClick(view, position, R.id.edit);
      }
    });
    holder.deleteButton.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
        ((ListView) parent).performItemClick(view, position, R.id.delete);
      }
    });

    return convertView;
  }

  @Override
  public int getCount() {
    return items.length;
  }

  @Override
  public Object getItem(int position) {
    return position;
  }

  @Override
  public long getItemId(int position) {
    return position;
  }
}

row_item.xml


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal">

  <Button
    android:id="@+id/edit"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentStart="true"
    android:text="Edit"/>

  <TextView
    android:id="@+id/text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:layout_marginStart="30dp"
    android:layout_toEndOf="@+id/edit"/>

  <Button
    android:id="@+id/delete"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentEnd="true"
    android:text="Delete"/>

</RelativeLayout>

In the custom Adapter, the part to be displayed in each line is acquired by findById, the text is the country name bysetText (), the button covers SetOnClickListener with performeItemClick, and the event is sent to the parent ListView. This method is the most recommended as it is relatively simple and does not interfere with other code.

At the end

What did you think? There are various ways to get the events in the ListView, but the one I introduced this time is the simplest, and I think it's easy to introduce because it doesn't have to be modified from the original code. Also, the flow is not so complicated, so I think it was easy to understand.

I hope it will be helpful to everyone.

Recommended Posts

[Android] I want to get the listener from the button in ListView
I want to get the value in Ruby
[Java] I want to calculate the difference from the date
I want to embed any TraceId in the log
Tokoro I rewrote in the migration from Wicket 7 to 8
I want to simplify the log output on Android
[Android Studio] I want to set restrictions on the values registered in EditText [Java]
# 1_JAVA I want to get the index number by specifying one character in the character string.
I want to set the conditions to be displayed in collection_check_boxes
What I did in the version upgrade from Ruby 2.5.2 to 2.7.1
I want to simplify the conditional if-else statement in Java
[Ruby on Rails] I want to get the URL of the image saved in Active Storage
I want to recreate the contents of assets from scratch in the environment built with capistrano
I want to get some properties as JSON strings in Jackson!
[Android / Java] Understand the description type in listener settings (button installation)
I want to remove the top margin in Grouped UITableView (swift)
[Java] I want to perform distinct with the key in the object
I want to change the value of Attribute in Selenium of Ruby
I want to use @Autowired in Servlet
[Ruby] I want to output only the odd-numbered characters in the character string
I want to write JSP in Emacs more easily than the default.
[Note] I want to get in reverse order using afterLast with JdbcTemplate
How to get the setting value (property value) from the database in Spring Framework
I want to display an error message when registering in the database
I want to get the field name of the [Java] field. (Old tale tone)
I want to find out what character the character string appears from the left
I want to output the day of the week
Run R from Java I want to run rJava
[Rails] I tried to raise the Rails version from 5.0 to 5.2
I want to send an email in Java.
I tried to organize the session in Rails
I want to use arrow notation in Ruby
3 ways to import the library in Android Studio
I want to var_dump the contents of the intent
How to get Class from Element in Java
I want to pass APP_HOME to logback in Gradle
rsync4j --I want to touch rsync in Java.
I want to play with Firestore from Rails
[Xcode] I want to manage images in folders
I want to be eventually even in kotlin
I want to write quickly from java to sqlite
I want to truncate after the decimal point
Get your version number in the Android app
I want to get the value of Cell transparently regardless of CellType (Apache POI)
I tried to get the distance from the address string to the nearest station with ruby
I want to recursively get the superclass and interface of a certain class
I want to get a list of only unique character strings by excluding fixed character strings from the file name
I want to output the character number from the left where an arbitrary character string appears.
I was addicted to the NoSuchMethodError in Cloud Endpoints
I want to go back to a specific VC by tapping the back button on the NavigationBar!
I want to use Combine in UIKit as well.
I want to use Clojure's convenient functions in Kotlin
I tried to organize the cases used in programming
I want to do something like "cls" in Java
I want to get the information of the class that inherits the UserDetails class of the user who is logged in with Spring Boot.
I want to use fish shell in Laradock too! !!
I want to use ES2015 in Java too! → (´ ・ ω ・ `)
I want to change the path after new registration after logging in with multiple devises.
I want to morphologically analyze the log in the DB and put it in the DB to classify messages 1
I want to judge the range using the monthly degree
I want to use a little icon in Rails