A020-列表容器之ListView

概述

前面介绍了Android UI中的五大布局容器,本节课介绍实际项目当中经常会用到的组件-ListView,它也是一个布局容器,它的每一项就是我们的列表项,每一个列表项都是一块独立的布局,我们可把数据填充到每一个列表项中,这样来完成数据的展示。

案例

ListView
ListView

上面的效果图就是我们在app中常见的列表,这里只是简单的示例,更加复杂的ListView项效果根据产品需求来做。

常见的功能需求有:

  • 根据视觉稿搭建列表项UI
  • 设置列表点击效果-selector
  • 设置列表之间的间隔-dividerHeight
  • 设置列表的分割线-divider
  • 异步加载图片
  • 下拉刷新最新列表数据
  • 滑动到底部加载更多数据
  • 点击列表项进行跳转
    更多...

实现过程

First Step:UI布局

layout/activity_listview.xml

<?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">

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:cacheColorHint="#00000000"
        android:dividerHeight="15dp"
        android:fadingEdge="none"
        android:scrollbars="none"
        android:fadeScrollbars="true"
        android:transcriptMode="alwaysScroll"
        />
</RelativeLayout>

layout/layout_list_item.xml

<?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"
    >

    <ImageView
        android:id="@+id/iv_head"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_margin="10dp"
        android:src="@drawable/pic_6"
        />

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/iv_head"
        android:layout_alignTop="@+id/iv_head"
        android:textSize="16sp"
        android:text="凤姐"/>

    <TextView
        android:id="@+id/tv_desc"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/iv_head"
        android:layout_below="@+id/tv_name"
        android:layout_marginTop="10dp"
        android:textSize="14sp"
        android:text="你才是一个没有故事的女同学"/>


</RelativeLayout>

常用属性说明:
android:cacheColorHint="#00000000" //设置拖动背景色为透明

android:dividerHeight="30px" //listview item之间的高度

android:divider="@drawable/ic_launcher" //listview item之间的背景或者说是颜色

android:fadingEdge="vertical" //上边和下边有黑色的阴影 值为none的话就没有阴影

android:scrollbars="horizontal|none" //只有值为horizontal|vertical的时候,才会显示滚动条,并且会自动影藏和显示

android:fastScrollEnabled="true" //快速滚动效果,配置这个属性,在快速滚动的时候旁边会出现一个小方块的快速滚动效果,自动隐藏和显示,

android:scrollbarStyle="outsideInset" //四个值的含义如下

1>outsideInset : 该ScrollBar显示在视图(view)的边缘,增加了view的padding. 如果可能的话,该ScrollBar仅仅覆盖这个view的背景.

2>outsideOverlay : 该ScrollBar显示在视图(view)的边缘,不增加view的padding,该ScrollBar将被半透明覆盖

3>insideInset :该ScrollBar显示在padding区域里面,增加了控件的padding区域,该ScrollBar不会和视图的内容重叠.

4>insideOverlay : 该ScrollBar显示在内容区域里面,不会增加了控件的padding区域,该ScrollBar以半透明的样式覆盖在视图(view)的内容上.

首先是stackFromBottom属性,这只该属性之后你做好的列表就会显示你列表的最下面,值为true和false

android:stackFromBottom="true"

第二是 transciptMode属性,需要用ListView或者其它显示大量Items的控件实时跟踪或者查看信息,并且希望最新的条目可以自动滚动到可视范围内。通过设置的控件transcriptMode属性可以将Android平台的控件(支持ScrollBar)自动滑动到最底部。 android:transcriptMode="alwaysScroll"

第三cacheColorHint属性,很多人希望能够改变一下它的背景,使他能够符合整体的UI设计,改变背景背很简单只需要准备一张图片然后指定属性 android:background="@drawable/bg",不过不要高兴地太早,当你这么做以后,发现背景是变了,但是当你拖动,或者点击list空白位置的时候发现ListItem都变成黑色的了,破坏了整体效果。

如果你只是换背景的颜色的话,可以直接指定android:cacheColorHint为你所要的颜色,如果你是用图片做背景的话,那也只要将android:cacheColorHint指定为透明(#00000000)就可以了

第四divider属性,该属性作用是每一项之间需要设置一个图片做为间隔,或是去掉item之间的分割线

android:divider="@drawable/list_driver" 其中 @drawable/list_driver 是一个图片资源,如果不想显示分割线则只要设置为android:divider="@drawable/@null" 就可以了

第五fadingEdge属性,上边和下边有黑色的阴影

android:fadingEdge="none" 设置后没有阴影了~

第六scrollbars属性,作用是隐藏listView的滚动条,

android:scrollbars="none"与setVerticalScrollBarEnabled(true);的效果是一样的,不活动的时候隐藏,活动的时候也隐藏

第七fadeScrollbars属性,android:fadeScrollbars="true" 配置ListView布局的时候,设置这个属性为true就可以实现滚动条的自动隐藏和显示。

Second Step:更加数据结构创建实体类

package com.devilwwj.androiddevelopcourse.domain;

/**
 * Created by devilwwj on 15/10/7.
 */
public class User {

    private String imageUrl;
    private String name;
    private String description;

    public String getImageUrl() {
        return imageUrl;
    }

    public void setImageUrl(String imageUrl) {
        this.imageUrl = imageUrl;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }


    @Override
    public String toString() {
        return "User{" +
                "imageUrl='" + imageUrl + '\'' +
                ", name='" + name + '\'' +
                ", description='" + description + '\'' +
                '}';
    }
}


Third Step:Activity展示

package com.devilwwj.androiddevelopcourse.activities;

import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import com.devilwwj.androiddevelopcourse.R;
import com.devilwwj.androiddevelopcourse.domain.User;

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

/**
 * A020-列表容器之ListView
 * @author devilwwj
 */
public class ListViewTestActivity extends ActionBarActivity implements OnItemClickListener{
    private ListView mListView;
    private ListViewAdapter mAdapter;
    private Context mContext;
    private List<User> userList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_listview);
        mContext = ListViewTestActivity.this;

        mListView = (ListView) this.findViewById(R.id.listView);


        /* 模拟数据 */
        userList = new ArrayList<User>();

        for (int i = 0; i < 20; i++) {
            User user = new User();
            user.setImageUrl("http://tp1.sinaimg.cn/2463074124/180/40037127109/1");
            user.setName("小巫" + i);
            user.setDescription("小巫不用说都应该知道是谁的啦!!!");
            userList.add(user);
        }

        mListView.setAdapter(new ListViewAdapter(this, userList));

    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        // TODO: 点击列表跳转到其他页面

    }


    private class ListViewAdapter extends BaseAdapter {

        private List<User> users;

        public ListViewAdapter(Context context, List<User> users) {
            this.users = users;
        }

        @Override
        public int getCount() {
            return users != null ? users.size() : 0;
        }

        @Override
        public User getItem(int position) {
            return users.get(position);
        }

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

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder viewHolder = null;


            if (convertView == null) {
                convertView = LayoutInflater.from(mContext).inflate(R.layout.layout_list_item, parent, false);
                viewHolder = new ViewHolder();
                viewHolder.itemHead = (ImageView) convertView.findViewById(R.id.iv_head);
                viewHolder.itemName = (TextView) convertView.findViewById(R.id.tv_name);
                viewHolder.itemDesc = (TextView) convertView.findViewById(R.id.tv_desc);


                convertView.setTag(viewHolder);

            } else {
                viewHolder = (ViewHolder) convertView.getTag();
            }

            User user = getItem(position);
            if (user != null) {
                // 这里只是模拟,实际开发可能需要加载网络图片,可以使用ImageLoader这样的图片加载框架来异步加载图片
                viewHolder.itemHead.setImageResource(R.drawable.pic_6);
                viewHolder.itemName.setText(user.getName());
                viewHolder.itemDesc.setText(user.getDescription());

            }

            return convertView;
        }


        class ViewHolder {
            ImageView itemHead;
            TextView itemName;
            TextView itemDesc;
        }
    }
}

这一步给大家展示了Adapter的标准写法,对item进行复用,通过获取到ListView控件对象,然后初始化数据,再调用setAdapter方法设置数据适配器。

最后

关于ListView的用法基本上就是这样了,实际开发中,单纯使用系统提供的ListView控件是满足不了我们的需求的,因为大部分界面都可能没那么简单,比如需要下拉刷新、加载更多这样的效果,这时我们可以使用优秀的开源控件来实现这样的效果,比如PullToRefresh开源库。ListView的使用是每位Android开发者必须掌握的知识点,它还涉及到很多关于数据展示,性能优化的点,这个随着大家深入学习和实践会了解到,这节课就讲这么多。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,719评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,337评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,887评论 0 324
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,488评论 1 266
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,313评论 4 357
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,284评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,672评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,346评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,644评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,700评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,457评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,316评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,706评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,261评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,648评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,859评论 2 335

推荐阅读更多精彩内容