精华内容
下载资源
问答
  • android studio通讯录
    万次阅读 多人点赞
    2021-05-29 16:56:34

    一、项目概述

    本次项目主要实现了对联系人信息(姓名和电话)的增加、删除、修改和查询功能,在删除和修改用户前,可以通过姓名搜索到指定联系人的信息,方便用户操作。通过SQLiteDatabase来存储数据,SQLite数据库和其他的SQL数据库不同, 我们并不需要在手机上另外安装一个数据库软件,Android系统已经集成了这个数据库,功能非常强大,而且使用也很方便快捷。我们下面会详细介绍SQLite数据库。

    二、开发环境

    开发环境还是老样子哈,Android Studio版本3.6.1及以上都可以顺利运行。
    在这里插入图片描述

    三、详细设计

    1、主界面的搭建

    最外层布局采用线性布局LinearLayout。orientation方向选择的也是vertical垂直排列。下面先是放置了一个小的LinearLayout,里面先放一个文本框来显示标题,再放一个图片框,显示图标。然后不断调整内外边距,找到最合适的位置。

        	<TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="通讯录"
                android:textSize="40sp"
                android:textStyle="bold"
                android:textColor="@color/DarkCyan"
                android:layout_margin="20dp"
                android:gravity="center"/>
    
            <ImageView
                android:layout_width="200dp"
                android:layout_height="200dp"
                android:src="@drawable/contact"
                android:layout_marginBottom="10dp"
                android:layout_gravity="center"/>
    

    下面是四个操作按钮,id分别以它们的功能命名,其实四个按钮除了id和text内容不同,其他都是一样的,背景background选择的是写好的btn_selector,在其中设置了按钮的外边框和弧度,而且按钮按下时会有相应的颜色变化。

     		<Button
                android:id="@+id/main_add"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="添加联系人"
                android:gravity="center"
                android:textColor="@color/Honeydew"
                android:background="@drawable/btn_selector"
                android:textSize="20sp"
                android:layout_margin="10dp"/>
            <Button
                android:id="@+id/main_delete"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="删除联系人"
                android:gravity="center"
                android:textColor="@color/Honeydew"
                android:background="@drawable/btn_selector"
                android:textSize="20sp"
                android:layout_margin="10dp"/>
            <Button
                android:id="@+id/main_update"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="修改联系人"
                android:gravity="center"
                android:textColor="@color/Honeydew"
                android:background="@drawable/btn_selector"
                android:textSize="20sp"
                android:layout_margin="10dp"/>
    
            <Button
                android:id="@+id/main_query"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="查询联系人"
                android:gravity="center"
                android:textColor="@color/Honeydew"
                android:background="@drawable/btn_selector"
                android:textSize="20sp"
                android:layout_margin="10dp"/>
    

    我们看下主界面的示意图:
    在这里插入图片描述

    2、SQLite数据库

    2.1、SQLite是什么?

    SQLite是一个轻量级的关系型数据库,运算速度快,占用资源少,很适合在移动设备上使用, 不仅支持标准SQL语法,还遵循ACID(数据库事务)原则,无需账号,使用起来非常方便!Android内置的SQLite是SQLite 3版本的。

    2.2、为什么要用SQLite?

    前面我们学习了使用文件与SharedPreference来保存数据,但是在很多情况下,文件并不一定是有效的,如多线程并发访问是相关的;app要处理可能变化的复杂数据结构等等。比如银行的存钱与取钱!使用前两者就会显得很无力或者繁琐,数据库的出现可以解决这种问题,而Android又给我们提供了这样一个轻量级的SQLite,那肯定要好好用啊。

    2.3、SQLite有什么特点?

    SQLite支持五种数据类型:NULL,INTEGER,REAL(浮点数),TEXT(字符串文本)和BLOB(二进制对象) 虽然只有五种,但是对于varchar,char等其他数据类型都是可以保存的;因为SQLite有个最大的特点:

     你可以将各种数据类型的数据保存到任何字段中,而不用关心字段声明的数据类型是什么。
    

    比如你可以在Integer类型的字段中存放String字符串,当然除了声明为主键INTEGER PRIMARY KEY的字段只能够存储64位整数。
    另外,SQLite 在解析CREATE TABLE 语句时,会忽略 CREATE TABLE 语句中跟在字段名后面的数据类型信息。如下面语句会忽略 name字段的类型信息:

     CREATE TABLE person (personid integer primary key autoincrement, name varchar(20))
    
    SQlite通过文件来保存数据库,一个文件就是一个数据库,数据库中又包含多个表格,表格里又有 多条记录,每个记录由多个字段构成,每个字段有对应的值,每个值我们可以指定类型,也可以不指定 类型(主键除外)

    3、SQLite相关的类

    3.1、SQLiteOpenHelper

    抽象类,我们通过继承该类,然后重写数据库创建以及更新的方法, 我们还可以通过该类的对象获得数据库实例,或者关闭数据库。

    3.2、SQLiteDatabase

    数据库访问类:我们可以通过该类的对象来对数据库做一些增删改查的操作。最核心的类!

    3.3、Cursor

    游标,有点类似于JDBC里的resultset,结果集!可以简单理解为指向数据库中某 一个记录的指针。

    4、创建数据库与版本管理

    Android给我们提供了SQLiteOpenHelper的两个方法:onCreate( )与onUpgrade( )来实现
    onCreate(database):首次使用软件时生成数据库表。
    onUpgrade(database,oldVersion,newVersion):在数据库的版本发生变化时会被调用, 一般在软件升级时才需改变版本号,而数据库的版本是由程序员控制的。

      class MyHelper extends SQLiteOpenHelper{
            public MyHelper(Context context){
                super(context,"dzh.db",null,1);//数据库文件夹名为dzh.db
            }
            //数据库第一次创建时被调用
            @Override
            public void onCreate(SQLiteDatabase db){
                db.execSQL("CREATE TABLE person(_id INTEGER PRIMARY KEY AUTOINCREMENT,name VARCHAR(20),phone VARCHAR(20))");
            }
            //软件版本号发生改变时调用
            @Override
            public void onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion){
    
            }
    

    上述代码第一次启动应用,我们会创建这个dzh.db的文件,并且会执行onCreate()里的方法, 创建一个person的表,它有两个字段:主键personId和name字段;接着如果我们修改db的版本号,那么下次启动就会调用onUpgrade()里的方法,这里我们没有去填写方法,感兴趣的小伙伴可以试一下!这就是创建数据库的模板代码!

    5、实现增删改查

    本项目使用Android给我们提供的操作数据库的一些API方法,先将它们集成在ContactsDao中,然后在增删改查四个Activity中,直接调用对应方法即可。下面教大家如何使用数据库进行增删改查操作:

    • 首先打开数据库,想要访问数据库,第一步肯定先打开。
    	//打开数据库
        public void open() throws SQLException {
            myDBOpenHelper=new MyDBOpenHelper(context);
            try {
                sqLiteDatabase=myDBOpenHelper.getWritableDatabase();
            }catch (SQLException e){
                sqLiteDatabase=myDBOpenHelper.getReadableDatabase();
            }
        }
    
    • 有开就有关,在操作完数据库后记得关闭数据库。
        //关闭数据库
        public void close(){
            if(sqLiteDatabase!=null){
                sqLiteDatabase.close();
                sqLiteDatabase=null;
            }
        }
    
    • 添加数据,想要添加数据就是通过values的键值对进行插入数据。
    	//添加联系人
        public long addContacts(Contacts c){
            //先创建集合对象
            ContentValues values=new ContentValues();
            //插入键值对
            values.put("name",c.name);
            values.put("phone",c.phone);
            return sqLiteDatabase.insert("contacts",null,values);
        }
    
    • 删除数据,肯定是根据主键来删除对应的记录,用的是where约束。
      //删除联系人
        public int deleteContacts(Contacts c){
            return sqLiteDatabase.delete("contacts","name=?",new String[]{String.valueOf(c.name)});
        }
    
    • 修改数据,也是通过where约束找到对应键的记录,然后修改它的其他非键属性。
     	//修改联系人
        public int updateContacts(Contacts c){
            ContentValues value=new ContentValues();
            value.put("phone",c.phone);
            return sqLiteDatabase.update("contacts",value,"name=?",new String[]{String.valueOf(c.name)});
        }
    
    • 查询数据,使用cursor游标,从第一行遍历到最后一行,在遍历每一行记录中,获得到每个字段的值,这样就获取到所有对象的数据了。
    	//根据姓名查找联系人
        public Contacts getContacts(String name){
            Cursor cursor=sqLiteDatabase.query("contacts",null,"name=?",new String[]{name},null,null,null);
            Contacts contacts=new Contacts();
            while(cursor.moveToNext()){
                contacts.name=cursor.getString(cursor.getColumnIndex("name"));
                contacts.phone=cursor.getString(cursor.getColumnIndex("phone"));
            }
            return contacts;
        }
    

    四、项目效果

    通讯录的运行演示视频如下:

    Android Studio实现一个简单的通讯录

    五、项目总结

    本次通讯录项目主要考验学生对于SQLite数据库的使用,还是比较基础的,刚接触Android不久的同学只要动手打一遍就掌握了。这些数据库知识点在今后的Android项目中会经常使用,因此希望大家能够熟练掌握SQLite的使用,方便后续开发项目。

    六、源码下载

    点击右侧链接,即可下载源码:👉Android Studio实现通讯录项目👈

    🍉还可以关注我的公众号《萌新加油站》,🍍后台回复:通讯录


    🚀这有你错过的精彩内容

    这凡尘到底有什么可留恋的?
    原来,都是这些小欢喜啊。
    它们在我的生命里唱着歌,跳着舞。
    活着,也就成了一件特别让人不舍的事情。
    2016.3.12 17:34 YXN

    更多相关内容
  • 使用Android开发 简单 强悍 适合初学者,代码具有登录界面,注册界面,添加通讯录联系人,修改联系人,删除联系人,查询联系人等多个功能,简单使用十分适合初学者练习 参考使用 内有apk 可直接在手机上运行
  • 本次通讯录项目主要实现了联系人信息(姓名和电话)的增加、删除、修改和查询功能。主要用到SQLiteDatabase来存储数据,SQLite数据库和其他的SQL数据库不同, 我们并不需要在手机上另外安装一个数据库软件,Android...
  • 用于与博客匹配的资源,简单学习Android 中读取通讯录的操作,方便大家进行学习和思考。仅用于学习参考,谢谢
  • 运用Android Studio练习的一个通讯录App,其中存储数据用的是SQLite数据库,能够实现联系人信息的增、删、改、查。 并且还能实现打电话功能和发短信功能。
  • 本次项目主要实现了对联系人信息(姓名和电话)的增加、删除、修改和查询功能,在删除和修改用户前,可以通过姓名搜索到指定联系人的信息,方便用户操作。使用SQLiteDatabase数据库来存储数据,界面简洁优雅,美观...
  • 1、获取手机通讯录的信息;2、手机通讯录的数据封装;3、手机通讯录的信息的UI适配;4、对ListView的优化。
  • 基于SQLite开发的简易通讯录 共两个页面:启动页+主页面 主页面实现增删改查、读取系统联系人、拨号等功能 非常非常非常简陋,所有功能都在主页面实现,没有封装类
  • android Studio通讯录

    千次阅读 2020-03-29 12:05:45
    帮别人做的期末考试作业· 1.大纲 2.目录结构 3.显示 4.源码

    帮别人做的期末考试作业·

    1.大纲

    在这里插入图片描述

    2.目录结构

    在这里插入图片描述

    3.显示在这里插入图片描述

    在这里插入图片描述

    4.源码

    //download.csdn.net/download/qq_42733641/12279869

    展开全文
  • 程序是使用 Android studio 开发的简单通讯录 适合刚入门的Android程序员,有对通讯录的增删改查功能,有登录界面 和验证密码功能 有数据库的简单练习
  • 包括Android 移动开发基础案例教程课本中第五章实战演练——绿豆通讯录的源代码,可用Android studio运行,适合初学者学习。
  • 功能包含:新增联系人、编辑联系人、删除联系人、拨打电话、发送短信等相关操作。 资源包含源码:1、apk安装包 2、演示视频 3、 基本安装环境、4、运行文档 5、以及源代码
  • 基于Android电话通讯录

    2018-03-16 10:10:39
    使用Android Studio平台,自定义适配器,利用SQLite的数据库技术,实现在手机电话通讯录。功能有:查看所有联系人,添加联系人,修改联系人信息,删除联系人。
  • android实现通讯录源码

    2021-03-26 13:00:33
    用Java实现的简单通讯录源码,运行环境:Eclipse,SQLite开发软件:Eclipse-helios、JDK1.6、Android SDK 、ADT10.0
  • 自己闲暇时间做的安卓通讯录,是用android studio 搭建的,直接可以导入使用,适合入门的新手使用,本人也是初入者,所以大家一起学习
  • Android Studio 获取手机联系人并进行,发短信,打电话,增删“改”操作
  • android 简易通讯录,使用sqlite数据库,开发环境idea。
  • 摘要:Java源码,Android源码,通讯录 Android contact通讯录实例,比较不错的例子,来自书中的完整实例,Android手机读取联系人信息、显示、保存、编辑联系人,多卡同时读取联系人等,涉及要点:删除指定数据列、URI...
  • 主要介绍了Android Studio实现发短信功能,非常不错,具有参考借鉴价值,需要的朋友可以参考下
  • Android Studio 实验四:手机通讯录(ListView的应用)

    目录

    activity_main.xml

    FruitAdapter

    Fruit类

    fruit_item.xml

    Activity

    运行截图

    项目文件


    activity_main.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">
    
        <ListView
            android:id="@+id/list_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            />
    
    </LinearLayout>

    FruitAdapter

    (虽然是通讯录,但是因为书上是拿水果举的例子,所以文件的命名也就照搬了)在包内创建一个Java类并命名为FruitAdapter,输入代码如下:

    public class FruitAdapter extends ArrayAdapter<Fruit> {
    
        private int resouceId;
    
        public FruitAdapter(Context context, int textViewResourceId, List<Fruit> objects) {
            super(context, textViewResourceId, objects);
            resouceId = textViewResourceId;
        }
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            Fruit fruit = getItem(position);
    
            View view;
            if (convertView == null) {
                view = LayoutInflater.from(getContext()).inflate(resouceId,parent,false);
            } else {
                view = convertView;
            }
    
            ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
            TextView fruitName = (TextView) view.findViewById(R.id.fruit_name);
            fruitImage.setImageResource(fruit.getImageId());
            fruitName.setText(fruit.getName());
            return view;
    
        }
    
    }
    

    Fruit类

    在包里创建Java类并命名为Fruit,代码如下:

    public class Fruit {
        private String name;
        private int imageId;
    
        public Fruit(String name, int imageId) {
            this.name = name;
            this.imageId = imageId;
        }
    
        public String getName() {
            return name;
        }
    
        public int getImageId() {
            return  imageId;
        }
    }
    

    fruit_item.xml

     创建layout文件并命名为fruit_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="wrap_content">
    
        <ImageView
            android:id="@+id/fruit_image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <TextView
            android:id="@+id/fruit_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginLeft="10dp"/>
    
    </LinearLayout>

    Activity

    public class MainActivity extends AppCompatActivity {
    
        private List<Fruit> fruitList = new ArrayList<>();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            initFruits();//初始化水果数据
            FruitAdapter adapter = new FruitAdapter(MainActivity.this,
                    R.layout.fruit_item,fruitList);
            ListView listView = (ListView) findViewById(R.id.list_view);
            listView.setAdapter(adapter);
    
        }
    
    
    //对图片进行加载,图片放在mian/res/drawable里面
        private void initFruits() {
            for(int i=0; i < 3; i++) {
                Fruit apple = new Fruit("周杰伦",R.drawable.image04);
                fruitList.add(apple);
                Fruit banana = new Fruit("哆啦",R.drawable.image02);
                fruitList.add(banana);
                Fruit orange = new Fruit("天皇",R.drawable.image03);
                fruitList.add(orange);
            }
        }
    }

     

    运行截图

      

    项目文件

    AndroidStudio实验四:手机通讯录(ListView的应用)-Android文档类资源-CSDN下载AndroidStudio实验四:手机通讯录(ListView的应用)更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/nazonomaster/85219538

     

     

    展开全文
  • android简易通讯录

    热门讨论 2012-10-21 00:43:06
    android简易通讯录,适合入门新手.本程序适合初学者学习项目开发技巧.
  • Android Studio中的手机通讯录开发

    万次阅读 多人点赞 2021-01-18 16:40:53
    Android Studio中的手机通讯录,包含功能(按首字母排序,动态添加) 第一次写博客,也刚踏入工作,想着把自己在项目中遇到的问题,以及自己在工作中所做的项目记录下来,方便以后自己查找知识,一开始没有接触过...

    Android Studio中的手机通讯录,包含功能(按首字母排序,动态添加)

    第一次写博客,也刚踏入工作,想着把自己在项目中遇到的问题,以及自己在工作中所做的项目记录下来,方便以后自己查找知识,一开始没有接触过Android,为了找工作,自学了5个月的Java,到公司实习的主要负责任务是安卓开发。
    第一个做的任务就是做的手机通讯录,虽然做出来了,但是还是大多数借鉴网络上的,自己再做了一点修改。
    下面是自己做的效果图,供大家参考,写的不好,大家就随便看看,希望对借鉴的人有点参考的意义。

    在这里插入图片描述 在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    上面几幅图形是运行成功候的图像,接下来就是代码部分。

    MainActivity 主页面功能代码

    package com.example.lastmodel;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.content.Intent;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.ImageButton;
    
    public class MainActivity extends AppCompatActivity implements View.OnClickListener {
        private ImageButton addUser;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            addUser = findViewById(R.id.addUser);
            addUser.setOnClickListener(this);
        }
    
        @Override
        public void onClick(View v) {
    
            startActivity(new Intent(MainActivity.this,AddUserActivity.class));
    
        }
    }
    

    activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <TextView
            android:id="@+id/tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="联系人"
            android:layout_centerHorizontal="true"
            android:textSize="30dp"/>
        <ImageButton
            android:id="@+id/addUser"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:layout_alignParentBottom="true"
            android:layout_alignParentEnd="true"
            android:layout_alignParentRight="true"
            android:background="@drawable/add"/>
    </RelativeLayout>
    

    AddUserActivity 添加联系人页面功能

    package com.example.lastmodel;
    
    import android.content.ContentValues;
    import android.content.Intent;
    import android.database.sqlite.SQLiteDatabase;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.Toast;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    /**
     * @author: hanxuan
     * @date: 2020/12/2
     */
    
    public class AddUserActivity extends AppCompatActivity implements View.OnClickListener {
        private MyDatabaseHelper dbHelper;
        private EditText username,telnumber;
        private Button ok_add;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_add_user);
    
            dbHelper = new MyDatabaseHelper(this,"Use.db",null,1);
            username = findViewById(R.id.add_user_name);
            telnumber = findViewById(R.id.add_user_telnumber);
    
            ok_add = findViewById(R.id.ok_add);
            ok_add.setOnClickListener(this);
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.ok_add:{
                    String name = username.getText().toString();
                    String tel_number = telnumber.getText().toString();
                    if (name == null||tel_number == null){
                        Toast.makeText(this,"用户名和电话不能为空",Toast.LENGTH_SHORT).show();
                    }else {
                        SQLiteDatabase db = dbHelper.getReadableDatabase();
                        ContentValues values = new ContentValues();
                        values.put("name",name);
                        values.put("telnumber",tel_number);
                        db.insert("Use",null,values);
                        Toast.makeText(this,"添加成功",Toast.LENGTH_SHORT).show();
                        startActivity(new Intent(AddUserActivity.this,UserListViewActivity.class));
                        this.finish();
                        db.close();
                    }
                }
    
            }
        }
    }
    

    activity_add_user.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".AddUserActivity">
    
        <EditText
            android:id="@+id/add_user_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:hint="姓名"/>
        <EditText
            android:id="@+id/add_user_telnumber"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:layout_below="@+id/add_user_name"
            android:hint="电话号码"/>
    
        <Button
            android:id="@+id/ok_add"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/add_user_telnumber"
            android:text="添加"/>
    
    </RelativeLayout>
    

    UserListViewActivity 展示姓名的页面功能

    package com.example.lastmodel;
    
    import android.animation.Animator;
    import android.animation.ObjectAnimator;
    import android.annotation.SuppressLint;
    import android.database.Cursor;
    import android.database.sqlite.SQLiteDatabase;
    import android.os.Bundle;
    import android.text.Editable;
    import android.text.TextUtils;
    import android.text.TextWatcher;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.ViewConfiguration;
    import android.view.Window;
    import android.widget.ListView;
    import android.widget.TextView;
    
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.recyclerview.widget.LinearLayoutManager;
    import androidx.recyclerview.widget.RecyclerView;
    
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    /**
     * @author: hanxuan
     * @date: 2020/12/2
     */
    public class UserListViewActivity extends AppCompatActivity {
        private MyDatabaseHelper dbHelper;
        private RecyclerView mRecyclerView;
        private List<SortModel> SourceDateList;
        private SideBar sideBar;
        private TextView dialog;
        private SortAdapter adapter;
        private ClearEditText mClearEditText;
        private PinyinComparator pinyinComparator;
        LinearLayoutManager manager;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_user_list_view);
    
            dbHelper = new MyDatabaseHelper(this,"User4.db",null,1);
            initViews();
            initUser();
    
            mRecyclerView = findViewById(R.id.recyclerView);
            
            SourceDateList = filledData(SourceDateList);
    
        }
    
        private void initViews()  {
            pinyinComparator = new PinyinComparator();
    
            sideBar =  findViewById(R.id.sideBar);
            dialog =  findViewById(R.id.dialog);
            sideBar.setTextView(dialog);
    
            sideBar.setOnTouchingLetterChangedListener(new SideBar.OnTouchingLetterChangedListener() {
    
                @Override
                public void onTouchingLetterChanged(String s) {
                    //该字母首次出现的位置
                    int position = adapter.getPositionForSection(s.charAt(0));
                    if (position != -1) {
                        manager.scrollToPositionWithOffset(position, 0);
                    }
    
                }
            });
            mClearEditText =  findViewById(R.id.filter_edit);
            mClearEditText.addTextChangedListener(new TextWatcher() {
    
                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                    filterData(s.toString());
                }
    
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                }
                @Override
                public void afterTextChanged(Editable s) {
                }
            });
    
    
        }
    
        public  List<SortModel> initUser(){
            SourceDateList = new ArrayList<>();
            SQLiteDatabase db = dbHelper.getReadableDatabase();
            Cursor cursor = db.query("Use",null,null,null,null,null,null);
            if (cursor.moveToFirst()){
                do{
                    String name = cursor.getString(cursor.getColumnIndex("name"));
    
                    SortModel data = new SortModel(name);
                    //SourceDateList.add(data);
                    SourceDateList.add(data);
                }while (cursor.moveToNext());
            }
            cursor.close();
            return SourceDateList;
        }
    
        private List<SortModel> filledData(List<SortModel> list) {
            List<SortModel> mSortList = new ArrayList<>();
    
            for (int i = 0; i < list.size(); i++) {
                SortModel sortModel = list.get(i);
                //sortModel.setName(list.get(i));
                //汉字转换成拼音
                String pinyin = PinyinUtils.getPingYin(list.get(i).getName());
                String sortString = pinyin.substring(0, 1).toUpperCase();
    
                // 正则表达式,判断首字母是否是英文字母
                if (sortString.matches("[A-Z]")) {
                    sortModel.setLetters(sortString.toUpperCase());
                } else {
                    sortModel.setLetters("#");
                }
    
                mSortList.add(sortModel);
            }
            return mSortList;
    
        }
    
        private void filterData(String filterStr) {
            List<SortModel> filterDateList = new ArrayList<>();
    
            if (TextUtils.isEmpty(filterStr)) {
                filterDateList = SourceDateList;
            } else {
                filterDateList.clear();
                for (SortModel sortModel : SourceDateList) {
                    String name = sortModel.getName();
                    if (name.indexOf(filterStr.toString()) != -1 ||
                            PinyinUtils.getFirstSpell(name).startsWith(filterStr.toString())
                            //不区分大小写
                            || PinyinUtils.getFirstSpell(name).toLowerCase().startsWith(filterStr.toString())
                            || PinyinUtils.getFirstSpell(name).toUpperCase().startsWith(filterStr.toString())
                    ) {
                        filterDateList.add(sortModel);
                    }
                }
            }
            // 根据a-z进行排序
            Collections.sort(filterDateList, pinyinComparator);
            adapter.updateList(filterDateList);
        }
    }
    

    activity_user_list_view.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:orientation="vertical"
        android:focusable="true"
        android:focusableInTouchMode="true">
    
        <com.example.lastmodel.ClearEditText
            android:id="@+id/filter_edit"
            android:layout_width="match_parent"
            android:layout_height="38dp"
            android:layout_marginLeft="12dp"
            android:layout_marginTop="10dp"
            android:layout_marginRight="12dp"
            android:layout_marginBottom="5dp"
            android:background="@drawable/shape"
            android:drawableLeft="@drawable/drawable"
            android:hint="搜索联系人"
            android:maxLines="1"
            android:paddingLeft="8dp"
            android:textSize="17dp" />
    
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent" >
    
            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/recyclerView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                />
    
            <TextView
                android:id="@+id/dialog"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_centerInParent="true"
                android:background="#A9A9A9"
                android:gravity="center"
                android:textColor="	#000000"
                android:textSize="30dp"
                android:visibility="invisible" />
    
            <com.example.lastmodel.SideBar
                android:id="@+id/sideBar"
                android:layout_width="30dp"
                android:layout_height="match_parent"
                android:layout_alignParentRight="true"
                />
        </RelativeLayout>
    
    </LinearLayout>
    

    以上的代码就是界面以及部分功能实现的代码,接下来的代码就是辅助类。

    CharPortraitView.java

    该类主要的功能是获得名字的首汉字,以及名字前面的圆形和随机分布圆形的颜色

    package com.example.lastmodel;
    
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.Color;
    import android.graphics.drawable.GradientDrawable;
    
    import android.util.AttributeSet;
    import android.view.Gravity;
    import android.view.View;
    
    import androidx.appcompat.widget.AppCompatTextView;
    import androidx.core.widget.TextViewCompat;
    
    import java.util.Random;
    /**
     * @author: hanxuan
     * @date: 2020/12/2
     */
    
    public class CharPortraitView extends AppCompatTextView {
    
        private boolean isRandom = false;
        private Random random;
        private int mBackColor;
        private Context mContext;
        private String[] colors;
        private boolean mHead=true;
        private String mContent;
    
    
        public CharPortraitView(Context context) {
            this(context, null);
        }
    
        public CharPortraitView(Context context, AttributeSet attrs) {
            super(context, attrs);
            mContext = context;
            init(attrs);
            build();
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            int width = View.MeasureSpec.getSize(widthMeasureSpec);
            int height = View.MeasureSpec.getSize(heightMeasureSpec);
            int minSize = Math.min(width, height);
            setMeasuredDimension(minSize, minSize);
        }
    
        private void init(AttributeSet attrs) {
            // 初始化随机数
            random = new Random();
            // 获取参数
            TypedArray array = mContext.obtainStyledAttributes(attrs, R.styleable.CharPortraitView);
            // 获取是否随机背景
            isRandom = array.getBoolean(R.styleable.CharPortraitView_random, false);
            // 获取背景颜色
            mBackColor = array.getColor(R.styleable.CharPortraitView_back_color, Color.BLUE);
            array.recycle();
        }
        //设置
        private void build() {
            if (!isRandom) {
                mBackColor = getRandomColor(); //产生随机颜色
            }
            // 设置居中
            setGravity(Gravity.CENTER);
            // 设置自适应文字大小
            TextViewCompat.setAutoSizeTextTypeWithDefaults(this, TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM);
            // 设置背景颜色
            setBackgroundResource(R.drawable.shape_drawable);
            GradientDrawable drawable = (GradientDrawable) getBackground();
            drawable.setColor(mBackColor);
            setBackgroundDrawable(drawable);
            if (mContent==null){
                return;
            }
            if (mHead){
                setText(mContent.substring(0, 1));//取首字符显示
            }else {
                setText(mContent.substring(mContent.length()-1, mContent.length()));//取末尾字符显示
            }
        }
        /**
         * 设置文本内容
         *@param mHead  true 第一个字符 false 最后一个字符
         *@return
         */
        public CharPortraitView setHead(boolean mHead) {
            this.mHead=mHead;
            build();
            return this;
        }
        //设置文本内容
        public CharPortraitView setContent(String str) {
            this.mContent=str;
            build();
            return this;
        }
    
        //设置背景颜色
        public CharPortraitView setBackColor(int backColor) {
            mBackColor = backColor;
            isRandom = false;
            build();
            return this;
        }
        //设置是否开启随机颜色
        public CharPortraitView setRandom(boolean isRandom) {
            this.isRandom = isRandom;
            build();
            return this;
        }
        /**
         * 设置随机背景颜色数组
         * @param colors
         * @return
         */
        public CharPortraitView setBackColor(String[] colors){
            this.colors=colors;
            build();
            return this;
        }
        /**
         * 获取随机背景颜色
         * @return
         */
        private int getRandomColor() {
            String[] colorArray;
            if (colors!=null&&colors.length>0){
               colorArray=colors;
            }else {
                colorArray=mContext.getResources().getStringArray(R.array.color);
            }
            int value = random.nextInt(colorArray.length);
            return Color.parseColor(colorArray[value]);
        }
    
    }
    
    
    

    ClearEditText.java

    该类主要是实现清除搜索栏的内容

    package com.example.lastmodel;
    
    import android.content.Context;
    import android.graphics.drawable.Drawable;
    import android.text.Editable;
    import android.text.TextWatcher;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.View.OnFocusChangeListener;
    import android.view.animation.Animation;
    import android.view.animation.CycleInterpolator;
    import android.view.animation.TranslateAnimation;
    import android.widget.EditText;
    /**
     * @author: hanxuan
     * @date: 2020/12/2
     */
    
    public class ClearEditText extends androidx.appcompat.widget.AppCompatEditText implements OnFocusChangeListener, TextWatcher {
        private Drawable mClearDrawable;
     
        public ClearEditText(Context context) { 
        	this(context, null); 
        } 
     
        public ClearEditText(Context context, AttributeSet attrs) { 
        	this(context, attrs, android.R.attr.editTextStyle);
        } 
        
        public ClearEditText(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            init();
        }
        
        
        private void init() { 
        	mClearDrawable = getCompoundDrawables()[2];
            if (mClearDrawable == null) { 
            	mClearDrawable = getResources().getDrawable(R.drawable.guanbifanhuishanchu);
            } 
            mClearDrawable.setBounds(-17, 5, mClearDrawable.getIntrinsicWidth(), mClearDrawable.getIntrinsicHeight());
            setClearIconVisible(false); 
            setOnFocusChangeListener(this); 
            addTextChangedListener(this); 
        } 
    
        @Override 
        public boolean onTouchEvent(MotionEvent event) { 
            if (getCompoundDrawables()[2] != null) { 
                if (event.getAction() == MotionEvent.ACTION_UP) { 
                	boolean touchable = event.getX() > (getWidth() 
                            - getPaddingRight() - mClearDrawable.getIntrinsicWidth()) 
                            && (event.getX() < ((getWidth() - getPaddingRight())));
                    if (touchable) { 
                        this.setText(""); 
                    } 
                } 
            } 
     
            return super.onTouchEvent(event); 
        } 
     
        @Override
        public void onFocusChange(View v, boolean hasFocus) { 
            if (hasFocus) { 
                setClearIconVisible(getText().length() > 0); 
            } else { 
                setClearIconVisible(false); 
            } 
        } 
     
     
        protected void setClearIconVisible(boolean visible) {
            Drawable right = visible ? mClearDrawable : null; 
            setCompoundDrawables(getCompoundDrawables()[0], 
                    getCompoundDrawables()[1], right, getCompoundDrawables()[3]); 
        } 
         
        
        @Override
        public void onTextChanged(CharSequence s, int start, int count, 
                int after) { 
            setClearIconVisible(s.length() > 0); 
        } 
     
        @Override 
        public void beforeTextChanged(CharSequence s, int start, int count, 
                int after) { 
             
        } 
     
        @Override 
        public void afterTextChanged(Editable s) { 
             
        } 
        
       
        public void setShakeAnimation(){
        	this.setAnimation(shakeAnimation(5));
        }
        
        
        public static Animation shakeAnimation(int counts){
        	Animation translateAnimation = new TranslateAnimation(0, 10, 0, 0);
        	translateAnimation.setInterpolator(new CycleInterpolator(counts));
        	translateAnimation.setDuration(1000);
        	return translateAnimation;
        }
     
     
    }
    
    

    MyDatabaseHelper.java

    数据库的创建

    package com.example.lastmodel;
    
    import android.content.Context;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteOpenHelper;
    import android.widget.Toast;
    
    import androidx.annotation.Nullable;
    /**
     * @author: hanxuan
     * @date: 2020/12/2
     */
    public class MyDatabaseHelper extends SQLiteOpenHelper {
        public static final String Create_Table_User = "create table Use (" + "name text," + "telnumber text)";
        private Context mContext;
    
        public MyDatabaseHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
            super(context, name, factory, version);
    
        }
    
    
        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(Create_Table_User);
            //Toast.makeText(mContext,"创建成功", Toast.LENGTH_SHORT).show();
    
        }
    
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    
        }
    }
    
    

    PinyinComparator.java

    package com.example.lastmodel;
    
    import java.util.Comparator;
    
    public class PinyinComparator implements Comparator<SortModel> {
    
    	public int compare(SortModel o1, SortModel o2) {
    		if (o1.getLetters().equals("@")
    				|| o2.getLetters().equals("#")) {
    			return -1;
    		} else if (o1.getLetters().equals("#")
    				|| o2.getLetters().equals("@")) {
    			return 1;
    		} else {
    			return o1.getLetters().compareTo(o2.getLetters());
    		}
    	}
    
    }
    
    

    PinyinUtils.java

    package com.example.lastmodel;
    
    
    import net.sourceforge.pinyin4j.PinyinHelper;
    import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
    import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
    import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
    import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
    import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
    /**
     * @author: hanxuan
     * @date: 2020/12/2
     */
    public class PinyinUtils {
        /**
         * 获取拼音
         *
         * @param inputString
         * @return
         */
        public static String getPingYin(String inputString) {
            HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
            format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
            format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
            format.setVCharType(HanyuPinyinVCharType.WITH_V);
    
            char[] input = inputString.trim().toCharArray();
            String output = "";
    
            try {
                for (char curChar : input) {
                    if (Character.toString(curChar).matches("[\\u4E00-\\u9FA5]+")) {
                        /*至少匹配一个汉字的写法,这两个unicode值正好时Unicode表中的汉字的头和尾
                        * []代表里面的值出现一个就可以, 后边的"+"代表至少出现1次,合起来即至少匹配一个汉字*/
                        String[] temp = PinyinHelper.toHanyuPinyinStringArray(curChar, format);
                        output += temp[0];
                    } else
                        output += Character.toString(curChar);
                }
            } catch (BadHanyuPinyinOutputFormatCombination e) {
                e.printStackTrace();
            }
            return output;
        }
    
        /**
         * 获取第一个字的拼音首字母
         * @param chinese
         * @return
         */
        public static String getFirstSpell(String chinese) {
            StringBuffer pinYinBF = new StringBuffer();
            char[] arr = chinese.toCharArray();
            HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
            defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
            defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
            for (char curChar : arr) {
                if (curChar > 128) {
                    try {
                        String[] temp = PinyinHelper.toHanyuPinyinStringArray(curChar, defaultFormat);
                        if (temp != null) {
                            pinYinBF.append(temp[0].charAt(0));
                        }
                    } catch (BadHanyuPinyinOutputFormatCombination e) {
                        e.printStackTrace();
                    }
                } else {
                    pinYinBF.append(curChar);
                }
            }
            return pinYinBF.toString().replaceAll("\\W", "").trim();
        }
    
    }
    
    

    SideBar.java

    右边侧滑栏的实现

    package com.example.lastmodel;
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Typeface;
    import android.graphics.drawable.ColorDrawable;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.View;
    import android.widget.TextView;
    /**
     * @author: hanxuan
     * @date: 2020/12/2
     */
    public class SideBar extends View {
    	// 触摸事件
    	private OnTouchingLetterChangedListener onTouchingLetterChangedListener;
    	public static String[] b = { "A", "B", "C", "D", "E", "F", "G", "H", "I",
    			"J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
    			"W", "X", "Y", "Z","#"};
    	private int choose = -1;
    	private Paint paint = new Paint();
    
    	private TextView mTextDialog;
    
    	/**
    	 * 为SideBar设置显示字母的TextView
    	 * @param textDialog
    	 */
    	public void setTextView(TextView textDialog) {
    		this.mTextDialog = textDialog;
    	}
    
    
    	public SideBar(Context context, AttributeSet attrs, int defStyle) {
    		super(context, attrs, defStyle);
    	}
    
    	public SideBar(Context context, AttributeSet attrs) {
    		super(context, attrs);
    	}
    
    	public SideBar(Context context) {
    		super(context);
    	}
    
    	protected void onDraw(Canvas canvas) {
    		super.onDraw(canvas);
    		int height = getHeight();
    		int width = getWidth();
    		int singleHeight = height / b.length;
    
    		for (int i = 0; i < b.length; i++) {
    			paint.setColor(Color.rgb(105, 105, 105));
    			// paint.setColor(Color.WHITE);
    			paint.setTypeface(Typeface.DEFAULT_BOLD);
    			paint.setAntiAlias(true);
    			paint.setTextSize(35);
    			if (i == choose) {
    				paint.setColor(Color.parseColor("#3399ff"));
    				paint.setFakeBoldText(true);
    			}
    
    			float xPos = width / 2 - paint.measureText(b[i]) / 2;
    			float yPos = singleHeight * i + singleHeight;
    			canvas.drawText(b[i], xPos, yPos, paint);
    			paint.reset();
    		}
    
    	}
    
    	@Override
    	public boolean dispatchTouchEvent(MotionEvent event) {
    		final int action = event.getAction();
    		final float y = event.getY();
    		final int oldChoose = choose;
    		final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;
    		final int c = (int) (y / getHeight() * b.length);
    
    
    		switch (action) {
    		case MotionEvent.ACTION_UP:
    			setBackground(new ColorDrawable(0x00000000));
    			choose = -1;
    			invalidate();
    			if (mTextDialog != null) {
    				mTextDialog.setVisibility(View.INVISIBLE);
    			}
    			break;
    
    		default:
    			setBackgroundResource(R.drawable.sidebar_background);
    			if (oldChoose != c) {
    				if (c >= 0 && c < b.length) {
    					if (listener != null) {
    						listener.onTouchingLetterChanged(b[c]);
    					}
    					if (mTextDialog != null) {
    						mTextDialog.setText(b[c]);
    						mTextDialog.setVisibility(View.VISIBLE);
    					}
    					
    					choose = c;
    					invalidate();
    				}
    			}
    
    			break;
    		}
    		return true;
    	}
    
    
    	public void setOnTouchingLetterChangedListener(
    			OnTouchingLetterChangedListener onTouchingLetterChangedListener) {
    		this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;
    	}
    
    
    	public interface OnTouchingLetterChangedListener {
    		void onTouchingLetterChanged(String s);
    	}
    
    }
    

    SortAdapter.java

    首字母排序功能

    package com.example.lastmodel;
    
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import androidx.recyclerview.widget.RecyclerView;
    
    import java.util.List;
    
    /**
     * @author: hanxuan
     * @date: 2020/12/2
     */
    
    public class SortAdapter extends RecyclerView.Adapter<SortAdapter.ViewHolder> {
        private LayoutInflater mInflater;
        private List<SortModel> mData;
        private Context mContext;
    
    
        public SortAdapter(Context context, List<SortModel> data) {
            mInflater = LayoutInflater.from(context);
            mData = data;
            this.mContext = context;
        }
    
        @Override
        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = mInflater.inflate(R.layout.item, parent,false);
            ViewHolder viewHolder = new ViewHolder(view);
            viewHolder.tvTag = view.findViewById(R.id.tag);
            viewHolder.tvName = view.findViewById(R.id.name);
            return viewHolder;
        }
    
        @Override
        public void onBindViewHolder(final ViewHolder holder, final int position) {
            int section = getSectionForPosition(position);
            //如果当前位置等于该分类首字母的Char的位置 ,则认为是第一次出现
            if (position == getPositionForSection(section)) {
                holder.tvTag.setVisibility(View.VISIBLE);
                holder.tvTag.setText(mData.get(position).getLetters());
                holder.portrait.setContent(mData.get(position).getName()).setHead(true);
            } else {
                holder.tvTag.setVisibility(View.GONE);
                holder.portrait.setContent(mData.get(position).getName()).setHead(true);
            }
            if (mOnItemClickListener != null) {
                holder.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        mOnItemClickListener.onItemClick(holder.itemView, position);
                    }
                });
            }
            holder.tvName.setText(this.mData.get(position).getName());
            holder.tvName.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Toast.makeText(mContext, mData.get(position).getName(),Toast.LENGTH_SHORT).show();
                }
            });
        }
        @Override
        public int getItemCount() {
            return mData.size();
        }
    
        public interface OnItemClickListener {
            void onItemClick(View view, int position);
        }
    
        private OnItemClickListener mOnItemClickListener;
    
        public void setOnItemClickListener(OnItemClickListener mOnItemClickListener) {
            this.mOnItemClickListener = mOnItemClickListener;
        }
    
    
        public static class ViewHolder extends RecyclerView.ViewHolder {
            TextView tvTag, tvName;
            private CharPortraitView portrait;
    
            public ViewHolder(View itemView) {
                super(itemView);
                tvName = itemView.findViewById(R.id.name);
                portrait = itemView.findViewById(R.id.user_img);
            }
        }
        /**
         * 提供给Activity刷新数据
         * @param list
         */
        public void updateList(List<SortModel> list){
            this.mData = list;
            notifyDataSetChanged();
        }
        public Object getItem(int position) {
            return mData.get(position);
        }
        /**
         * 根据ListView的当前位置获取分类的首字母的char ascii值
         */
        public int getSectionForPosition(int position) {
            return mData.get(position).getLetters().charAt(0);
        }
    
        /**
         * 根据分类的首字母的Char ascii值获取其第一次出现该首字母的位置
         */
        public int getPositionForSection(int section) {
            for (int i = 0; i < getItemCount(); i++) {
                String sortStr = mData.get(i).getLetters();
                char firstChar = sortStr.toUpperCase().charAt(0);
                if (firstChar == section) {
                    return i;
                }
            }
            return -1;
        }
    
    }
    
    

    item.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="wrap_content"
        android:orientation="vertical">
    
        <TextView
            android:id="@+id/tag"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:background="#ffffff"
            android:gravity="center_vertical"
            android:paddingLeft="15dp"
            android:text="A"
            android:textColor="#000000" />
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="10dp">
    
            <!--<ImageView
                android:id="@+id/user_img"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/ic_launcher"
                />-->
            <com.example.lastmodel.CharPortraitView
                android:id="@+id/user_img"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:textColor="#ffffff"
                android:layout_centerVertical="true"
                android:padding="5dp"/>
            <TextView
                android:id="@+id/name"
                android:layout_width="match_parent"
                android:layout_height="60dp"
                android:layout_marginLeft="20dp"
                android:layout_centerVertical="true"
                android:layout_toRightOf="@id/user_img"
                android:gravity="center_vertical"
                android:textSize="20sp"
                android:textColor="#000000"
                />
    
            <View
                android:id="@+id/view_lv_item_line"
                android:layout_width="320dp"
                android:layout_height="0.05dp"
                android:layout_below="@+id/name"
                android:layout_alignParentLeft="true"
                android:layout_alignParentEnd="true"
                android:layout_alignParentRight="true"
                android:layout_marginEnd="30dp"
                android:layout_marginRight="30dp"
                android:background="#C0C0C0"
                android:paddingBottom="15dp" />
        </RelativeLayout>
    </LinearLayout>
    
    
    
    
    
    

    SortModel.java

    实体类

    package com.example.lastmodel;
    
    public class SortModel {
        private String telnumber;
        private String name;
        private String letters;//显示拼音的首字母
    
    
    
        public SortModel(String name) {
            this.name = name;
        }
    
        public SortModel(String telnumber, String name) {
            this.telnumber = telnumber;
            this.name = name;
    
        }
    
        public SortModel() {    }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getLetters() {
            return letters;
        }
    
        public void setLetters(String letters) {
            this.letters = letters;
        }
    
        @Override
        public String toString() {
            return "SortModel{" +
                    "name='" + name + '\'' +
                    ", letters='" + letters + '\'' +
                    '}';
        }
    
    }
    
    

    接下来就是资源类的文件了

    drawable下的

    shape.xml

    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle">
        <corners android:radius="20dp"/>
        <stroke android:width="1dp"
            android:color="#bcb8b8"/>
        <size android:width="320dp"
            />
        <solid android:color="#F5F5F5" />
    </shape>
    

    shape_drawable.xml

    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="oval">
        <solid android:color="@android:color/holo_red_light"/>
    
    </shape>
    

    sidebar_background.xml

    <?xml version="1.0" encoding="utf-8"?>
    <shape android:shape="rectangle"
      xmlns:android="http://schemas.android.com/apk/res/android">
        <solid android:color="#ffffff"/>
        <corners
            android:topLeftRadius="8dp"
            android:bottomLeftRadius="8dp"/>
        
    </shape>
    
    

    values下的xml文件

    arrys.xml

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <string-array name="color">
            <item>#FFBBFF</item>
            <item>#A8A8A8</item>
            <item>#EEC591</item>
            <item>#D8BFD8</item>
            <item>#CAE1FF</item>
            <item>#BC8F8F</item>
            <item>#CDB79E</item>
            <item>#EEE8AA</item>
            <item>#C5C1AA</item>
            <item>#C1CDC1</item>
        </string-array>
    
    </resources>
    

    attrs.xml

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <declare-styleable name="CharPortraitView">
            <attr name="back_color" format="reference"/>
            <attr name="random" format="boolean"/>
        </declare-styleable>
    </resources>
    
    
    

    OK,以上就是全部的代码了,有些图片资源我没有附上去,那不太重要,可以自己找几张。仅供大家参考,若有侵权,请联系本人立即删除。

    展开全文
  • 本资源是初学者用于练手的作品可以供初学者参考
  • 利用SQLite数据库 + ListView开发技术,实现了一个简易的通讯录系统,其功能模块包括通讯录信息的增加、删除、修改、查询等。
  • Android StudioAndroid Studio ListView数据适配器实现通讯录设计(头像加名称) 一、ui设计 二、自定义适配器BaseAdapter 三、绑定绑定数据适配器
  • Android 仿通讯录A-Z侧边索引查询 LetterListView androidstudio

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,542
精华内容 1,016
关键字:

android studio通讯录