ListView是Android中最重要的组件之一,几乎每个Android应用中都会使用ListView。它以垂直列表的方式列出所需的列表项。
(1)将数据填充到布局; 
(2)处理用户的选择点击等操作。
(1)ListVeiw:用来展示列表的View; 
(2)适配器: 用来把数据映射到ListView上的中介; 
(3)数据源: 具体的将被映射的字符串,图片,或者基本组件。
适配器是一个连接数据和AdapterView的桥梁,通过它能有效地实现数据与AdapterView的分离设置,使AdapterView与数据的绑定更加简便,修改更加方便。
  Android开发中的适配器一共可分为: 
  ArrayAdapter, 
  BaseAdapter,  
  CursorAdapter, 
  HeaderViewListAdapter,  
  ResourceCursorAdapter, 
  SimpleAdapter, 
  SimpleCursorAdapter, 
  WrapperListAdapter 
  其中,ArrayAdapter和SimpleAdapter最为常见。
ArrayAdapter最为简单,只能展示一行字;
SimpleAdapter有最好的扩充性,可以自定义各种各样的布局,除了文本外,还可以放ImageView(图片)、Button(按钮)、CheckBox(复选框)等等;
但是实际工作中,常用自定义适配器。即继承于BaseAdapter的自定义适配器类。
  android:divider 
  android:dividerHeight
先看下面代码:
package com.danny_jiang.day08_listview_introduce;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 1 初始化ListView
        ListView listView = (ListView) findViewById(R.id.list_Main);
        // 2 初始化数据源
        String[] data = getResources().getStringArray(R.array.arr);
        // 3 初始化适配器
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, data);
        // 4 将适配器设置到ListView控件中
        listView.setAdapter(adapter);
        // 设置ListView的单击事件
        listView.setOnItemClickListener(new OnItemClickListener() {
            /**
             * @param parent
             *            ListView
             * @param view
             *            所点击的item视图,也就是TextView
             * @param position
             *            所点击item的位置
             * @param id
             *            所点击item的id
             */
            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {
                if (view instanceof TextView) {
                    TextView textView = (TextView) view;
                    String content = textView.getText().toString();
                    Toast.makeText(MainActivity.this, "点击了 " + content,
                            Toast.LENGTH_SHORT).show();
                }
            }
        });
        // 设置ListView的长按事件
        listView.setOnItemLongClickListener(new OnItemLongClickListener() {
            /**
             * @param parent
             *            ListView
             * @param view
             *            所点击的item视图,也就是TextView
             * @param position
             *            所点击item的位置
             * @param id
             *            所点击item的id
             */
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view,
                    int position, long id) {
                if (view instanceof TextView) {
                    TextView textView = (TextView) view;
                    String content = textView.getText().toString();
                    Toast.makeText(MainActivity.this, "长按了 " + content,
                            Toast.LENGTH_SHORT).show();
                }
                // 返回true,表示将单击事件进行拦截
                return true;
            }
        });
    }
}
布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="${relativePackage}.${activityClass}" >
    <!--
        通过ListView标签可以声明列表视图
        android:divider="#FF0000"   设置ListView间隙之间的颜色,必须指定dividerHeight后才会生效
        android:dividerHeight="2dp"     设置ListView间隙之间的间隔
    -->
    <ListView
        android:id="@+id/list_Main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:divider="#FF0000"
        android:dividerHeight="2dp" >
    </ListView>
</RelativeLayout>
strings.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">Day08_ListView_Introduce</string>
    <string name="hello_world">Hello world!</string>
    <string-array name="arr">
        <item>西游记</item>
        <item>红楼梦</item>
        <item>李尔王</item>
        <item>麦克白</item>
        <item>西游记</item>
        <item>红楼梦</item>
        <item>李尔王</item>
        <item>麦克白</item>
        <item>西游记</item>
        <item>红楼梦</item>
        <item>李尔王</item>
        <item>麦克白</item>
        <item>西游记</item>
        <item>红楼梦</item>
        <item>李尔王</item>
        <item>麦克白</item>
    </string-array>
</resources>
效果图如下: 
2.1 使用系统自带item布局 
先看下面代码:
package com.danny_jiang.day08_listview_simpleadapter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;
import android.widget.SimpleAdapter;
public class MainActivity extends Activity {
    private ListView listView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 初始化ListView控件
        listView = (ListView) findViewById(R.id.list_Main);
        // 初始化数据源
        List<Map<String, String>> list = new ArrayList<Map<String, String>>();
        for (int i = 0; i < 10; i++) {
            Map<String, String> map = new HashMap<String, String>();
            map.put("name", "Android-" + i);
            map.put("age", "age-" + i);
            map.put("gender", "male");
            list.add(map);
        }
        // 初始化item的布局文件(使用系统自带布局)
        int itemLayout = android.R.layout.simple_list_item_2;
        /**
         * 初始化SimpleAdapter适配器
         * 
         * @param this 
         *                上下文
         * @param list
         *            数据源 List<Map>
         * @param itemLayout
         *            item的布局文件ID,使用此item来显示ListVirw中的每一个item
         * @param new String[] { "gender", "age" }
         *            是一系列String,key的数组,key是Map中put时所使用的key值
         * @param new int[] { android.R.id.text1, android.R.id.text2 } 
         *            一些列id的int数组,id的顺序决定了数据源中item的摆放顺序
         *        
         */
        SimpleAdapter adapter = new SimpleAdapter(this, list, itemLayout,
                new String[] { "gender", "age" },
                new int[] { android.R.id.text1, android.R.id.text2 });
        // ListView设置适配器
        listView.setAdapter(adapter);
    }
}
布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="${relativePackage}.${activityClass}" >
    <ListView
        android:id="@+id/list_Main"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </ListView>
</RelativeLayout>
效果图如下: 
2.2 自定义item布局文件
代码如下:
package com.danny_jiang.day08_listview_iconitem;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;
import android.widget.SimpleAdapter;
public class MainActivity extends Activity {
    private ListView listView;
    // 声明需要显示到ListView上的图片资源ID
    private int[] iconId = new int[] { R.drawable.tv01, R.drawable.tv02,
            R.drawable.tv03, R.drawable.tv04, R.drawable.tv05,
            R.drawable.tv06, R.drawable.tv07, R.drawable.tv08, 
            R.drawable.tv09, R.drawable.tv10, R.drawable.tv01,};
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 初始化ListView控件
        listView = (ListView) findViewById(R.id.list_main);
        // 初始化数据源
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        for (int i = 0; i < iconId.length; i++) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("name", "Android-" + i);
            map.put("icon", iconId[i]);
            list.add(map);
        }
        // 初始化item布局
        int itemLayout = R.layout.list_item;
        // 初始化适配器SimpleAdapter
        SimpleAdapter adapter = new SimpleAdapter(this, list, itemLayout,
                new String[] { "icon", "name" }, new int[] { R.id.image,
                        R.id.name });
        // ListView设置适配器
        listView.setAdapter(adapter);
    }
}
布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="${relativePackage}.${activityClass}" >
    <ListView
        android:id="@+id/list_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>
item布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_vertical"
    android:orientation="horizontal" >
    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:text="TEXT" />
    <ImageView
        android:id="@+id/image"
        android:layout_width="200dp"
        android:layout_height="120dp"
        android:layout_marginLeft="50dp"
        android:scaleType="fitXY"
        android:src="@drawable/ic_launcher" />
</LinearLayout>
效果图如下: 
代码如下:
package com.danny_jiang.day08_listview_baseadapter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class MainActivity extends Activity {
    private ListView listView;
    private List<Map<String, String>> list = new ArrayList<Map<String,String>>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listView = (ListView) findViewById(R.id.list_Main);
        for(int i = 0; i < 50; i++) {
            Map<String, String> map = new HashMap<String, String>();
            map.put("key", "value" + i);
            map.put("asd", "asd" + i);
            list.add(map);
        }
        MyBaseAdapter adapter = new MyBaseAdapter(this, list);
        listView.setAdapter(adapter);
    }
}
自定义适配器 MyBaseAdapter:
package com.danny_jiang.day08_listview_baseadapter;
import java.util.List;
import java.util.Map;
import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class MyBaseAdapter extends BaseAdapter{
    // 在自定义Adapter中声明全局的数据源对象
    private List<Map<String, String>> list;
    private Context context;
    // 声明布局填充器,通过它可以填充xml布局文件并返回View对象
    private LayoutInflater inflater;
    public MyBaseAdapter(Context context, List<Map<String, String>> list) {
        this.context = context;
        inflater = LayoutInflater.from(context);
        this.list = list;
    }
    /**
     * 返回ListView需要显示条数
     * 一般情况下需要返回数据源的长度
     */
    @Override
    public int getCount() {
        // 如果数据源是null,则返回0,否则返回数据源的长度
        return list == null ? 0 : list.size();
    }
    /**
     * 返回某位置上的item对象
     * 当调用ListView.getItemAtPosition(0/1)
     * 应当返回数据源中position对应的对象
     */
    @Override
    public Object getItem(int position) {
        return list.get(position);
    }
    /**
     * 返回position对应item的id,一般返回position
     */
    @Override
    public long getItemId(int position) {
        return position;
    }
    /**
     * 返回ListView中position所对应的item需要显示的视图对象
     * position从0开始
     * 
     * @param position      需要填充视图的视图位置,从0开始
     * @param convertView   ListView的优化机制,Android系统对getView返回视图的一个复用机制
     * @param parent            将item视图填充到的AdapterView,也就是ListView本身
     */
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        if (convertView == null) {
            // 通过LayoutInflater填充xml布局文件,将获取到的convertView对象返回
            convertView = inflater.inflate(R.layout.list_item, null);
            // 初始化holder,并为其属性赋值
            holder = new ViewHolder();
            holder.text1 = (TextView) convertView.findViewById(R.id.text1);
            holder.text2 = (TextView) convertView.findViewById(R.id.text2);
            // 给convertView添加标签holder
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        // 获取当前位置中数据源的元素
        Map<String, String> map = list.get(position);
        String value = map.get("key");
        String asd = map.get("asd");
        // 为每个item中的所有UI控件设置属性值
        holder.text1.setText(value);
        holder.text2.setText(asd);
        return convertView;
    }
    class ViewHolder{
        TextView text1;
        TextView text2;
    }
}
布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="${relativePackage}.${activityClass}" >
    <ListView
        android:id="@+id/list_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>
自定义item布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_vertical"
    android:orientation="horizontal" >
    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:text="TEXT" />
    <ImageView
        android:id="@+id/image"
        android:layout_width="200dp"
        android:layout_height="120dp"
        android:layout_marginLeft="50dp"
        android:scaleType="fitXY"
        android:src="@drawable/ic_launcher" />
</LinearLayout>
效果图如下: 
Adapter的作用就是ListView界面与数据之间的桥梁,当列表里的每一项显示到页面时,都会调用Adapter的getView方法返回一个View。
如果在我们的列表有上千项时会是什么样的?是不是会占用极大的系统资源?
  Android中有个叫做Recycler的构件,如果你有100个item,其中只有可见的项目存在内存中,其他的在Recycler中。ListView先请求一个type1视图(getView),然后请求其他可见的item,convertView在getView中是空(null)的。 
当item1滚出屏幕,并且一个新的item从屏幕底端上来时,ListView再请求一个type1视图,convertView此时不是空值了,它的值是item1。你只需设定新的数据,然后返回convertView,不必重新创建一个视图。
  项目中的ListView不仅仅是简单的文字,常常需要自己定义ListView,如果自己定义的Item中存在诸如ImageButton,Button,CheckBox等子控件,此时这些子控件会将焦点获取到,所以当点击item中的子控件时有变化,而item本身的点击没有响应。 
  解决方案的关键是:android:descendantFocusability 
  当一个view获取焦点时,定义ViewGroup及其子控件之间的关系。  
  属性的值有三种: 
        beforeDescendants:viewgroup会优先其子类控件而获取到焦点 
        afterDescendants:viewgroup只有当其子类控件不需要获取焦点时才获取焦点 
        blocksDescendants:viewgroup会覆盖子类控件而直接获得焦点
通常我们用到的是第三种,即在Item布局的根布局加android:descendantFocusability=”blocksDescendants”的属性(阻塞子控件抢夺焦点,让Item具有焦点。这样ListView的onItemClick就能被正确触发,同时item上的button等控件在被点击时照样可以触发自身的点击事件)就好了,至此ListView点击的灵异事件告一段落。
1、android:layout_height属性: 
  必须将ListView的布局高度属性设置为非“wrap_content“,(可以是match_parent/fill parent/400dp等绝对数值),如果ListView的布局高度为“wrap_content”,那么getView()就会重复调用。一般来说,一个item会被调用三次左右。 
    2、ViewHolder: 
  利用ViewHolder内部类,将item布局文件中需要展示的控件定义为属性(其实ViewHolder就是一个自定义的模型类)。这样就把item中散在的多个控件合成一个整体,这样可以有效地避免图片错位。 
3、convertView: 
  ListView的加载是一个item一个item的加载,这样就会每次都inflate一个item布局,然后findViewById一遍该布局上的所有控件。当数据量大的时候,是不可想象的。而利用Recycle回收利用就可以解决问题。所以要善于重复利用convertView,这样可以减少填充布局的过程,减少ViewHolder对象实例化的次数。减少内存开销,提高性能。 
4、convertView的setTag(): 
  利用setTag()方法将ViewHolder对象作为标签附加到convertView上,当convertView被重复利用的时候,因为上面有ViewHolder对象,所以convertView就具有了ViewHolder中的几个属性,这样就节省了findViewById()这个过程。如果一个item有三个控件,如果有100条item,那么在加载数据过程中,就就相当于节省了几百次findViewById(),节约了执行findViewById()的时间,提升了加载速度,节省了性能的开销。 
5、LayoutInflater对象的inflate()方法: 
  inflate()方法一般接收两个参数,第一个参数就是要加载的布局id,第二个参数是指给该布局的外部再嵌套一层父布局,如果不需要就直接传null。
  inflate()方法还有个接收三个参数的方法重载 
  1.如果root为null,attachToRoot将失去作用,设置任何值都没有意义。 
  2.如果root不为null,attachToRoot设为true,则会在加载的布局文件的最外层再嵌套一层root布局。 
  3.如果root不为null,attachToRoot设为false,则root参数失去作用。 
  4.在不设置attachToRoot参数的情况下,如果root不为null,attachToRoot参数默认为true。 
  所以在使用LayoutInflater填充布局的时候,要注意inflate()方法的参数。如果是两个参数,则第二个参数可以采用null;如果使用三个参数的方法,则要注意参数之间的搭配。
1. 目的: 
   Android 应用开发中,采用ListView组件来展示数据是很常用的功能,当一个应用要展现很多的数据时,一般情况下都不会把所有的数据一次就展示出来,而是通过 分页的形式来展示数据,这样会有更好的用户体验。因此,很多应用都是采用分批次加载的形式来获取用户所需的数据。例如:微博客户端可能会在用户滑 动至列表底端时自动加载下一页数据,也可能在底部放置一个”查看更多”按钮,用户点击后,加载下一页数据。 
 2. 核心技术点: 
  a. 借助 ListView组件的OnScrollListener监听事件,去判断何时该加载新数据; 
  b.往服务器get传递表示页码的参数:page。而该page会每加载一屏数据后自动加一; 
    c.利用addAll()方法不断往list集合末端添加新数据,使得适配器的数据源每新加载一屏数据就发生变化; 
    d.利用适配器对象的notifyDataSetChanged()方法。该方法的作用是通知适配器自己及与该数据有关的view,数据已经发生变动,要刷新自己、更新数据。
案例演示:
package com.danny_jiang.day09_listview_scroll;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AbsListView.LayoutParams;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AbsListView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.ListView;
public class MainActivity extends Activity {
    private ListView listView;
    private boolean isLastShown;
    private List<String> data = new ArrayList<String>();
    private ArrayAdapter<String> adapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listView = (ListView) findViewById(R.id.list_Main);
        for(int i = 0; i < 20; i++) {
            data.add("Android-" + i);
        }
        adapter = new ArrayAdapter<String>(this, 
                android.R.layout.simple_list_item_1, data);
        listView.setAdapter(adapter);
        /**
         * 通过ListView.addHeaderView方法可以给ListView添加一个头视图View
         */
        ImageView header = new ImageView(this);
        /**
         * 当需要动态修改UI控件的宽高,需要使用LayoutParams参数对象,
         * 指定宽高,并将此LayoutParams设置到相应的UI控件上
         */
        //初始化LayoutParams时,需要指定宽高
        LayoutParams param = new LayoutParams(LayoutParams.MATCH_PARENT, 200);
        //将LayoutParams设置到UI控件上
        header.setLayoutParams(param);
        //设置ImageView宽高都填充父视图
        header.setScaleType(ScaleType.FIT_XY);
        header.setImageResource(R.drawable.food);
        listView.addHeaderView(header);
        /**
         * 通过ListView.addFooterView方法可以给ListView添加一个底部视图View
         */
        View footer = getLayoutInflater().inflate(R.layout.footer_loading, null);
        listView.addFooterView(footer);
        /**
         * ListView的分页实现
         * 通过setOnScrollListener可以给ListView设置滑动监听
         * 1 滑动状态的改变
         * 2 滑动时,item的位置信息
         * 通过此OnScrollListener可以判断出ListView是否已经滑动到屏幕底部,并且滑动停止
         */
        listView.setOnScrollListener(new OnScrollListener() {
            /**
             * 当ListView的滑动状态发送改变时,此方法被调用
             * @param view  指ListView本身
             * @param scrollState   表示当前ListView所处于的状态
             *      SCROLL_STATE_FLING--2 抛掷状态--手指离开屏幕前,用力滑了一下,屏幕产生惯性滑动
             *      SCROLL_STATE_IDLE--0    停止状态
             *      SCROLL_STATE_TOUCH_SCROLL--1    手指触摸屏幕触发ListView滚动状态
             */
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                android.util.Log.e("TAG", "onScrollStateChanged");
                // 说明ListView已经滑动到底部,并且停止状态
                if (isLastShown && scrollState == SCROLL_STATE_IDLE) {
                    int dataSize = data.size();
                    for(int i = dataSize; i < dataSize + 20; i++) {
                        data.add("Andorid-" + i);
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    // 通知适配器数据源已经发生改变
                    adapter.notifyDataSetChanged();
                }
            }
            /**
             * 只要ListView处于滑动状态,此方法会被一直调用
             * @param view  指ListView本身
             * @param firstVisibleItem  屏幕当前第一个可见Item的位置,从0开始
             * @param visibleItemCount  屏幕当前可见item的个数
             * @param totalItemCount        ListView中总的item的个数
             */
            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, 
                    int visibleItemCount, int totalItemCount) {
                android.util.Log.e("TAG", "onScroll");
                // 通过方法参数可以判断出最后一条是否已经显示到屏幕上
                isLastShown = firstVisibleItem + visibleItemCount == totalItemCount;
            }
        });
    }
}
布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="${relativePackage}.${activityClass}" >
    <ListView
        android:id="@+id/list_Main"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </ListView>
</RelativeLayout>
底部视图布局文件:footer_loading.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="horizontal" >
    <ProgressBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:text="Loading..." />
</LinearLayout>原文:http://blog.csdn.net/sq19920518/article/details/52589266