Customization, optimization and click events of Android ListView

                                                                                                                                                Read the "First Line of Code - 2nd Edition" notes

ListView allows users to scroll off-screen data into the screen by sliding their fingers up and down.


set layout file

<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />            

Read data in MainActivity and display it in listview

adding data:

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

Get data in onCreate:

ArrayAdapter<String> adapter = new ArrayAdapter<String>(
        MainActivity.this,android.R.layout.simple_list_item_1,data);
ListView listView = findViewById(R.id.list_view);
listView.setAdapter(adapter);
The data in the array cannot be directly transferred to the ListView, and an adapter is required.
The ArrayAdapter adapter specifies the data type to be adapted through generics, and then passes in the adapted data in the constructor.
In the constructor of the ArrayAdapter, pass in the current context, the id of the sub-layout item of the ListView, and the data to be adapted.
I used android.R.layout.simple_list_item_1 as the id of the sub-layout item of ListView, which is an Android built-in layout file
with only one Textview in it, which is used to display a simple text.
Finally, call the setAdapter method of the listview to pass in the adapter object.

Customize the interface of ListView

If you want to add a picture in front of the text: First, you need to prepare a set of pictures yourself.
Define an entity class as the adaptation type of the ListView adapter.
Create a new Fruit:

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

    public String getName() {
        return name;
    }

    public int getImageId() {
        return imageId;
    }
}

Create a new fruit_item.xml under the layout directory

Add a textview and an imageview

Next you need to create a custom adapter that inherits from ArrayAdapter and assigns the generic to the Furit class.

public class FruitAdapter extends ArrayAdapter<Fruit> {
    private int resourceId;
    public FruitAdapter(Context context, int textViewResouceId, List<Fruit> objects){
        super(context,textViewResouceId,objects);
resourceId = textViewResouceId;
}            

    @NonNull
    @Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {    
        Fruit fruit = getItem(position);
        View view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
        ImageView fruitImage = view.findViewById(R.id.fruit_image);
        TextView fruitName = view.findViewById(R.id.fruit_name);
        fruitImage.setImageResource(fruit.getImageId());
        fruitName.setText(fruit.getName());
        return view;
    }
}

    FruitAdapter overrides a set of constructors of the parent class to pass in the context, ID and data of the ListView child layout.

In addition, the getView() method is overridden, which is called when each child item is scrolled into the screen. In the getView() method, first get the Fruit instance of the current item through the getItem() method. Then use LayoutInflater to load the incoming layout for this child.

     LayoutInflater的inflater()方法接收3个参数,第三个参数指定成false是表示只让在父布局中声明layout属性生效,但不会为这个View添加父布局,因为一旦View有了父布局之后就不能再添加到LIstview中了。

    修改MainActivity中的代码:

private List<Fruit> fruitList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initFruit();//初始化水果数据
    FruitAdapter adapter = new FruitAdapter(MainActivity.this,R.layout.fruit_item,fruitList);
    ListView listView = findViewById(R.id.list_view);
    listView.setAdapter(adapter);
    
}

private void initFruit() {
    for(int i =0 ; i<2 ;i++){
        Fruit apple = new Fruit("Apple",R.drawable.apple_pic);
        fruitList.add(apple);
        //类似添加其他元素
    }
}

这样就可以完成一个自定义的ListView。

优化ListView    

以上方法虽然创建了一个自定义的ListView但是运行效率很低,因为在FruitAdapter的getView()方法中每次都会将布局重新加载一次,当listview快速滚动时就会成为功能的瓶颈。

    在getView()方法中的convertView参数用于将之前加载的布局进行缓存,以便之后进行重用。

    新增一个内部类ViewHolder,用于对控件的实例进行缓存。当convertView为null的时候,创建一个ViewHolder对象,并将控件的实例都存放在ViewHolder中,然后调用view的setTag()方法,将ViewHolder对象存储在View中。
当convertView不为null的时候取出。这样所有控件的实例都缓存在ViewHolder里,大大提高了效率。

修改FruitAdapter如下:

public class FruitAdapter extends ArrayAdapter<Fruit> {
    private int resourceId;
    public FruitAdapter(Context context, int textViewResouceId, List<Fruit> objects){
        super(context,textViewResouceId,objects);
        resourceId = textViewResouceId;
    }

    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        Fruit fruit = getItem(position);
        View view ;
        ViewHolder viewHolder;
        if(convertView == null){
            view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
            viewHolder = new ViewHolder();
            viewHolder.fruitImage=view.findViewById(R.id.fruit_image);
            viewHolder.fruitName = view.findViewById(R.id.fruit_name);
            view.setTag(viewHolder);
        }else{
           view  = convertView;
           viewHolder = (ViewHolder) view.getTag();
        }

        viewHolder.fruitImage.setImageResource(fruit.getImageId());
        viewHolder.fruitName.setText(fruit.getName());
        return view;
    }

    private class ViewHolder {
        ImageView fruitImage;
        TextView fruitName;
    }
}

ListView的点击事件

 添加listview的点击事件,onItemClick()方法。

listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
        Fruit  fruit = fruitList.get(i);
        Toast.makeText(MainActivity.this,fruit.getName(),
                Toast.LENGTH_SHORT).show();
    }
});

    






Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324407526&siteId=291194637