安卓基础之《(20)—高级控件(2)列表类视图》

一、列表视图ListView

1、ListView允许在页面上分行展示数据列表,例如新闻列表、商品列表等,方便用户浏览与操作

2、ListView去掉分隔线

设置属性:

android:divider="@null"

android:dividerHeight="0dp"

3、ListView去掉点击的动画效果

设置属性:

android:listSelector="#00000000"

4、例子

ListViewActivity.java

java 复制代码
package com.example.chapter08;

import androidx.appcompat.app.AppCompatActivity;

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 com.example.chapter08.adapter.PlanetBaseAdapter;
import com.example.chapter08.bean.Planet;
import com.example.chapter08.util.ImageUtil;
import com.example.chapter08.util.ToastUtil;

import java.util.List;

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

    private List<Planet> planetList;
    private CheckBox ck_divider;
    private CheckBox ck_selector;
    private ListView lv_planet;

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

        lv_planet = findViewById(R.id.lv_planet);
        planetList = Planet.getDefaultList();
        PlanetBaseAdapter adapter = new PlanetBaseAdapter(this, planetList);
        lv_planet.setAdapter(adapter);

        lv_planet.setOnItemClickListener(this);

        ck_divider = findViewById(R.id.ck_divider);
        ck_selector = findViewById(R.id.ck_selector);
        ck_divider.setOnCheckedChangeListener(this);
        ck_selector.setOnCheckedChangeListener(this);
    }

    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
        ToastUtil.show(this, "您选择的是:" + planetList.get(position).getName());
    }

    @Override
    public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
        if (compoundButton.getId() == R.id.ck_divider) {
            // 显示分隔线
            if (ck_divider.isChecked()) {
                Drawable drawable = getResources().getDrawable(R.color.black, getTheme());
                lv_planet.setDivider(drawable);
                // 设置分隔线的高度
                lv_planet.setDividerHeight(ImageUtil.dip2px(this, 1));
            } else {
                lv_planet.setDivider(null);
                lv_planet.setDividerHeight(0);
            }

        } else if (compoundButton.getId() == R.id.ck_selector) {
            if (ck_selector.isChecked()) {
                // 显示按压背景
                lv_planet.setSelector(R.drawable.list_selector); // 设置选择器
            } else {
                Drawable drawable = getResources().getDrawable(R.color.transparent, getTheme());
                lv_planet.setSelector(drawable);
            }

        }
    }
}

布局文件activity_list_view.xml

java 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".ListViewActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:orientation="horizontal">
    
        <CheckBox
            android:id="@+id/ck_divider"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="start|center"
            android:text="显示分隔线"
            android:textSize="17sp"/>

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

    </LinearLayout>
    
    <ListView
        android:id="@+id/lv_planet"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:divider="@null"
        android:dividerHeight="0dp"
        android:listSelector="@color/transparent"
        />

</LinearLayout>

适配器PlanetBaseAdapter.java

java 复制代码
package com.example.chapter08.adapter;

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

import com.example.chapter08.R;
import com.example.chapter08.bean.Planet;

import java.util.List;

public class PlanetBaseAdapter extends BaseAdapter {

    private Context mContext;
    private List<Planet> mPlanetList;

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

    // 获取列表项的个数
    @Override
    public int getCount() {
        return mPlanetList.size();
    }

    // 获取第i个条目
    @Override
    public Object getItem(int i) {
        return mPlanetList.get(i);
    }

    // 获取item的id,没有id则返回下标
    @Override
    public long getItemId(int i) {
        return i;
    }

    // 获取列表条目的View对象,这样才能显示出来
    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        ViewHolder holder;

        if (view == null) {
            // 根据布局文件item_list.xml生成转换视图对象
            // 布局加载器
            view = LayoutInflater.from(mContext).inflate(R.layout.item_list, null);
            holder = new ViewHolder();
            holder.iv_icon = view.findViewById(R.id.iv_icon);
            holder.tv_name = view.findViewById(R.id.tv_name);
            holder.tv_desc = view.findViewById(R.id.tv_desc);
            // 把holder绑定到View上
            view.setTag(holder); // 将视图持有者保存到转换视图当中
        } else {
            holder = (ViewHolder) view.getTag();
        }

        // 给控件设置好数据
        Planet planet = mPlanetList.get(i);
        holder.iv_icon.setImageResource(planet.getImage());
        holder.tv_name.setText(planet.getName());
        holder.tv_desc.setText(planet.getDesc());
        return view;
    }

    // 把控件打包,放入convertView中
    public final class ViewHolder {
        public ImageView iv_icon;
        public TextView tv_name;
        public TextView tv_desc;

    }
}

条目文件item_list.xml

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:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

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

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

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

        <!-- 显示行星描述的文本视图 -->
        <TextView
            android:id="@+id/tv_desc"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="2"
            android:gravity="start|center"
            android:textColor="@color/black"
            android:textSize="13sp"
            tools:text="水星是太阳系八大行星之一"/>
    </LinearLayout>

</LinearLayout>

选择器list_selector.xml

XML 复制代码
<?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/orange"/>
    <item android:drawable="@color/white"/>
</selector>

颜色资源colors.xml

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="black">#FF000000</color>
    <color name="white">#FFFFFFFF</color>
    <color name="orange">#FFFFDD</color>
    <color name="transparent">#00000000</color>
</resources>

二、Android事件传递机制

1、如果在ListView的条目里有个按钮,此时点击条目会没有反应

一般来说事件会向下传递

2、在条目的xml文件中设置android:descendantFocusability="blocksDescendants"

blocksDescendants可阻止下级控件获得焦点,避免堵塞列表视图的点击事件

或者在代码中也可以设置

3、例子

ListFocusActivity.java

java 复制代码
package com.example.chapter08;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;

import com.example.chapter08.adapter.PlanetListWithButtonAdapter;
import com.example.chapter08.bean.Planet;
import com.example.chapter08.util.ToastUtil;

import java.util.List;

public class ListFocusActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {

    private List<Planet> planetList;
    private ListView lv_planet;

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

        lv_planet = findViewById(R.id.lv_planet);
        planetList = Planet.getDefaultList();
        PlanetListWithButtonAdapter adapter = new PlanetListWithButtonAdapter(this, planetList);
        lv_planet.setAdapter(adapter);

        lv_planet.setOnItemClickListener(this);

    }

    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
        ToastUtil.show(this, "条目被点击了:" + planetList.get(position).getName());
    }
}

布局文件activity_list_focus.xml

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".ListFocusActivity">

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

</LinearLayout>

适配器PlanetListWithButtonAdapter.java

java 复制代码
package com.example.chapter08.adapter;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.example.chapter08.R;
import com.example.chapter08.bean.Planet;
import com.example.chapter08.util.ToastUtil;

import java.util.List;

public class PlanetListWithButtonAdapter extends BaseAdapter {

    private Context mContext;
    private List<Planet> mPlanetList;

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

    // 获取列表项的个数
    @Override
    public int getCount() {
        return mPlanetList.size();
    }

    // 获取第i个条目
    @Override
    public Object getItem(int i) {
        return mPlanetList.get(i);
    }

    // 获取item的id,没有id则返回下标
    @Override
    public long getItemId(int i) {
        return i;
    }

    // 获取列表条目的View对象,这样才能显示出来
    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        ViewHolder holder;

        if (view == null) {
            // 根据布局文件item_list.xml生成转换视图对象
            // 布局加载器
            view = LayoutInflater.from(mContext).inflate(R.layout.item_list_with_button, null);
            holder = new ViewHolder();
            holder.ll_item = view.findViewById(R.id.ll_item);
            holder.iv_icon = view.findViewById(R.id.iv_icon);
            holder.tv_name = view.findViewById(R.id.tv_name);
            holder.tv_desc = view.findViewById(R.id.tv_desc);
            holder.btn_oper = view.findViewById(R.id.btn_oper);
            // 把holder绑定到View上
            view.setTag(holder); // 将视图持有者保存到转换视图当中
        } else {
            holder = (ViewHolder) view.getTag();
        }

        // 给控件设置好数据
        Planet planet = mPlanetList.get(i);
        holder.ll_item.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
        holder.iv_icon.setImageResource(planet.getImage());
        holder.tv_name.setText(planet.getName());
        holder.tv_desc.setText(planet.getDesc());
        holder.btn_oper.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ToastUtil.show(mContext, "按钮被点击了:" + planet.getName());
            }
        });
        return view;
    }

    // 把控件打包,放入convertView中
    public final class ViewHolder {
        public LinearLayout ll_item;
        public ImageView iv_icon;
        public TextView tv_name;
        public TextView tv_desc;
        public Button btn_oper;

    }
}

条目文件item_list_with_button.xml

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:id="@+id/ll_item"
    android:orientation="horizontal"
    android:descendantFocusability="blocksDescendants"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

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

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

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

        <!-- 显示行星描述的文本视图 -->
        <TextView
            android:id="@+id/tv_desc"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="2"
            android:gravity="start|center"
            android:textColor="@color/black"
            android:textSize="13sp"
            tools:text="水星是太阳系八大行星之一"/>
    </LinearLayout>

    <Button
        android:id="@+id/btn_oper"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:text="点我"
        android:gravity="center"/>

</LinearLayout>
相关推荐
JMchen1232 小时前
Android计算摄影实战:多帧合成、HDR+与夜景算法深度剖析
android·经验分享·数码相机·算法·移动开发·android-studio
恋猫de小郭3 小时前
Flutter 在 Android 出现随机字体裁剪?其实是图层合并时的边界计算问题
android·flutter·ios
2501_915918414 小时前
把 iOS 性能监控融入日常开发与测试流程的做法
android·ios·小程序·https·uni-app·iphone·webview
benjiangliu5 小时前
LINUX系统-09-程序地址空间
android·java·linux
独自破碎E5 小时前
字符串相乘
android·java·jvm
DokiDoki之父5 小时前
边写软件边学kotlin(一):Kotlin语法初认识:
android·开发语言·kotlin
REDcker5 小时前
Telegram Android 源码解析完整文档
android
Big Cole6 小时前
PHP面试题(核心基础篇:垃圾回收+自动加载)
android·开发语言·php
雪球Snowball6 小时前
【Android关键流程】WMS的创建
android