Create a ListView custom control for Android

The most commonly used and most difficult to use control-ListView

ListView is definitely one of the most commonly used controls in Android. Almost all applications will use it.
ListView allows users to scroll the data outside the screen into the screen by sliding their fingers up and down, while the original data on the screen will scroll out of the screen.
However, the usage of ListView is relatively more complicated than the previous controls.

New project ListViewTest

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></ListView>
</LinearLayout>

A ListView usually has two responsibilities.
(1) Fill the data into the layout.
(2) Process the user's selection, click and other operations.
The creation of a ListView requires three elements
(1) View of each column in the ListView
(2) Fill in the data or pictures of the View.
(3) Adapter for connecting data and ListView.
In other words, to use ListView, you must first understand what an adapter is.
Adapter is a bridge that connects data and AdapterView (ListView is a typical AdapterView)
. Through it, it can effectively realize the separation of data and AdaterView, making the binding of AndroidView and data easier and more convenient for modification.
Many Adapters are provided in Android

Adapter meaning

ArrayAdapter is used to bind an array and supports generic operations

SimpleAdapter is used to bind the data corresponding to the control defined in xml

SimpleCursorAdapter is used to bind the data obtained by the cursor

BaseAdapter Universal base adapter

In fact, there are many adapters. It should be noted that various adapters are just different in conversion methods and capabilities.

package net.nyist.lenovo.listviewtest;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class MainActivity extends AppCompatActivity {
    
    

private String[] data = {
    
    "Apple","Banana","Orange","Watermelon","Pear","Grape","Pineapple","Strawberry","Cherry","Mango",
        "Apple","Banana","Orange","Watermelon","Pear","Grape","Pineapple","Strawberry","Cherry","Mango"};

@Override
protected void onCreate(Bundle savedInstanceState) {
    
    
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(
            MainActivity.this,android.R.layout.simple_list_item_1,data);
    ListView listView= (ListView)findViewById(R.id.list_view);
    listView.setAdapter(adapter);
}
}

Since ListView is used to display a large amount of data, we should provide the data first. These data can be downloaded from the Internet or read from the database, depending on the specific application scenario. Here I use a simple data array to test, which contains the names of many fruits.
However, the data in the array cannot be directly passed to the ListView, we also need to use an adapter to complete.
ArrayAdpter has multiple overloaded constructors, and the appropriate one should be selected according to the actual situation.
Since the data we provide are all strings, we specify the generic type of ArrayAdapter as String, and then pass in the current context, the id of the LitView subitem layout, and the data to be adapted in the ArrayAdapter's constructor. Note that we used android.R.layout.simple_list_item_1 as the id of the ListView subitem layout. This is an Android built-in layout file with only one TextView, which can be used to simply display a piece of text. In this way, the adapter object is constructed.
Finally, you need to call the setAdapter() method of ListView to pass in the constructed adapter object, so that the association between ListView and data is established.
[External link image transfer failed. The source site may have an anti-leech link mechanism. It is recommended to save the image and upload it directly (img-0I9U22qy-1587024879884)(http://i.imgur.com/xBKRLfV.png)] #Custom
ListView Interface
The ListView that can only display a paragraph of text is too monotonous. Let's customize the interface of the ListView so that it can display richer content.
First, you need to prepare a set of pictures.
Then define an entity class as the adaptation type of the ListView adapter. Create a new Fruit, the code is as follows:

package net.nyist.lenovo.listviewtest;
public class Fruit {
    
    
private String name;

private int imageId;

public Fruit(String name ,int imageId){
    
    
    this.name = name;
    this.imageId = imageId;
}

public int getImageId() {
    
    
    return imageId;
}

public String getName() {
    
    
    return name;
}
}

There are only two fields in the Fruit class, name represents the name of the fruit, and imageId represents the resource id of the image corresponding to the fruit.
Then we need to specify a custom layout for the children of ListView, create a new fruit_item.xml in the layout directory. The code is as follows:

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

<ImageView
    android:id="@+id/fruit_image"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

<TextView
    android:id="@+id/fruit_name"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_vertical"
    android:layout_marginLeft="10dp"
    />
</LinearLayout>

In this layout, we define an ImageView to display pictures of fruits, and define a TextView to display the name of the fruits, and let the TextView display in the center in the vertical direction.

Next, you need to create a custom adapter that inherits from ArrayAdapter and assign the generic as the Fruit class. Create a new class FruitAdapter, the code is as follows:

package net.nyist.lenovo.listviewtest;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;

public class FruitAdapter extends ArrayAdapter<Fruit>{
    
    

private int resourceId;

public FruitAdapter(Context context, int textViewResourceId, List<Fruit>objects){
    
    
    super(context,textViewResourceId,objects);
    resourceId = textViewResourceId;
}


@Override
public View getView(int position,  View convertView,  ViewGroup parent) {
    
    
    Fruit fruit = getItem(position);//获取当前项的Fruit实例
    View view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
    ImageView fruitImage = (ImageView)view.findViewById(R.id.fruit_image);
    TextView fruitName = (TextView)view.findViewById(R.id.fruit_name);
    fruitImage.setImageResource(fruit.getImageId());
    fruitName.setText(fruit.getName());
    return view;
}
}

// Load the layout manager and convert the xml layout into a view object
View view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
//Use the view object to find the components in the layout
ImageView fruitImage = ( ImageView)view.findViewById(R.id.fruit_image);
TextView fruitName = (TextView)view.findViewById(R.id.fruit_name);
FruitAdapter
rewrites a set of constructors of the parent class to combine the context and ListView children The id and data of the layout are passed in.
In addition, the getView() method is overridden. This method is called when each child item is scrolled to the screen. In the getView() method, first obtain the Fruit instance of the current item through the getItem() method, and then use LayoutInflater to load the layout we passed in for this child item.
Here, the inflate() method of LayoutInflater receives three parameters. We already know what the first two parameters mean, and the third parameter is specified as false, which means that only the layout attribute declared in the parent layout is valid, but not for this View adds a parent layout, because once a View has a parent layout, it can no longer be added to the ListView.
Next, call the findViewById() method of View to obtain the instances of ImageView and TextView respectively.
And call their setImageResource() and setText() methods to set the displayed picture and text, and finally return the layout, so that the defined adapter is completed.
Modify the code in MainActivity as follows:

package net.nyist.lenovo.listviewtest;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    
    

private List<Fruit>fruitList = new ArrayList<>();



private String[] data = {
    
    "Apple","Banana","Orange","Watermelon","Pear","Grape","Pineapple","Strawberry","Cherry","Mango",
        "Apple","Banana","Orange","Watermelon","Pear","Grape","Pineapple","Strawberry","Cherry","Mango"};

@Override
protected void onCreate(Bundle savedInstanceState) {
    
    
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initFruits();//初始化水果数据
    FruitAdapter adapter = new FruitAdapter(MainActivity.this,R.layout.fruit_item,fruitList);
    ListView listView= (ListView)findViewById(R.id.list_view);
    listView.setAdapter(adapter);
}
private void initFruits(){
    
    
    for (int i  = 0;i < 2;i++){
    
    
        Fruit apple = new Fruit("Apple",R.drawable.apple_pic);
        fruitList.add(apple);
        Fruit banana = new Fruit("Banana",R.drawable.banana_pic);
        fruitList.add(banana);
        Fruit orange = new Fruit("Orange",R.drawable.orange_pic);
        fruitList.add(orange);
        Fruit watermelon = new Fruit("Watermelon",R.drawable.watermelon_pic);
        fruitList.add(watermelon);
        Fruit pear = new Fruit("Pear",R.drawable.pear_pic);
        fruitList.add(pear);
        Fruit grape = new Fruit("Grape",R.drawable.grape_pic);
        fruitList.add(grape);
        Fruit pineapple = new Fruit("Pineapple",R.drawable.pineapple_pic);
        fruitList.add(pineapple);
        Fruit strawberry = new Fruit("Strawberry",R.drawable.strawberry_pic);
        fruitList.add(strawberry);
        Fruit cherry = new Fruit("Cherry",R.drawable.cherry_pic);
        fruitList.add(cherry);
        Fruit mango = new Fruit("Mango",R.drawable.mango_pic);
        fruitList.add(mango);

    }
}
}

Add an initFruits() method here to initialize all fruit data. In the constructor of the Fruit class, pass in the name of the fruit and the corresponding image id, and then add the created object to the fruit list. In addition, we use a for loop to add all fruit data twice. This is Because if you only add it once, the amount of data is not enough to fill the entire screen, then a FruitAdpter object is created in the onCreate() method and the FruitAdapter is passed to the ListView as an adapter, so that the task of customizing the ListView interface is done.

Write picture description here

#ListView's click event By the way
, the scrolling of the ListView only satisfies our visual effects after all, but if the child items in the ListView cannot be clicked, this control has no practical use. Therefore, in this section we will learn how ListView can respond to user click events.
Modify the code in MainActivity as follows:

public class MainActivity extends AppCompatActivity {
    
    

private List<Fruit>fruitList = new ArrayList<>();
private String[] data = {
    
    "Apple","Banana","Orange","Watermelon","Pear","Grape","Pineapple","Strawberry","Cherry","Mango",
        "Apple","Banana","Orange","Watermelon","Pear","Grape","Pineapple","Strawberry","Cherry","Mango"};

@Override
protected void onCreate(Bundle savedInstanceState) {
    
    
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initFruits();//初始化水果数据
    FruitAdapter adapter = new FruitAdapter(MainActivity.this,R.layout.fruit_item,fruitList);
    ListView listView= (ListView)findViewById(R.id.list_view);
    listView.setAdapter(adapter);
    listView.setOnItemClickListener(new AdapterView.OnItemClickListener(){
    
    
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    
    
            Fruit fruit = fruitList.get(position);
            Toast.makeText(MainActivity.this, fruit.getName(), Toast.LENGTH_SHORT).show();
        }
    });
}

As you can see, we use the setOnItemClickListener() method to register a listener for the ListView. When the user clicks on any child item in the ListView, the onItemClick() method will be called back. In this method, the position parameter can be used to determine which subitem the user clicked, and then the corresponding fruit can be obtained, and the name of the fruit can be displayed through Toast.

Guess you like

Origin blog.csdn.net/i_nclude/article/details/75263636