您的位置:首页 > 移动开发 > Android开发

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

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

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

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


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



怎么样,够简单吧,不过虽然简单,却不能使用系统提供给我们的适配器来做,我们来自定义适配器

一、纵观全局—-我们先来分析一下页面有哪些元素

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
4000
.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,按照顺序,得先把优化框架搭上,这个是不能少的。然后再是填数据,附加事件

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>


下面我们来看看代码运行后的效果图:



以上,完了。代码贴完就完了。如有问题或好的建议希望大家留言,感激。

作者:Amir

博客:http://blog.csdn.NET/amir_zt/

以上原创,转载请注明出处,谢谢。

http://blog.csdn.net/amir_zt/article/details/70240519
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息