`

Android ListView的使用

 
阅读更多

本文主要介绍ListView的使用、使用简单数据源、详解如何自定义Adapter(数据源)、如何动态追加内容、如何调整样式以及其他的小技巧

 

0、添加layout文件view_status.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:background="#ADD8E6">
    <ListView 
    	android:id="@+id/statusListView"
    	android:layout_width="fill_parent"
    	android:layout_height="wrap_content"></ListView>
</LinearLayout>

 

1、使用简单数据源

android提供了ArrayAdapterSimpleAdapter,满足了简单的list数据源问题

如list显示一系列字符串,只需要

String data[] = {"信息展示1", "信息展示2", "信息展示3"};
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(
														 AccountManageActivity.this,
														 R.id.accountLongClickTextView,
														 data);
statusListView.setAdapter(arrayAdapter);

其中 ArrayAdapter参数为context、textView的resource id,字符串数组

 

以下到5为自定义数据源

2、Activity中创建listView,并设置数据源

    private Context          context;
    private ListView         statusListView = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.view_status_activity);
        context = getApplicationContext();

        statusListView = (ListView)findViewById(R.id.statusListView);
        StatusAdapter statusAdapter = new StatusAdapter(context, statusInfoList);
        statusListView.setAdapter(statusAdapter);
    }

 其中StatusAdapter为自定义的数据源setAdapter设置数据源

 

3、设置列表每个条目的layout,文件为

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
		xmlns:android="http://schemas.android.com/apk/res/android"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content">
	<ImageView
		android:id="@+id/userIconImageView"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:src="@drawable/icon_sina"
		android:layout_margin="8px">
		</ImageView>
	<TextView
		android:id="@+id/userNameTextView"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:textSize="15px"
		android:textColor="#424952"
		android:layout_alignParentLeft="true">
		</TextView>
</LinearLayout> 

 表示列表每个条目显示一个image和一个text

 

4、自定义数据源--StatusAdapter数据源定义

public class StatusAdapter extends BaseAdapter {

    private List<StatusInfo> mStatusList;
    private Context          mContext;

    public StatusAdapter(Context context, List<StatusInfo> statusList){
        mContext = context;
        mStatusList = statusList;
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return mStatusList.size();
    }

    @Override
    public Object getItem(int arg0) {
        // TODO Auto-generated method stub
        return mStatusList.get(arg0);
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        convertView = LayoutInflater.from(mContext).inflate(R.layout.status_activity, null);
        StatusView statusView = new StatusView();
        statusView.setUserIcon((ImageView)convertView.findViewById(R.id.userIconImageView));
        statusView.setUserName(((TextView)convertView.findViewById(R.id.userNameTextView)));

        StatusInfo statusInfo = mStatusList.get(position);
        if (statusInfo != null && statusView != null) {
            if (statusView.getUserName() != null) {
                statusView.getUserName().setText(statusInfo.getUserName());
            }
            ……
        }
        return convertView;
    }
}

其中BaseAdapter为

Common base class of common implementation for an Adapter that can be used in both ListView (by implementing the specialized ListAdapter interface} and Spinner(by implementing the specialized SpinnerAdapter interface.

 

四个必须实现的函数

4.1、getCount表示在适配器的数据集中有多少数据

public int getCount()
 

4.2、getItem表示得到固定位置的数据集

public Object getItem(int arg0)
 

4.3、getItemId表示得到lilst中固定位置的条目id

public long getItemId(int position)
  

4.4、getView表示得到list中固定位置的条目内容

public View getView(int position, View convertView, ViewGroup parent)

Get a View that displays the data at the specified position in the data set. You can either create a View manually or inflate it from an XML layout file. When the View is inflated, the parent View (GridView, ListView...) will apply default layout parameters unless you use inflate(int, android.view.ViewGroup, boolean) to specify a root view and to prevent attachment to the root.
  

5、每个条目对应的实体类

public class StatusView {

    public ImageView userIcon;
    public TextView  userName;
    
    public void setUserIcon(ImageView userIcon) {
        this.userIcon = userIcon;
    }
    
    public TextView getUserName() {
        return userName;
    }
    
    public void setUserName(TextView userName) {
        this.userName = userName;
    }
}

 

在调试的时候出现一个问题,将断点设置在StatusAdapter的getView函数中,始终无法跳进去,list显示为空

后来发现是getCount使用了默认的函数体return 0; 修改为 return mStatusList.size();问题解决

 

因为listview在开始绘制的时候会调用getCount得到条目的总个数,根据个数注意调用getView绘制每一个条目,这就是为啥return 0;列表不会显示啦

 

6、listView自动追加内容

从上面5最后的介绍可知,首先需要修改getCount的返回值,然后刷新adapter,即通知adapter数据集变更即可。adapter会自动刷新,先调用getCount得到条目的总个数,然后依次调用getView。

上例中如下即可

statusAdapter.getStatusList().addAll(statusInfoList);
statusAdapter.notifyDataSetChanged();

 第一条语句表示追加list,因为getCount是读取list大小,所以也会向相应变化,第二条语句表示通知adapter数据集变更。如果想listView达到底部时自动追加内容可以如下:

 

    /**
     * listView的滚动事件
     */
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

        /**
         * 表示当内容多余一屏并且到达listView底时自动追加
         */
        if (firstVisibleItem > 0 && totalItemCount > 0 && (firstVisibleItem + visibleItemCount == totalItemCount)) {
            setListAdapter();
        }
    }
  

7、listView得到每一个条目的view

经常我们需要在点击或长按item的时候进行相应的响应操作

public void onItemClick(AdapterView<?> arg0, View itemView, int position, long id)

 这个时候我们很想得到存储在某个item中的数据,如用户名、用户id、时间等,这个时候如何得到呢

上述函数的第二个参数意义如下

view	The view within the AdapterView that was clicked (this will be a view provided by the adapter)

 view即表示点击的条目,包含其条目信息,其实这个view就相当于BaseAdapter中getView返回的view。所以我们只要跟getView中set操作相应使用get操作即可得到

参考:

http://developers.androidcn.com/reference/android/widget/AdapterView.OnItemClickListener.html

 

8、设置了背景颜色后,listview在滚动时背景色变黑

listView默认为透明的背景,当使用一个自定义的背景时,在静止情况下listView显示正常,但在滚动滚动条时,listView又会使用默认的(黑色)背景。由于android framework采用了"cache color hint.",即窗口采用默认的背景色,为RGB色,是为了取代性能较差的Porter - Duff混合模式(一种实现淡入淡出效果的模式)。android dark主题默认色为“#191919”。因为listView默认的背景色是透明的,当listView重绘其子控件时候,会用窗口的背景色代替,在滚动listView时需要不停的重绘listView,为了提高性能,这时候android framework框架又重新使用了cache color hint,listView将其子控件的所有背景色填充为cache color hint。更多参考listView backGround

从上面可知,要解决这个问题,我们只需要把默认的cache color hint去掉即可,以下两种方法皆可

a、layout文件中listView的属性增加cacheColorHint

android:cacheColorHint="@color/activityBgColor"

b、activity中listView创建时候setCacheColorHint

statusListView.setCacheColorHint(0);

注意如下代码并不能达到效果

statusListView.setCacheColorHint(R.color.activityBgColor);

参考:

http://developer.android.com/resources/articles/listview-backgrounds.html

 

9、listView前或后面添加其他控件,如Button

如果直接在listView所在的layout文件listView前或者后面添加一个Button,在Activity中create后发现无法显示,这个时候我们可以用listView的addHeaderView或addFooterView实现相应效果,在前或后面添加Button,代码如下

        statusListView = (ListView)findViewById(R.id.statusListView);
        Button moreStatusesBt = new Button(this);
        moreStatusesBt.setText("更多状态");
        moreStatusesBt.setBackgroundColor(R.color.activityBgColor);
        moreStatusesBt.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                setListAdapter();
            }
        });
        statusListView.addFooterView(moreStatusesBt);

 如果是较多的控件,可以另外定义一个layout文件,在程序中加载此文件后,设置header或footer,如下:

View header = ((LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.comment_list_header,
                                                                                                       null, false);
        commentListView.addHeaderView(header);

碰到一个奇怪的问题,当TextView为footer时,无法设置其高度,设置时报异常,

java.lang.IllegalArgumentException: bitmap size exceeds 32bits

 设置代码如下:

        LayoutParams param = new LayoutParams(LayoutParams.FILL_PARENT, R.dimen.moreStatusesBtHeight);
        loadTipText.setLayoutParams(param);

 或如此设置高度

loadTipText.setHeight(R.dimen.moreStatusesBtHeight);

 都会出现异常

 

对于增加了多个控件的listView,在layout中设置的时

  <ListView 
   	android:id="@+id/commentsListView"
   	android:layout_width="fill_parent"
   	android:layout_height="fill_parent"
   	android:cacheColorHint="@color/activityBgColor">
   	</ListView>

 android:layout_height不能为wrap_content否则,listView显示无法滚动

参考:

http://developers.androidcn.com/reference/android/widget/ListView.html

http://developer.android.com/reference/android/widget/Adapter.html

 

 

10、样式

10.1、分割线样式,分别表示颜色和高度

android:divider="#FFCC00"
android:dividerHeight="4px"
  

11、快速定位

statusListView.setSelection(0);

 上面表示定位到index为0的item,即第一个item。

如果存在setAdapter或adatper更新,如下

statusAdapter.notifyDataSetChanged();

 需要将setSelection放在其后面

 

12、滚动到某个位置

使用statusListView.scrollTo(x, y)滚动到某个位置,如scrollView.scrollTo(0, 0)表示滚动到顶部

如果刚刚更新adapter,则调用statusListView.setSelection(0)滚动到顶部;

 

13、记录和恢复ListView滚动的位置

http://trinea.iteye.com/blog/1481474

分享到:
评论
2 楼 kxys422834 2012-04-20  
good!
1 楼 ycq__110 2012-02-22  
    

相关推荐

Global site tag (gtag.js) - Google Analytics