ListView组件开发,仿ios系统设置页面

一、前言

利用android的ListView组件开发,类似于苹果手机的“系统设置”页面,达到ListView子项item包含图标,文字说明,以及子项item分组具有突出显示的效果。下文会有效果的展示以及开发流程。

二、效果图

这里写图片描述

三、开发步骤&源代码

3.1、添加ListView控件

首先新建一个ListView项目,并让Android Studio自动帮我们创建好活动,然后修改activity_main.xml的代码,如下所示。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorGray">

    <LinearLayout android:id="@+id/line1"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_marginTop="20dp"
        android:background="@android:color/white">

        <!--并不能够通过添加两个ListView,来达到在一个activity中放置两个ListView的预期效果,
            会导致丧失ListView原有的滚动效果,因为两个ListView相互独立,只有一个ListView会滚动
            而不是两个作为整体滚动。 -->
        <ListView
            android:id="@+id/system_setting_list_view_1"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </LinearLayout>

</RelativeLayout>

外层是相对布局RelativeLayout,并设置背景颜色RGB为#E5E5E5,背景色的RGB值放置在资源文件“app/res/values/colors.xml”中。

内存为线性布局LinearLayout,并设置背景色white, 通过对背景色的设置就达到了突出显示。

值得说明的是在内层的线性布局中,利用android:layout_alignParentTop属性,让内层布局置顶;利用android:layout_marginTop=”20dp”属性,将内层线性布局与标题分隔20dp。

3.2、定义实体类

定义一个实体类SystemSettingItem,作为ListView适配器(adapter)的适配类型。

public class SystemSettingItem {
    private String SystemSettingName;
    private int ImageId;
    // ... 省略了构造函数,以及get,set方法
}

SystemSettingName: 系统设置项的名称,类似于“飞行模式”。
ImageId:系统设置项图标的id, 图标资源文件放置在/app/res/drawable-hdpi目录下
这里写图片描述

这里指的注意的是,我们给png图片起的文件名并不是数字,为什么ImageId为int类型的数据。这是因为我们引用png图片的方式为imageView.setImageResource(R.drawable.flight_mode);“R.drawable.flight_mode”,这是一个由系统自动为我们生成的整型数据。

3.3、ListView子项布局

为ListView子项指定一个我们自定义的布局,在app/res/layout目录下新建一个system_setting_item.xml。

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

    <ImageView
        android:id="@+id/image_id"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_alignParentLeft="true"
        android:layout_margin="10dp"/>

    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/image_id"
        android:layout_centerVertical="true"
        android:layout_marginLeft="10dp"/>

    <ImageView android:id="@+id/enter_id"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_alignParentRight="true"
        android:layout_margin="10dp"/>

</RelativeLayout>

这里之所以采用相对布局的方式,是为了达到让“进入图标”能够在最右边显示的效果,相对于线性布局,相对布局更容易实现。

ImageView - android:layout_alignParentLeft=”true” : 让图标视图处于ListView子项的最左边。

TextView - android:layout_toRightOf=”@id/image_id” : 让文本处于图标的右边

Image-View : android:layout_alignParentRight=”true” : 让“进入”图标处于ListView空间子项的最右边。

3.4、自定义适配器

接下来创建一个自定义适配器SystemSettingAdapter,这个适配器继承自ArrayAdapter,指定泛型为SystemSettingItem。

package com.dmw.adapter;

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 com.dmw.activity.R;
import com.dmw.domain.SystemSettingItem;

import java.util.List;

public class SystemSettingAdapter extends ArrayAdapter<SystemSettingItem> {

    private int resourceId;
    private Context context;

    /**
     * 
     * @param context  :MainActivity.this 活动的上下文
     * @param resource :R.layout.system_setting_item 自定义的ListView子项
     * @param objects  :ssiList 自定义的实体类数组
     */
    public SystemSettingAdapter(@NonNull Context context, int resource, @NonNull List<SystemSettingItem> objects) {
        super(context, resource, objects);
        resourceId = resource;
        this.context = context;
    }

    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        // 获得当前项的实例,position为子项Item在ListView空间中的顺序编号
        SystemSettingItem ssi = getItem(position);
        View view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);

        // 模拟分割,将ListView中的一项item设置背景颜色为gray
        if(ssi.getSystemSettingName().equals("line")){
            // 获取自定义资源文件中的颜色值(int)
            view.setBackgroundColor(context.getResources().getColor(R.color.colorGray));
            return view;
        }

        // 设置列表项内容
        ImageView imageView = (ImageView)view.findViewById(R.id.image_id);
        imageView.setImageResource(ssi.getImageId());

        TextView textView = (TextView)view.findViewById(R.id.name);
        textView.setText(ssi.getSystemSettingName());

        ImageView enterView = (ImageView)view.findViewById(R.id.enter_id);
        enterView.setImageResource(R.drawable.enter);

        return view;
    }
}

为了实现ListView控件子项的分组,曾采用过在一个Activity活动页面添加两个独立的ListView控件的方式,但是由于两个控件相互独立,在页面滑动的过程中,展现的效果不是整体的滑动效果,另人尴尬。

所以这里采用的是,将一个ListView中名为”line”的一个子项,将他的背景色设置为布局的背景色,不添加图标和文字,也不添加点击事件,只作为分割线使用。

3.5、MainActivity

package com.dmw.activity;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

import com.dmw.adapter.SystemSettingAdapter;
import com.dmw.domain.SystemSettingItem;

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

public class MainActivity extends AppCompatActivity {

    private List<SystemSettingItem> ssiList = new ArrayList<>();

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

        // 只是为了展示滚动效果,所以让数量*2
        for(int i = 0;i < 2;i++)
            initSsiList();

        // 借助适配器将数据传递给ListView
        SystemSettingAdapter adapter = new SystemSettingAdapter(MainActivity.this, R.layout.system_setting_item, ssiList);

        ListView listView = findViewById(R.id.system_setting_list_view_1);
        listView.setAdapter(adapter);

        // 设置ListView中子项item的点击事件
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                SystemSettingItem ssi = ssiList.get(position);
                if(!ssi.getSystemSettingName().equals("line"))
                    Toast.makeText(MainActivity.this, ssi.getSystemSettingName(), Toast.LENGTH_SHORT).show();
            }
        });

    }

    /**
     * ListView子项item数据初始化
     */
    private void initSsiList(){
        SystemSettingItem flightMode = new SystemSettingItem("飞行模式", R.drawable.flight_mode);
        ssiList.add(flightMode);

        SystemSettingItem wlan = new SystemSettingItem("无线局域网", R.drawable.wlan);
        ssiList.add(wlan);

        SystemSettingItem blueTooth = new SystemSettingItem("蓝牙", R.drawable.blue_tooth);
        ssiList.add(blueTooth);

        SystemSettingItem cellular = new SystemSettingItem("蜂窝移动网络", R.drawable.cellular);
        ssiList.add(cellular);

        SystemSettingItem hotspot = new SystemSettingItem("个人热点", R.drawable.hotspot);
        ssiList.add(hotspot);

        SystemSettingItem operator = new SystemSettingItem("运营商", R.drawable.operator);
        ssiList.add(operator);

        ssiList.add(new SystemSettingItem("line", 0));

        SystemSettingItem inform = new SystemSettingItem("通知", R.drawable.inform);
        ssiList.add(inform);

        SystemSettingItem console = new SystemSettingItem("控制中心", R.drawable.console);
        ssiList.add(console);

        SystemSettingItem moon = new SystemSettingItem("勿扰模式", R.drawable.moon);
        ssiList.add(moon);

        ssiList.add(new SystemSettingItem("line", 0));

    }
}

猜你喜欢

转载自blog.csdn.net/dmw2016/article/details/79937514
今日推荐