欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2023-11-08 14:57:10
首先还是xml布局文件,在其中添加listview控件: 主布局layout_main.xml 复制代码 代码如下:

首先还是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;
    }
}



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

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