android开发教程之使用listview显示qq联系人列表

首先还是xml布局文件,在其中添加ListView控件:

主布局layout_main.xml

代码如下:

<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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:background="#00aaff"
    tools:context=".MainActivity" >

<TextView
        android:id="@+id/myText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="联系人"
        android:textSize="7pt"
        android:layout_centerHorizontal="true"
        android:textColor="#ffffff"
        android:textStyle="bold" />
    <ListView
        android:id="@+id/qq_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/myText"/>
</RelativeLayout>

然后是每一行ListItem的布局,采用LinerLayout布局,一些注意的点都在里面:

代码如下:

<?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="wrap_content"
    android:background="#efefef" >   
    <!-- LinerLayout有比较奇怪的性质:当布局中的控件可以超出布局规定的大小 ,所以这里一行的行宽改成由内部的几个控件
    控制,而LinerLayout的layout_height改成wrap_content ..  -->
    <ImageButton
        android:id="@+id/ct_photo"
        android:layout_height="70dip"
        android:layout_width="70dip"
        android:layout_margin="5dip"
        android:background="@drawable/contact_0"/>
    <TextView
        android:id="@+id/ct_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="5dip"
        android:layout_toRightOf="@id/ct_photo"
        android:layout_alignTop="@id/ct_photo"
        android:text="为你我受冷风吹"
        android:textSize="8pt"
        android:textStyle="bold"
        android:maxLength="7"/>  
    <TextView
        android:id="@+id/ct_sign"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="5dip"
        android:layout_toRightOf="@id/ct_photo"
        android:layout_alignBottom="@id/ct_photo"
        android:text="为什么受伤的总是我"
        android:textColor="#888888"/>
    <!-- 注意不是layout_padding -->
</RelativeLayout>

因为这里使用的是自己定义的MyAdapter类,可以更灵活的实现列表的一些功能,比如和数据库相联系,动态更新数据、添加按钮控件等等,在本例中模仿QQ列表为头像设置成了ImageButton,后面的附图中的一个Toast信息就是点击图像做出的相应,当然点击一行也可以做出相应,这个后续可能会对QQ程序做一些扩展,如增加网络模块,聊天窗口等等。到时候再进一步讨论。

下面是MyAdapter类,这个类最好和MainActivity类放在同一个包里。

代码如下:

package com.example.android_qqlist;

import java.util.*;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.*;

public class MyAdapter extends BaseAdapter{
    private Context context=null;
    private int resources;
    private ArrayList<HashMap<String,Object>> list=null;
    private String[] from;
    private int[] to;   
    /**
     * 这里仿照的是SimpleAdapter的形参列表
     * @param context
     * @param Resources
     * @param list
     * @param from
     * @param to
     */

public MyAdapter(Context context, int resources,
            ArrayList<HashMap<String, Object>> list, String[] from, int[] to) {
        super();
        this.context = context;
        this.resources = resources;
        this.list = list;
        this.from = from;
        this.to = to;
    }

/**
     * 剩下的问题就是依次实现BaseAdapter的这几个类方法就可以了
     */

@Override
    public int getCount() {        //这个方法返回的是ListView的行数
        // TODO Auto-generated method stub
        return list.size();
    }
    @Override
    public Object getItem(int arg0) {      //这个方法没必要使用,可以用getItemId代替
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public long getItemId(int itemId) {     //点击某一行时会调用该方法,其形参由安卓系统提供
        // TODO Auto-generated method stub
        return itemId;
    }
    /**
     * getView方法为系统在绘制每一行时调用,在此方法中要设置需要显示的文字,图片,
     * 以及为按钮设置监听器。
     *
     * 形参意义:
     * position:当前绘制的item 的位置(ID);
     * convertView,系统在绘制ListView时,如果是绘制第一个Item(即第一行),convertView为null,当
     * 绘制第二个及以后的Item的convertView不为空,这时可以直接利用这个convertView的getTag()方法,获得各控件
     * 的实例,并进行相应的设置,这样可以加快绘图速度。
     *
     * 为了为convertView设置附加信息Tag,这里创建一个内部类ViewHolder,用于盛放一行中所有控件的引用,将这些引用
     * 实例化后作为convertView的附加信息。
     */
    class ViewHolder{
        public ImageButton ctPhoto=null;
        public TextView ctName=null,ctSign=null;

/*
         * 从这里可以看出,from和to数组彼此之间的元素应该一一对应,同时from和to各自元素内部的顺序不同,最后ListView
         * 呈现的位置也会不同!
         */
        public ViewHolder(View convertView){
            ctPhoto=(ImageButton)convertView.findViewById(to[0]);   
            /*注意View和Activity都属于容器类,都需要设置布局文件,内部都含有子控件,且都有findViewById()
             * 他们之间没有明显的继承关系
             */
            ctName=(TextView)convertView.findViewById(to[1]);
            ctSign=(TextView)convertView.findViewById(to[2]);

}

}   
    class ImageListener implements OnClickListener{

private int position;

public ImageListener(int position){
            this.position=position;
        }                          //构造函数没有返回值

@Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            String str=list.get(position).get(from[1]).toString();
            Toast.makeText(context,str+" is Clicked" , Toast.LENGTH_LONG).show();

}

}
    @Override
    public View getView(int position, View convertView, ViewGroup arg2) {
        // TODO Auto-generated method stub

/**
         * 首先判断是不是第一次创建Item,若是,则创建convertView实例和ViewHolder对象,并通过fandViewById()方法
         * 获得每一行中所有空间的实例放在ViewHolder对象中,然后对convertView设置标签
         */
        ViewHolder viewHolder=null;

//注意convertView不是随意创建的,需要有LayoutInflater,根据list_item布局文件创建
        if(convertView==null){
            LayoutInflater inflater=LayoutInflater.from(context);
            convertView=inflater.inflate(resources,null);    //这里的null是一个ViewGroup形参,基本用不上
            viewHolder=new ViewHolder(convertView);
            convertView.setTag(viewHolder);        
        }
        else{
            viewHolder=(ViewHolder)convertView.getTag();    //通过getTag()方法获得附加信息
        }
        /**
         * 这里对viewHolder中的各个控件进行相应的设置
         */
        /**
         * @author DragonGN
         * 这里出现了一个问题:在绘制当前行的ListItem时,只需要对当前行的控件进行设置,因此这里不能加一个for
         * 循环对每一个list中的每一个元素进行遍历,而应该根据当前创建的ListItem行的position,然后
         * 访问数据库list中相应位置的Map的数据,进行控件的设置!
         */
        /**
         * 注意这里必须是setBackgroundDrawable() 而不是setBackground(),后者会报错,尽管前者过期了但一样可用
         */
            viewHolder.ctPhoto.setBackgroundDrawable((Drawable)(list.get(position).get(from[0])));
            //Map中要添加一个Drawable对象,这里的from和to中的元素应该一一对应,其顺序也应该对应ViewHolder构造方法中控件的调用的顺序

viewHolder.ctName.setText((String)(list.get(position).get(from[1])));
            viewHolder.ctSign.setText((String)(list.get(position).get(from[2])));   
            viewHolder.ctPhoto.setOnClickListener(new ImageListener(position));      
        return convertView;     //把这个每一行的View对象返回
    }
}

最后就是MainActivity类了,与因为MyAdapter的封装方式与SimpleAdpter是一样额,因此这里MainActivity的操作基本不变。

代码如下:

package com.example.android_qqlist;

import java.util.*;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.ListView;

public class MainActivity extends Activity {

//每一列的列名/Map的键名  和其对应的View子控件的ID
    String[] from={"userPhoto","userName","userSign"};           //这里的内容对应后面HashMap中的键
    int[] to={R.id.ct_photo,R.id.ct_name,R.id.ct_sign};

//整个ListView所显示的全部信息和资源数组
    int[] photoRes={R.drawable.contact_0,R.drawable.contact_1,R.drawable.contact_2,R.drawable.contact_3};
    String[] strName={"暗夜之殇","街角的幸福","静悄悄","愤怒的小胖"};
    String[] strSign={"Where is my love...","有些事终于想开了","总有一天会寻找到自己的幸福","谁再叫我小胖我跟谁急..."};

//数据链表和Map容器
    ArrayList<HashMap<String,Object>> list=null;
    HashMap<String,Object> map=null;

ListView listView=null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listView=(ListView)findViewById(R.id.qq_list);
        list=new ArrayList<HashMap<String,Object>>();    
        for(int i=0; i<4; i++){
            map=new HashMap<String,Object>();    //map调用put方法添加键值对
            map.put("userPhoto",getResources().getDrawable(photoRes[i]));
            map.put("userName", strName[i]);
            map.put("userSign",strSign[i]);
            list.add(map);       
        }       
        //创建自定义的MyAdapter对象
        MyAdapter adapter=new MyAdapter(this,R.layout.list_item,list,from,to);

//调用ListView的setAdapter()方法设置适配器
        listView.setAdapter(adapter);            
    }

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
}

这几个头像是我自己下载的图片,其对应的资源地址在 MainActivity中用一个 photoRes数组表示的~

(0)

相关推荐

  • Android实现带列表的地图POI周边搜索功能

    先看效果图:(以公司附近的国贸为中心点) 上面是地图,下面是地理位置列表,有的只有地理位置列表(QQ动态的位置),这是个很常见的功能.它有个专门的叫法:POI周边搜索. 实现: 这个效果实现起来其实很简单,不过需要你先阅读下地图的API,这里使用的是高德地图的Android SDK,SDK的配置这里不作讲解,文末会放一些链接供学习. 思路: 1.利用地图的定位功能,获取用户当前的位置 2.根据获得的位置信息调用POI搜索,获取位置列表 3.ListView展示位置列表 4.用户拖动地图,获取地图

  • Android实现三级联动下拉框 下拉列表spinner的实例代码

    主要实现办法:动态加载各级下拉值的适配器 在监听本级下拉框,当本级下拉框的选中值改变时,随之修改下级的适配器的绑定值              XML布局: 复制代码 代码如下: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_w

  • ListView实现聊天列表之处理不同数据项

    通常我们用惯的ListView每一项的布局都是相同的,只是控件所绑定的数据不同.但单单只是如此并不能满足我们某些特殊需求,比如我们常见的QQ.微信的聊天列表,除了有左右之分外,内容更是有很大区别,有文字.语音.图片.视频等等,他们真的是ListView可以实现的吗?答案是肯定的,只要我们做一下类型区别即可. 实现效果如下所示: 大家不要在意布局,这里为了方便就随意了.大家可以看到,这里有两种布局,一种头像在左,一种头像在右,虽然这是一种简单的情况,但我们只需要了解其中的原理,再复杂的情况都可以迎

  • Android实现获取应用程序相关信息列表的方法

    本文所述为Androdi获取手机应用列表的方法,比如获取到Android应用的软件属性.大小和应用程序路径.应用名称等,获取所有已安装的Android应用列表,包括那些卸载了的,但没有清除数据的应用程序,同时在获取到应用信息的时候,判断是不是系统的应用程序,这是一个应用管理器所必需具备的功能. 具体实现代码如下: //AppInfoProvider.java package com.xh.ui; import java.util.ArrayList; import java.util.List;

  • Android用ListView显示SDCard文件列表的小例子

    复制代码 代码如下: filePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/ADASiteMaps/SigRecord";        File file=new File(filePath);        File[] files = file.listFiles(); 构造Adapter, 复制代码 代码如下: for(File mCurrentFile:files){       

  • android二级listview列表实现代码

    今天来实现以下大众点评客户端的横向listview二级列表,先看一下样式.  这种横向的listview二级列表在手机软件上还不太常见,但是使用过平板的都应该知道,在平板上市比较常见的.可能是因为平板屏幕比较大,而且也能展现更多的内容. 下面来看一下我的实现步骤. 首先自定义一个listview,代码如下: 复制代码 代码如下: public class MyListView extends ListView implements Runnable { private float mLastDo

  • Android uses-permission权限列表中文注释版

    android同时也限定了系统资源的使用,像网络设备,SD卡,录音设备等.如果你的应用希望去使用任何系统资源,我们必须去申请Android的权限.这就是<uses-permission>元素的作用. 一个权限通常有以下格式,用一个名字为name 的字符串去指导我们希望使用的权限. 复制代码 代码如下: <uses-permission android:name="string"/> 例如:想要获得networking APIs的使用权限,我们指定如下的元素作为

  • Android通过LIstView显示文件列表的两种方法介绍

    在Android中通过ListView显示SD卡中的文件列表一共有两种方法,一是:通过继承ListActivity显示;二是:利用BaseAdapter显示.BaseAdapter是一个公共基类适配器,用于对ListView和Spinner等 一些控件提供显示数据.下面是利用BaseAdapter类来实现通过LIstView显示SD卡的步骤: 1.main.xml界面设计,如下图 复制代码 代码如下: <?xml version="1.0" encoding="utf-

  • android 支持的语言列表(汇总)

    Arabic, Egypt (ar_EG) -----------------------------阿拉伯语,埃及Arabic, Israel (ar_IL) -------------------------------阿拉伯语,以色列Bulgarian, Bulgaria (bg_BG) ---------------------保加利亚语,保加利亚Catalan, Spain (ca_ES) ---------------------------加泰隆语,西班牙Czech, Czech

  • Android ExpandableListView展开列表控件使用实例

    你是否觉得手机QQ上的好友列表那个控件非常棒? 不是..... 那也没关系,学多一点知识对自己也有益无害. 那么我们就开始吧. 展开型列表控件, 原名ExpandableListView 是普通的列表控件进阶版, 可以自由的把列表进行收缩, 非常的方便兼好看. 首先看看我完成的截图, 虽然界面不漂亮, 但大家可以自己去修改界面. 该控件需要一个主界面XML 一个标题界面XML及一个列表内容界面XML 首先我们来看看 mian.xml 主界面 复制代码 代码如下: //该界面非常简单, 只要一个E

随机推荐