7. Android advanced controls (2) (list view)

1. The basic adapter BaseAdapter

Android provides a more adaptable base adapter BaseAdapter, which allows developers to perform logic processing in other code files. The data adapter derived from BaseAdapter mainly implements the following five methods.

Constructor: Specifies the collection of data that the adapter needs to process.

getCount: Get the number of data items.

getItem: Get the data of the list item.

getItemId: Get the ID of the list item.

getView: Get the display view of each item and manipulate the internal controls of each item.

Implementation steps for a basic adapter:

(1) Write the layout file item_list.xml of the list items.

(2) Write a new adapter to inherit BaseAdapter to realize the management operation of list items. Three methods need to be written for the adapter:

1) Create a construction method and pass in the data list required by the list item.

1) Override the getCount method to return the number of list items.

2) Rewrite the getView method to return the view content of the list item at the specified position according to the layout in item_list.xml. (3) Create the adapter instance in the page code, and give it to the drop-down box to set the adapter.

package com.example.chapter05.Bean;



import com.example.chapter05.R;

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

public class Planet {
    public int image; // 行星图标
    public String name; // 行星名称
    public String desc; // 行星描述

    public Planet(int image, String name, String desc) {
        this.image = image;
        this.name = name;
        this.desc = desc;
    }

    private static int[] iconArray = {R.drawable.shuixing, R.drawable.jinxing, R.drawable.diqiu,
            R.drawable.huoxing, R.drawable.muxing, R.drawable.tuxing};
    private static String[] nameArray = {"水星", "金星", "地球", "火星", "木星", "土星"};
    private static String[] descArray = {
            "水星是太阳系八大行星最内侧也是最小的一颗行星,也是离太阳最近的行星",
            "金星是太阳系八大行星之一,排行第二,距离太阳0.725天文单位",
            "地球是太阳系八大行星之一,排行第三,也是太阳系中直径、质量和密度最大的类地行星,距离太阳1.5亿公里",
            "火星是太阳系八大行星之一,排行第四,属于类地行星,直径约为地球的53%",
            "木星是太阳系八大行星中体积最大、自转最快的行星,排行第五。它的质量为太阳的千分之一,但为太阳系中其它七大行星质量总和的2.5倍",
            "土星为太阳系八大行星之一,排行第六,体积仅次于木星"
    };

    public static List<Planet> getDefaultList() {
        List<Planet> planetList = new ArrayList<Planet>();
        for (int i = 0; i < iconArray.length; i++) {
            planetList.add(new Planet(iconArray[i], nameArray[i], descArray[i]));
        }
        return planetList;
    }
}
package com.example.chapter05;

import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.Spinner;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;


import com.example.chapter05.Adapt.PlanetBaseAdapter;
import com.example.chapter05.Bean.Planet;

import java.util.List;

public class BaseAdapterActivity extends AppCompatActivity {
    private List<Planet> planetList; // 声明一个行星列表

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_base_adapter);
        initPlanetSpinner(); // 初始化行星列表的下拉框
    }

    // 初始化行星列表的下拉框
    private void initPlanetSpinner() {
        // 获取默认的行星列表,即水星、金星、地球、火星、木星、土星
        planetList = Planet.getDefaultList();
        // 构建一个行星列表的适配器
        PlanetBaseAdapter adapter = new PlanetBaseAdapter(this, planetList);
        // 从布局文件中获取名叫sp_planet的下拉框
        Spinner sp_planet = findViewById(R.id.sp_planet);
        sp_planet.setPrompt("请选择行星"); // 设置下拉框的标题
        sp_planet.setAdapter(adapter); // 设置下拉框的列表适配器
        sp_planet.setSelection(0); // 设置下拉框默认显示第一项
        // 给下拉框设置选择监听器,一旦用户选中某一项,就触发监听器的onItemSelected方法
        sp_planet.setOnItemSelectedListener(new MySelectedListener());
    }

    // 定义一个选择监听器,它实现了接口OnItemSelectedListener
    private class MySelectedListener implements OnItemSelectedListener {
        // 选择事件的处理方法,其中arg2代表选择项的序号
        public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
            Toast.makeText(BaseAdapterActivity.this, "您选择的是" + planetList.get(arg2).name, Toast.LENGTH_LONG).show();
        }

        // 未选择时的处理方法,通常无需关注
        public void onNothingSelected(AdapterView<?> arg0) {}
    }

}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <!-- 这是显示行星图片的图像视图 -->
    <ImageView
        android:id="@+id/iv_icon"
        android:layout_width="0dp"
        android:layout_height="80dp"
        android:layout_weight="1"
        android:scaleType="fitCenter" />

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="3"
        android:layout_marginLeft="5dp"
        android:orientation="vertical">

        <!-- 这是显示行星名称的文本视图 -->
        <TextView
            android:id="@+id/tv_name"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:gravity="left|center"
            android:textColor="@color/black"
            android:textSize="20sp" />

        <!-- 这是显示行星描述的文本视图 -->
        <TextView
            android:id="@+id/tv_desc"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="2"
            android:gravity="left|center"
            android:textColor="@color/black"
            android:textSize="13sp" />
    </LinearLayout>
</LinearLayout>

QQ screen recording 20221105164251

2. List view ListView

The list view allows similar data lists to be displayed on the page, such as news lists, product lists, book lists, etc., for the convenience of users to browse and operate. The similarities and differences between ListView and Spinner in coding:

(1) The same point: Both call the setAdapter method to set the data adapter of the list item, and both can use the basic adapter. (2) The difference: Spinner sets the selected listener of the list item through the setOnItemSelectedListener method; while ListView sets the click listener of the list item through the setOnItemClickListener method, and sets the long press listener of the list item through the setOnItemLongClickListener method.

package com.example.chapter05;

import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ListView;
import android.widget.Toast;

import com.example.chapter05.Adapt.PlanetBaseAdapter;
import com.example.chapter05.Bean.Planet;
import com.example.chapter05.util.Utils;

import java.util.List;

public class ListViewActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener, CompoundButton.OnCheckedChangeListener {

    private final static String TAG = "ListViewActivity";
    private CheckBox ck_divider;
    private CheckBox ck_selector;
    private ListView lv_planet; // 声明一个列表视图对象
    List<Planet> planetList = Planet.getDefaultList();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_list_view);
        lv_planet=findViewById(R.id.lv_planet);
        ck_divider=findViewById(R.id.ck_divider);
        ck_selector=findViewById(R.id.ck_selector);
        ck_selector.setOnCheckedChangeListener(this);
        ck_divider.setOnCheckedChangeListener(this);
        List<Planet> planetList=Planet.getDefaultList();
        PlanetBaseAdapter adapter=new PlanetBaseAdapter(this,planetList);
        lv_planet.setAdapter(adapter);
        lv_planet.setOnItemSelectedListener(this);
    }

    @Override
    public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {

    }

    @Override
    public void onNothingSelected(AdapterView<?> adapterView) {

    }

    @Override
    public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
        refleshListView();
    }

    //刷新试图列表
    @SuppressLint("ResourceType")
    private void refleshListView(){
        lv_planet.setCacheColorHint(Color.TRANSPARENT);//防止滚动时列表拉黑
        if (ck_divider.isChecked()){//显示分割线
            Drawable drawable=getResources().getDrawable(R.color.purple_200);
            lv_planet.setDivider(drawable); // 设置列表视图的分隔线
            lv_planet.setDividerHeight(Utils.dip2px(this, 5)); // 设置列表视图的分隔线高度
        }
        else {//不显示分割线
            lv_planet.setDivider(null); // 设置列表视图的分隔线
            lv_planet.setDividerHeight(0); // 设置列表视图的分隔线高度
        }
        if (ck_selector.isChecked()) { // 显示按压背景
            lv_planet.setSelector(R.drawable.list_selector); // 设置列表项的按压状态图形
        } else { // 不显示按压背景
            //lv_planet.setSelector(null); // 直接设置null会报错,因为运行时报空指针异常
            // 从资源文件获得图形对象
            Drawable drawable = getResources().getDrawable(R.color.purple_200);
            lv_planet.setSelector(drawable); // 设置列表项的按压状态图形
        }
    }

}
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@color/black"/>
    <item android:drawable="@color/purple_700"/>
</selector>
<?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"
    android:orientation="vertical"
    android:background="@color/white">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="40dp">

        <CheckBox
            android:id="@+id/ck_divider"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="left|center"
            android:text="显示分隔线"
            android:textColor="@color/black"
            android:textSize="17sp" />

        <CheckBox
            android:id="@+id/ck_selector"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="left|center"
            android:text="显示按压背景"
            android:textColor="@color/black"
            android:textSize="17sp" />

    </LinearLayout>

    <ListView
        android:id="@+id/lv_planet"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:divider="@color/black"
        android:dividerHeight="20dp"
        android:background="@null"
        android:listSelector="#880088"
        />


</LinearLayout>

 3. Grid view GridView

 

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="5dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="40dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="拉伸模式:"
            android:textColor="@color/black"
            android:textSize="17sp" />

        <Spinner
            android:id="@+id/sp_stretch"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="left|center"
            android:spinnerMode="dialog" />
    </LinearLayout>

    <GridView
        android:id="@+id/gv_planet"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#00ffff"
        android:horizontalSpacing="3dp"
        android:verticalSpacing="3dp"
        android:numColumns="2"
        android:stretchMode="columnWidth" />

</LinearLayout>
package com.example.chapter05.Adapt;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.example.chapter05.Bean.Planet;
import com.example.chapter05.R;

import java.util.List;

public class PlanetGridAdapter extends BaseAdapter implements AdapterView.OnItemClickListener, AdapterView.OnItemLongClickListener{

    private Context mContext;//上下文对象
    private List<Planet> mPlanetList;//声明行星信息列表

    public PlanetGridAdapter(Context mContext, List<Planet> mPlanetList) {
        this.mContext = mContext;
        this.mPlanetList = mPlanetList;
    }

    @Override
    public int getCount() {
        return mPlanetList.size();
    }

    @Override
    public Object getItem(int i) {
        return mPlanetList.get(i);
    }

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

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        ViewHolder viewHolder;
        if (view==null){
            viewHolder=new ViewHolder();//构建一个视图持有者
            //根据布局文件生成转换视图象
            view= LayoutInflater.from(mContext).inflate(R.layout.item_grid,null);
            viewHolder.iv_icon=view.findViewById(R.id.iv_icon);
            viewHolder.tv_desc=view.findViewById(R.id.tv_desc);
            viewHolder.tv_name=view.findViewById(R.id.tv_name);
            view.setTag(viewHolder);
        }
        else {
            viewHolder= (ViewHolder) view.getTag();
        }
        Planet planet=mPlanetList.get(i);
        viewHolder.iv_icon.setImageResource(planet.image); // 显示行星的图片
        viewHolder.tv_name.setText(planet.name); // 显示行星的名称
        viewHolder.tv_desc.setText(planet.desc); // 显示行星的描述
        return view;
    }



    //定义一个视图持有者
    public final class ViewHolder {
        public ImageView iv_icon; // 声明行星图片的图像视图对象
        public TextView tv_name; // 声明行星名称的文本视图对象
        public TextView tv_desc; // 声明行星描述的文本视图对象
    }

    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
        String desc = String.format("您点击了第%d个行星,它的名字是%s", i + 1,
                mPlanetList.get(i).name);
        Toast.makeText(mContext, desc, Toast.LENGTH_LONG).show();
    }

    @Override
    public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
        String desc = String.format("您长按了第%d个行星,它的名字是%s", i + 1,
                mPlanetList.get(i).name);
        Toast.makeText(mContext, desc, Toast.LENGTH_LONG).show();
        return true;
    }
}
package com.example.chapter05;

import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.GridView;
import android.widget.Spinner;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import com.example.chapter05.Adapt.PlanetGridAdapter;
import com.example.chapter05.Bean.Planet;
import com.example.chapter05.util.Utils;

import java.util.List;

public class GridViewActivity extends AppCompatActivity {
    private GridView gv_planet; // 声明一个网格视图对象
    private Object DivideSelectListener;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_grid_view);
        List<Planet> planetList=Planet.getDefaultList();
        //构建一个行星列表的网格适配器
        PlanetGridAdapter planetGridAdapter=new PlanetGridAdapter(this,planetList);
        //从布局视图中获取名叫gv_planet的网格视图
        gv_planet=findViewById(R.id.gv_planet);
        gv_planet.setAdapter(planetGridAdapter);//设置网格视图的适配器
        gv_planet.setOnItemClickListener(planetGridAdapter);
        gv_planet.setOnItemLongClickListener(planetGridAdapter);
        gv_planet.setOnItemClickListener(planetGridAdapter);
        initDividerSpinner();
    }

    private String[] dividerArray = {
            "不显示分隔线",
            "不拉伸(NO_STRETCH)",
            "拉伸列宽(COLUMN_WIDTH)",
            "列间空隙(STRETCH_SPACING)",
            "左右空隙(SPACING_UNIFORM)",
            "使用padding显示全部分隔线"};

        //初始化拉伸模式的下拉框
        private void initDividerSpinner(){
            ArrayAdapter<String> divideAdapter=new ArrayAdapter<String>(this,R.layout.item_select,dividerArray);
            Spinner sp_stretch=findViewById(R.id.sp_stretch);
            sp_stretch.setPrompt("设置拉伸模式");//设置下拉框标婷
            sp_stretch.setSelection(0);
            sp_stretch.setAdapter(divideAdapter);
            sp_stretch.setOnItemSelectedListener(new DivideSelectListener());
        }

        class  DivideSelectListener implements AdapterView.OnItemSelectedListener{

            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int arg2, long l) {
                int dividerPad = Utils.dip2px(GridViewActivity.this, 2); // 定义间隔宽度为2dp
                gv_planet.setBackgroundColor(Color.CYAN);  // 设置背景颜色
                gv_planet.setHorizontalSpacing(dividerPad);  // 设置列表项在水平方向的间距
                gv_planet.setVerticalSpacing(dividerPad);  // 设置列表项在垂直方向的间距
                gv_planet.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);//是自己拉伸模式
                gv_planet.setColumnWidth(Utils.dip2px(GridViewActivity.this, 120));//设置每列宽度120dp
                gv_planet.setPadding(1,1,1,1);//设置网格视图的四周边距
                if (arg2 == 0) {  // 不显示分隔线
                    gv_planet.setBackgroundColor(Color.WHITE);
                    gv_planet.setHorizontalSpacing(0);
                    gv_planet.setVerticalSpacing(0);
                } else if (arg2 == 1) {  // 不拉伸(NO_STRETCH)
                    gv_planet.setStretchMode(GridView.NO_STRETCH);
                } else if (arg2 == 2) {  // 拉伸列宽(COLUMN_WIDTH)
                    gv_planet.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
                } else if (arg2 == 3) {  // 列间空隙(STRETCH_SPACING)
                    gv_planet.setStretchMode(GridView.STRETCH_SPACING);
                } else if (arg2 == 4) {  // 左右空隙(SPACING_UNIFORM)
                    gv_planet.setStretchMode(GridView.STRETCH_SPACING_UNIFORM);
                } else if (arg2 == 5) {  // 使用padding显示全部分隔线
                    gv_planet.setPadding(dividerPad, dividerPad, dividerPad, dividerPad);
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {

            }
        }
}

 

 

 

 

 

 

Guess you like

Origin blog.csdn.net/weixin_62190821/article/details/127463094
Recommended