网络资源模板--基于Android studio 通讯录App

发布于:2025-06-19 ⋅ 阅读:(18) ⋅ 点赞:(0)

目录

一、测试环境说明

二、项目简介

三、项目演示

四、部设计详情(部分)

登录页面

注册页面

通讯录首页

五、项目源码 


一、测试环境说明

二、项目简介

该项目简介来自网络,具体内容需要自行测试

这款基于Android Studio开发的通讯录应用是一款功能完善、界面友好的联系人管理工具。应用采用现代化的设计理念,提供了完整的用户账号体系和数据管理功能。

1. 用户系统:支持账号注册、登录和密码修改,用户数据通过SharedPreferences安全存储。

2. 联系人管理:

   - 支持添加、修改、删除联系人信息

   - 联系人信息包括姓名、性别、多个电话号码、关系类型和备注等

   - 提供详细的表单验证机制确保数据完整性

3. 搜索功能:

   - 强大的联系人搜索功能

   - 实时显示搜索结果数量

   - 支持搜索结果的刷新和取消

4. 数据展示:

   - 联系人列表视图

   - 底部导航栏切换不同功能模块

   - 个人中心显示统计信息

应用采用了Android开发的主流技术架构:

- 使用Fragment实现模块化界面

- 通过SQLite数据库持久化存储联系人数据

- 实现抽屉式导航界面

- 包含完善的表单验证和用户提示系统

- 采用响应式设计,适配不同屏幕尺寸

三、项目演示

网络资源模板--基于Android studio 通讯录App

四、部设计详情(部分)

登录页面

package com.example.myapplication;

import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import com.example.myapplication.databinding.ActivityMainBinding;
import com.example.myapplication.service.SharedPreferencesService;

import java.util.Map;
import java.util.Objects;

public class MainActivity extends AppCompatActivity {

    private ActivityMainBinding mainBinding;
    private Intent intent;
    private boolean isRole = false; //登录的记录是否存在

    /*--start--删除数据库--*/
//    private static final String TAG = "MainActivity";
//    private static final String DATABASE_NAME = "myLogInfo.db";
    /*--end--*/

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mainBinding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(mainBinding.getRoot());

        Map<String, String> userInfo = SharedPreferencesService.getUserInfo(this);
//自动填充已有账号
        if (!userInfo.isEmpty() && !Objects.requireNonNull(userInfo.get("account")).isEmpty()) {
            isRole = true;
            mainBinding.dlZhh.setText(userInfo.get("account"));
            mainBinding.dlMm.setText(userInfo.get("password"));
        }

//登录按钮
        mainBinding.dlAnn.setOnClickListener(view -> {
            String roleName = mainBinding.dlZhh.getText().toString().trim();
            String password = mainBinding.dlMm.getText().toString().trim();
            if (!roleName.isEmpty() && !password.isEmpty()) {
                if (isRole) {
                    if (userInfo.get("account").equals(roleName) && userInfo.get("password").equals(password)) {
                        intent = new Intent(this, MainActivity2PageView.class);
                        startActivity(intent);
                        finish();
//                        startActivityIfNeeded(intent, 1);
                    } else {
                        Toast.makeText(MainActivity.this, "账号或密码错误", Toast.LENGTH_SHORT).show();
                    }
                } else {
                    Toast.makeText(MainActivity.this, "账号不存在", Toast.LENGTH_SHORT).show();
                }
            } else {
                Toast.makeText(MainActivity.this, "账号或密码不能为空", Toast.LENGTH_SHORT).show();
            }

    }

}

采用MVC模式,将数据存取逻辑封装在SP中。登录验证时先检查账号是否存在,再核对密码,最后跳转到主页面。注释中还包含了删除数据库的备用代码段,方便调试时使用。整体实现了基本的用户认证流程。

1. 使用ViewBinding替代findViewById来绑定界面元素

2. 通过SharedPreferences存储和获取用户登录信息

3. 实现了自动填充已保存账号密码的功能

4. 包含登录验证逻辑,检查账号密码是否正确

5. 提供注册账号和修改密码的跳转功能

6. 使用Toast提示用户操作反馈

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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">

    <ImageView
        android:id="@+id/dl_bj"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@drawable/deng_lu"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.0" />

    <de.hdodenhof.circleimageview.CircleImageView
        android:id="@+id/dl_tp"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:src="@drawable/tou_xiang"
        app:layout_constraintBottom_toTopOf="@+id/guideline7"
        app:layout_constraintEnd_toStartOf="@+id/guideline3"
        app:layout_constraintHorizontal_bias="0.462"
        app:layout_constraintStart_toStartOf="@+id/guideline2"
        app:layout_constraintTop_toTopOf="@+id/guideline4" />

    <EditText
        android:id="@+id/dl_zhh"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="@drawable/text_1"
        android:ems="10"
        android:hint="请输入账号"
        android:inputType="textPersonName"
        app:layout_constraintBottom_toTopOf="@+id/dl_mm"
        app:layout_constraintEnd_toStartOf="@+id/guideline3"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="@+id/guideline2"
        app:layout_constraintTop_toTopOf="@+id/guideline7"
        tools:ignore="TouchTargetSizeCheck" />

    <EditText
        android:id="@+id/dl_mm"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:background="@drawable/text_1"
        android:ems="10"
        android:hint="请输入密码"
        android:inputType="textPassword"
        app:layout_constraintBottom_toTopOf="@+id/dl_ann"
        app:layout_constraintEnd_toEndOf="@+id/dl_zhh"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="@+id/dl_zhh"
        app:layout_constraintTop_toBottomOf="@+id/dl_zhh"
        tools:ignore="TouchTargetSizeCheck" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.15" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.85" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.15" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline7"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.48" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.85" />

    <Button
        android:id="@+id/dl_ann"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:background="@drawable/button_1"
        android:text="登 录"
        android:textAllCaps="false"
        android:textSize="18sp"
        app:layout_constraintBottom_toTopOf="@+id/dl_qhzhh"
        app:layout_constraintEnd_toEndOf="@+id/dl_zhh"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="@+id/dl_zhh"
        app:layout_constraintTop_toBottomOf="@+id/dl_mm" />

    <LinearLayout
        android:id="@+id/dl_qhzhh"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="12dp"
        android:orientation="vertical"
        app:layout_constraintBottom_toTopOf="@+id/guideline5"
        app:layout_constraintEnd_toEndOf="@+id/dl_zhh"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="@+id/dl_zhh"
        app:layout_constraintTop_toBottomOf="@+id/dl_ann"
        tools:ignore="MissingConstraints">

    </LinearLayout>

    <TextView
        android:id="@+id/dl_myzhh"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="没有账号?"
        app:layout_constraintBottom_toTopOf="@+id/guideline5"
        app:layout_constraintEnd_toStartOf="@+id/dl_wjmm"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintHorizontal_chainStyle="spread_inside"
        app:layout_constraintStart_toStartOf="@+id/guideline2"
        app:layout_constraintTop_toTopOf="@+id/guideline5" />

    <TextView
        android:id="@+id/dl_wjmm"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="忘记密码?"
        app:layout_constraintBottom_toBottomOf="@+id/dl_myzhh"
        app:layout_constraintEnd_toStartOf="@+id/guideline3"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/dl_myzhh"
        app:layout_constraintTop_toTopOf="@+id/dl_myzhh" />


</androidx.constraintlayout.widget.ConstraintLayout>

注册页面

package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentManager;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.os.Environment;
import android.widget.Toast;

import com.example.myapplication.databinding.ActivityMainZhuCeBinding;
import com.example.myapplication.service.SharedPreferencesService;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Random;

public class MainActivityZhuCe extends AppCompatActivity {

    private ActivityMainZhuCeBinding mainZhuCeBinding;
    private Intent intent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_zhu_ce);

        mainZhuCeBinding = ActivityMainZhuCeBinding.inflate(getLayoutInflater());
        setContentView(mainZhuCeBinding.getRoot());

//注册
        mainZhuCeBinding.zhcAnn.setOnClickListener(view -> {
            String roleName = mainZhuCeBinding.zhcZhh.getText().toString().trim();
            String password = mainZhuCeBinding.zhcMm.getText().toString().trim();
            String password2 = mainZhuCeBinding.zhcMm2.getText().toString().trim();
            if (!(password.length()<6)) {
                if (password.equals(password2)) {
                    boolean isSuccess = SharedPreferencesService.seveUserInfo(MainActivityZhuCe.this, roleName, password);
                    if (isSuccess) {
                        Toast.makeText(MainActivityZhuCe.this, "存储成功", Toast.LENGTH_SHORT).show();
                        intent = new Intent(this, MainActivity2PageView.class);
                        startActivity(intent);
                    } else {
                        Toast.makeText(MainActivityZhuCe.this, "存储失败", Toast.LENGTH_SHORT).show();
                    }
                } else {
                    Toast.makeText(MainActivityZhuCe.this, "密码不一致", Toast.LENGTH_SHORT).show();
                }
            } else {
                Toast.makeText(MainActivityZhuCe.this, "密码长度不少于6位", Toast.LENGTH_SHORT).show();
            }
        });

//已有账号
        mainZhuCeBinding.zhcYyzhh.setOnClickListener(view -> {
            intent = new Intent(this, MainActivity.class);
            startActivity(intent);
            finish();

            /*返回栈操作(未测试)*/
//            // 移除返回栈顶部的Activity
//            FragmentManager fragmentManager = getSupportFragmentManager();
//            fragmentManager.popBackStack();
//            // 移除特定ID的Activity
//            int id = getResources().getIdentifier("my_activity", "id", getPackageName());
//            fragmentManager.popBackStack(id, FragmentManager.POP_BACK_STACK_INCLUSIVE);
        });


    }

    /*————————————————————start——————————————————
     * 借鉴 https://blog.51cto.com/u_16175494/6870299 网址51CTO博客的代码
     * 未使用
     */
    /*private String generateCaptcha() {
        // 生成随机的验证码
        String captcha = generateRandomCaptcha();

        // 将验证码图片保存到本地
        saveCaptchaImage(captcha);

        return captcha;
    }

    private String generateRandomCaptcha() {
        // 随机生成4位验证码
        Random random = new Random();
        StringBuilder captcha = new StringBuilder();
        for (int i = 0; i < 4; i++) {
            captcha.append(random.nextInt(10));
        }
        return captcha.toString();
    }

  
    /*——————————————————end——————————————————*/
}

将用户数据存储逻辑封装在SharedPreferencesService中,实现了基本的用户注册流程验证。注释中还保留了验证码生成和图片保存的参考实现,方便后续功能扩展。整体实现了注册页面的核心功能需求。

1. 用户注册功能:

   - 检查两次输入密码是否一致

   - 验证密码长度是否达到6位以上

   - 通过SharedPreferences存储用户注册信息

   - 注册成功跳转到主页面

2. 界面交互:

   - 使用ViewBinding绑定视图组件

   - 提供"已有账号"按钮返回登录页

   - 使用Toast提示用户操作结果

3. 其他特性:

   - 包含验证码生成功能(注释状态)

   - 尝试实现返回栈管理(注释状态)

通讯录首页

package com.example.myapplication;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import android.app.Fragment;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.TextView;
import android.widget.Toast;

import com.example.myapplication.Bean.ListAdapter;
import com.example.myapplication.Bean.RiJiInfoBean;
import com.example.myapplication.Dao.MySQLiteOpenHelper;
import com.example.myapplication.databinding.Activity2MainShouYeBinding;

import java.util.List;
import java.util.Objects;

public class MainActivityShouYe extends Fragment {

    private Activity2MainShouYeBinding mainShouYeBinding;
    private Intent intent;
    private View view;
    private List<RiJiInfoBean> riJiInfoBeanList;
    private ListAdapter ListAdapter;
    private MySQLiteOpenHelper mySQLiteOpenHelper;
    private boolean isDrawerOpen;   /*抽屉导航,开启为真*/
    private boolean isQuery;    /*查询标识,未查询为假*/

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mainShouYeBinding = Activity2MainShouYeBinding.inflate(inflater,container,false);

        /*保持当前页面布局不被软键盘顶起*/
        getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);

        /*——————————————————————————start——————————————————————————————————*/
        //这个registerForActivityResult方法要写在Activity的onCreate方法里(在Activity创建的时候就要创建出来,不能等到使用的时候再创建,不然会报错LifecycleOwner com.xx.MainActivity@28b4e79 is attempting to register while current state is RESUMED. LifecycleOwners must call register before they are STARTED.)。
      /*  ActivityResultLauncher<Intent> intentActivityResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
                result -> {
                    if (result.getResultCode() == RESULT_OK) {
                        //获取返回的结果
                        String data = result.getData().getStringExtra("test");
                        Toast.makeText(this, data, Toast.LENGTH_SHORT).show();
                    }
                });

        intent = new Intent();
        intent.putExtra("test_name", "test_value");
        intentActivityResultLauncher.launch(intent);*/

        mySQLiteOpenHelper = new MySQLiteOpenHelper(getContext());
        riJiInfoBeanList = mySQLiteOpenHelper.queryAllFromDB(0, null, null);
        mainShouYeBinding = Activity2MainShouYeBinding.inflate(getLayoutInflater());

        ListAdapter = new ListAdapter(riJiInfoBeanList, getContext());
        mainShouYeBinding.shyList.setAdapter(ListAdapter);

        mainShouYeBinding.shyTb.shyReSs.setVisibility(View.VISIBLE);
        mainShouYeBinding.shyTb.shySs.setVisibility(View.VISIBLE);

        /*列表滑动监听*/
        mainShouYeBinding.shyList.setOnScrollListener(new OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView absListView, int i) {

            }

            @Override
            public void onScroll(AbsListView absListView, int i, int i1, int i2) {
                if (i > 1) {
                    mainShouYeBinding.shyFloatGd.setVisibility(View.VISIBLE);
                } else {
                    mainShouYeBinding.shyFloatGd.setVisibility(View.GONE);
                }
            }
        });

        /*返回顶部*/
        mainShouYeBinding.shyFloatGd.setOnClickListener(view -> {
            /*滑动到顶层*/
            mainShouYeBinding.shyList.smoothScrollToPosition(0);
        });

        /*列表点击事件*/
        mainShouYeBinding.shyList.setOnItemClickListener((adapterView, view, i, l) -> {
            RiJiInfoBean riJiInfoBean = riJiInfoBeanList.get(i);
            if (getActivity() != null) {
                intent = new Intent(getActivity(), MainActivity2BianXie.class);
                intent.putExtra("name", riJiInfoBean.getName());
                intent.putExtra("sex", riJiInfoBean.getSex());
                intent.putExtra("phone", riJiInfoBean.getPhone());
                intent.putExtra("phone2", riJiInfoBean.getPhone2());
                intent.putExtra("relation", riJiInfoBean.getRelation());
                intent.putExtra("reText", riJiInfoBean.getReText());
                intent.putExtra("address", riJiInfoBean.getAddress());

                /*修改标识*/
                intent.putExtra("home", "update");
                getActivity().startActivityIfNeeded(intent, 1);
            }
        });

        /*列表长按事件*/
        mainShouYeBinding.shyList.setOnItemLongClickListener((adapterView, view, i, l) -> {
            RiJiInfoBean riJiInfoBean = riJiInfoBeanList.get(i);
            LayoutInflater inflater2 = LayoutInflater.from(getActivity());
            View customView = inflater2.inflate(R.layout.pop_up, null);
            TextView title = customView .findViewById(R.id.up_bt);
            TextView message = customView.findViewById(R.id.up_tsh);
            title.setText("删除提示");
            message.setText("是否删除 "+ riJiInfoBean.getName() +"的信息");
            // 创建一个弹窗构造器
            AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
            builder.setView(customView);

            // 创建并显示弹窗
            AlertDialog dialog = builder.create();
            dialog.show();


            /*弹窗-确认*/
            TextView sure = customView.findViewById(R.id.up_qr);
            sure.setOnClickListener(view1 -> {
                boolean isSuccess = mySQLiteOpenHelper.deleteData(riJiInfoBean);
                if (isSuccess){
                    Toast.makeText(getContext(), "删除成功", Toast.LENGTH_SHORT).show();
                    showQueryData();
                }else {
                    Toast.makeText(getContext(), "删除失败", Toast.LENGTH_SHORT).show();
                }
                dialog.cancel();
            });

            /*弹窗-取消*/
            TextView off = customView.findViewById(R.id.up_qx);
            off.setOnClickListener(view1 -> {
                dialog.cancel();
            });
            return true;
        });

        /*返回*/
        mainShouYeBinding.shyTb.shyFh.setOnClickListener(view -> {
            exitHint();
        });


        /*搜索 -- 打开抽屉*/
        mainShouYeBinding.shyTb.shySs.setOnClickListener(view -> {
            String name = mainShouYeBinding.chxSsk.getText().toString().trim();
            if (name.isEmpty()) {
                mainShouYeBinding.chxQx.setText("关 闭");
            } else {
                mainShouYeBinding.chxQx.setText("清 空");
            }
            mainShouYeBinding.shyZhy.openDrawer(Gravity.RIGHT);
        });

        /*抽屉监听事件*/
        mainShouYeBinding.shyZhy.addDrawerListener(new DrawerLayout.DrawerListener() {
            @Override
            public void onDrawerSlide(@NonNull View drawerView, float slideOffset) {

            }

            @Override
            public void onDrawerOpened(@NonNull View drawerView) {
                isDrawerOpen = true;
            }

            @Override
            public void onDrawerClosed(@NonNull View drawerView) {
                isDrawerOpen = false;
                // 关闭系统键盘
                InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(mainShouYeBinding.chxSsk.getWindowToken(), 0);

                if (!isQuery) {
                    showQueryData();
                    mainShouYeBinding.shyTb.shyFh.setVisibility(View.VISIBLE);
                    mainShouYeBinding.shyTb.shyQk.setVisibility(View.GONE);
                }
            }

            @Override
            public void onDrawerStateChanged(int newState) {

            }
        });

        /*搜索--查询*/
        mainShouYeBinding.chxChx.setOnClickListener(view -> {
            String name = mainShouYeBinding.chxSsk.getText().toString().trim();
            if (!TextUtils.isEmpty(name)) {
                long l = search(name);
                mainShouYeBinding.chxTsh.setText("共搜索出" + l + "条数据");
                if (l > 0) {
                    isQuery = true;
                    mainShouYeBinding.chxTsh.setTextColor(ContextCompat.getColor(getActivity(), R.color.yellow));
                    mainShouYeBinding.shyTb.shyFh.setVisibility(View.GONE);
                    mainShouYeBinding.shyTb.shyQk.setVisibility(View.VISIBLE);
                    mainShouYeBinding.shyZhy.closeDrawers();
                    mainShouYeBinding.chxSsk.clearFocus();
                    // 关闭系统键盘
                    InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
                    imm.hideSoftInputFromWindow(mainShouYeBinding.chxSsk.getWindowToken(), 0);
                } else {
                    isQuery = false;
                    mainShouYeBinding.chxTsh.setTextColor(ContextCompat.getColor(getContext(), R.color.red));
                }
                mainShouYeBinding.shyList.setAdapter(new ListAdapter(riJiInfoBeanList, getContext()));
            }
            mainShouYeBinding.chxQx.setText("关 闭");
        });

        /*刷新搜索*/
        mainShouYeBinding.shyTb.shyReSs.setOnClickListener(view -> {
            if (isQuery) {
                Toast.makeText(getContext(), "刷新成功,共" +
                        search(mainShouYeBinding.chxSsk.getText().toString().trim()) + "条数据", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(getContext(), "刷新成功,共" +
                        showQueryData() + "条数据", Toast.LENGTH_SHORT).show();
            }
        });

        /*取消搜索*/
        mainShouYeBinding.shyTb.shyQk.setOnClickListener(view -> {
            mainShouYeBinding.shyTb.shyFh.setVisibility(View.VISIBLE);
            isQuery = false;
            mainShouYeBinding.chxSsk.setText("");
            mainShouYeBinding.chxTsh.setText("");
            showQueryData();
            mainShouYeBinding.shyTb.shyQk.setVisibility(View.GONE);
        });

        /*无字/有字有查-关闭,有字无查-清空*/
        mainShouYeBinding.chxQx.setOnClickListener(view -> {
            switch (mainShouYeBinding.chxQx.getText().toString().trim().substring(0, 1)) {
                case "关":
                    if (!isQuery) {
                        riJiInfoBeanList = mySQLiteOpenHelper.queryAllFromDB(0, null, null);
                        mainShouYeBinding.shyList.setAdapter(new ListAdapter(riJiInfoBeanList, getContext()));
                    }
                    mainShouYeBinding.shyZhy.closeDrawer(GravityCompat.END);
                    break;
                case "清":
                    mainShouYeBinding.chxSsk.setText("");
                    mainShouYeBinding.chxTsh.setText("");
                    isQuery = false;
                    mainShouYeBinding.chxQx.setText("关 闭");
                    break;
                default:
            }
        });

        /*搜索框监听事件*/
        mainShouYeBinding.chxSsk.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void afterTextChanged(Editable editable) {
                if (!mainShouYeBinding.chxSsk.getText().toString().trim().isEmpty()) {
                    int count = mySQLiteOpenHelper.queryCount(mainShouYeBinding.chxSsk.getText().toString().trim());
                    mainShouYeBinding.chxTsh.setTextColor(ContextCompat.getColor(getContext(), R.color.yellow));
                    if (count > 0) {
                        mainShouYeBinding.chxTsh.setText("已为您搜索出" + count + "条数据");
                    } else {
                        mainShouYeBinding.chxTsh.setText("未能查到数据");
                    }
                    mainShouYeBinding.chxQx.setText("清 空");
                } else {
                    mainShouYeBinding.chxTsh.setText("");
                    mainShouYeBinding.chxQx.setText("关 闭");
                }
            }
        });


        return mainShouYeBinding.getRoot();
    }



    /*退出APP提示*/
    protected void exitHint() {
        LayoutInflater inflater = LayoutInflater.from(getContext());
        View customView = inflater.inflate(R.layout.pop_up, null);
        TextView title = customView.findViewById(R.id.up_bt);
        TextView message = customView.findViewById(R.id.up_tsh);
        title.setText("关闭通讯录提示");
        message.setText("确认要退出通讯录吗?");
        // 创建一个弹窗构造器
        AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
        builder.setView(customView);

        // 创建并显示弹窗
        AlertDialog dialog = builder.create();
        dialog.show();


        /*弹窗-确认*/
        TextView sure = customView.findViewById(R.id.up_qr);
        sure.setOnClickListener(view1 -> {
            getActivity().finish();
        });

        /*弹窗-取消*/
        TextView off = customView.findViewById(R.id.up_qx);
        off.setOnClickListener(view1 -> {
            dialog.cancel();
        });
    }

    /*搜索处理*/
    @SuppressLint("SetTextI18n")
    private long search(String name) {
        riJiInfoBeanList = mySQLiteOpenHelper.queryAllFromDB(1, name, null);
        return riJiInfoBeanList.size();
    }

    /*渲染列表*/
    private long showQueryData() {
        if (riJiInfoBeanList != null) {
            riJiInfoBeanList.clear();
        }
        riJiInfoBeanList = mySQLiteOpenHelper.queryAllFromDB(0, null, null);
        ListAdapter = new ListAdapter(riJiInfoBeanList, getContext());
        mainShouYeBinding.shyList.setAdapter(ListAdapter);
        return riJiInfoBeanList.size();
    }




    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }




    /*public void Load() {
        //title.setText("当前时间:\n" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));

    }*/

    /*在全局区域抽屉监听触摸事件*/
    /*@Override
    public boolean onTouchEvent(MotionEvent event) {
        if (isDrawerOpen && drawerLayout.onTouchEvent(event)) {
            isDrawerOpen = false;
        }
        return super.onTouchEvent(event);
    }*/
}

1. 核心功能:

   - 联系人列表展示与滑动浏览

   - 联系人搜索功能(支持模糊查询)

   - 联系人详情查看与编辑

   - 联系人删除功能(带确认弹窗)

   - 列表快速返回顶部功能

2. 交互设计:

   - 使用DrawerLayout实现右侧抽屉式搜索面板

   - 列表项点击进入编辑界面

   - 列表项长按触发删除操作

   - 智能搜索提示(实时显示匹配结果数)

   - 退出应用确认对话框

3. 技术实现:

   - 采用ViewBinding进行视图绑定

   - 使用SQLite数据库存储联系人数据

   - 自定义ListAdapter适配器渲染列表

   - 监听软键盘和滚动事件优化用户体验

   - 使用TextWatcher实现搜索框实时反馈

4. 其他特性:

   - 保持布局不被软键盘顶起

   - 列表滚动时显示返回顶部按钮

   - 搜索状态标记与管理

   - 提供数据刷新功能

五、项目源码 

👇👇👇👇👇快捷方式👇👇👇👇👇


网站公告

今日签到

点亮在社区的每一天
去签到