Android列表用法之一:实战简单ListView

ListView这个列表控件,是我们在开发当中使用频率比较高的一个控件。
既然是使用频率比较高,那么我们就有必要将它的使用方式保存,方便以后直接复制粘贴,把注意力放在架构上面,不用经常做代码搬运工(重复搬运)。

当然Android的API也提供了许多创建ListView适配器的快捷方式。例如ArrayAdapter、SimpleAdapter、SimpleCursorAdapter等。但是在日常的开发当中,我是从来不会使用系统自带的适配器。毕竟一个项目当中,大部分列表Item的高度、容纳的控件数量、控件类型、逻辑处理、事件的处理等等都是不同的,使用系统自带的完全不能胜任。

套用一句俚语:一切不以实际项目为例子的Sample都是耍*流*氓^_^

今天的简单实例为百度地图-收藏夹页面的收藏点列表的仿写(只是列表哟),下面我们先来看看原装正品效果图动画:
百度地图原版GIF

怎么样,够简单吧,不过虽然简单,却不能使用系统提供给我们的适配器来做,我们来自定义适配器
一、纵观全局—-我们先来分析一下页面有哪些元素
1、一个列表(费话,我们就是来做列表的!^_^)。
2、一个餐厅名称、一个收藏时间、一个右箭头。
3、一条分隔线(这一个千万忘不得)。
4、点击Item会有交互颜色变化。

二、技术选型
1、这一步是不可少的哈,因为实现列表,我们有多种方式,ListView可以,RecyclerView也可以,当然硬布局+ScrollView也可以(这一个估计没人这么做)等等。这里,我们使用ListView。没什么原因,就因为今天是ListView的实例。^_^
2、名称和时间肯定使用TextView了。右箭头使用ImageView,由于这个箭头只是一个标识作用,没有集成事件之类的,所以不会选择ImageButton、Button等控件。
3、分隔线,这个就有讲究了。我们仔细观察,这个分隔线是从左到右,横跨整个列表的。实现它的方法,至少有两种:(1)使用Listview自带的divder. (2)写一个View到Item布局当中。
如果这个分隔线不是横跨整个列表,而是有左边距或右边距呢,比如分隔线是和文字以及时间控件左对齐的呢,我们就只能写到Item布局当中了。
4、选择使用Selector。

三、码代码
1、构造数据,模拟好像是在线获取的数据,这里我们封闭一个数据获取的方法即可,所有的数据增删查改等都在此方法内进行。

    /**
     * 数据封装,模拟从网络上获取到的数据
     *
     * @return 返回数据列表
     */
    private List<RestaurantBean> getDatasFromNetwork() {
        for (int i = 0; i < Constants.PLACE.length; i++) {
            RestaurantBean restaurant = new RestaurantBean();
            restaurant.setPlace(Constants.PLACE[i]);
            restaurant.setTime(Constants.TIME[i]);
            datas.add(restaurant);
        }
        //刷新列表,如果是真实的网络数据,则放到请求回调函数当中使用。
        //注意如果是在异步线程中,应该怎么使用?它必须在主线程中执行!!
        listViewSimpleAdapter.notifyDataSetChanged();
        return datas;
    }

以下附方法内使用到的常量:

package oliver.zhantao.oliverproject.constants;

/**
 * 存放常量类
 *
 * Created by ZhanTao on 2017/4/17.
 */

public class Constants {

    //地点列表
    public static final String PLACE[] = {
        "德克士(新世幻环球中心店)", "肯德基(九方餐厅)", "第18区海鲜拼盘", "邓家面馆",
            "锦水缘餐厅", "麦地里(中海店)", "可可豆汤", "临江门火锅店",
            "若水河鲜", "自贡鸿鹤鲜锅兔", "又见曾毛肚老火锅"
    };

    //时间列表
    public static final String TIME[] = {
            "2017-04-08" , "2017-04-09", "2017-04-10", "2017-04-11",
            "2017-04-12", "2017-04-13", "2017-04-14" , "2017-04-15",
            "2017-04-16", "2017-04-17", "2017-04-18"
    };
}

以下附方法内使用到的实体类:

package oliver.zhantao.oliverproject.listview;

import java.io.Serializable;

/**
 * 用于存放保存餐厅的地点和时间的实体类。
 *
 * Created by ZhanTao on 2017/4/17.
 */

public class RestaurantBean implements Serializable {
    //地点字段
    private String place;
    //收藏时间字段
    private String time;

    public String getPlace() {
        return place;
    }

    public void setPlace(String place) {
        this.place = place;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }
}

2、构建一个ListViewSimpleActivity

package oliver.zhantao.oliverproject.listview;

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

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

import oliver.zhantao.oliverproject.R;
import oliver.zhantao.oliverproject.constants.Constants;

/**
 * 实战项目中简单的列表实现,自定义适配器。
 * 仿写百度地图当中,收藏夹里面,收藏点的列表实现。
 * 一切脱离实战的实例,都是耍流氓。
 * <p>
 * Created by ZhanTao on 2017/4/14.
 */

public class ListViewSimpleActivity extends AppCompatActivity {
    private ListView listViewSimple;
    private ListViewSimpleAdapter listViewSimpleAdapter;
    private List<RestaurantBean> datas = null;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_listview_simple);
        datas = new ArrayList<>();
        //1、找到布局当中的列表控件
        listViewSimple = (ListView) findViewById(R.id.listViewSimple);
        //2、创建适配器对象, 上下文必须传(非常有用)、数据必须传
        listViewSimpleAdapter = new ListViewSimpleAdapter(ListViewSimpleActivity.this, datas);
        //3、将适配器与listview进行绑定
        listViewSimple.setAdapter(listViewSimpleAdapter);
        //4、构造数据、刷新列表
        getDatasFromNetwork();
    }
}

3、建立activity的布局文件activity_listview_simple
有人可能会疑惑:ConstraintLayout这个是什么布局。你可以将它改为RelativeLayout或LinearLayout,这个布局我会在以后的文章中介绍到。

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
    tools:context="oliver.zhantao.oliverproject.listview.ListViewSimpleActivity">

    <ListView
        android:id="@+id/listViewSimple"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:listSelector="@drawable/listviewsimple_bg_selector"
        android:divider="@color/transparent_20"
        android:dividerHeight="@dimen/px_1"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

以上布局文件要注意几个要点:
(1)分隔线的粗细:dividerHeight
(2)分隔线的颜色:divider
(3)点击Item后交互变化:listSelector

以下来制作:listviewsimple_bg_selector
颜色值就自己定义:以下color_221E90FF名字当中,221E90FF就是颜色值。

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

    <item android:drawable="@color/color_221E90FF" android:state_pressed="true" />
    <item android:drawable="@color/transparent" />

</selector>

4、自定义Adapter,按照顺序,得先把优化框架搭上,这个是不能少的。然后再是填数据,附加事件

扫描二维码关注公众号,回复: 4037313 查看本文章
package oliver.zhantao.oliverproject.listview;

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

import java.util.List;

import oliver.zhantao.oliverproject.R;

/**
 * 餐厅列表适配器,在这里将数据与控件进行绑定
 * <p>
 * 项目中都是自定义适配器,很少用到系统提供的简易适配器。
 * 所以果断抛弃系统的简易适配器,自定义想咋样就咋样,一个字,爽^_^
 * <p>
 * Created by ZhanTao on 2017/4/17.
 */

public class ListViewSimpleAdapter extends BaseAdapter {
    private Context mContext;
    //餐厅列表
    private List<RestaurantBean> restaurantList;
    private LayoutInflater mInflater;

    public ListViewSimpleAdapter(Context context, List<RestaurantBean> restaurantList) {
        this.mContext = context;
        this.restaurantList = restaurantList;
        mInflater = LayoutInflater.from(context);
    }

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

    @Override
    public Object getItem(int position) {
        return position;
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        //1、优化框架搭起
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.activity_listview_simple_item, null);
            holder = new ViewHolder();
            holder.place = (TextView) convertView.findViewById(R.id.resturant_place);
            holder.time = (TextView) convertView.findViewById(R.id.resturant_time);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        //2、绑定数据到控件
        bindViewData(position, convertView, holder);
        //3、绑定监听事件
        bindViewClickListener(position, convertView, holder);

        return convertView;
    }

    class ViewHolder {
        private TextView place;
        private TextView time;
    }

    /**
     * 绑定数据到控件,在这里做统一处理,方便数据抽离
     *
     * @param position    列表索引
     * @param convertView 每个position对应的itemView
     * @param holder      holder对象
     */
    private void bindViewData(int position, View convertView, ViewHolder holder) {
        holder.place.setText(restaurantList.get(position).getPlace());
        holder.time.setText("时间:" + restaurantList.get(position).getTime());
    }

    /**
     * 绑定控件的各种View的事件,在这里做统一处理,比如点击事件,长安事件。
     *
     * @param position    列表索引
     * @param convertView 每个position对应的itemView
     * @param holder      holder对象
     */
    private void bindViewClickListener(int position, View convertView, ViewHolder holder) {

    }
}

5、编写Item布局文件activity_listview_simple_item
资源icon_right_arrow,大家都自己去各种app当中扒。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/dp_10"
    android:paddingTop="@dimen/dp_10">

    <ImageView
        android:id="@+id/img_right_arrow"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_marginLeft="@dimen/dp_16"
        android:layout_marginRight="@dimen/dp_16"
        android:src="@drawable/icon_right_arrow" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_marginLeft="@dimen/dp_16"
        android:layout_toLeftOf="@id/img_right_arrow"
        android:orientation="vertical">

        <TextView
            android:id="@+id/resturant_place"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textColor="@color/color_AA000000"
            android:textSize="@dimen/dp_14" />

        <TextView
            android:id="@+id/resturant_time"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/dp_5"
            android:textSize="@dimen/dp_12" />
    </LinearLayout>
</RelativeLayout>

下面我们来看看代码运行后的效果图:
简单ListView实战
以上,完了。代码贴完就完了。如有问题或好的建议希望大家留言,感激。

作者:Amir
博客:http://blog.csdn.NET/amir_zt/
以上原创,转载请注明出处,谢谢。
http://blog.csdn.net/amir_zt/article/details/70240519

猜你喜欢

转载自blog.csdn.net/u011635351/article/details/70240519
今日推荐