【愚公系列】《Android应用案例开发大全》016-LBS类应用掌上杭州(辅助工具类的开发)

💎【行业认证·权威头衔】

✔ 华为云天团核心成员:特约编辑/云享专家/开发者专家/产品云测专家

✔ 开发者社区全满贯:CSDN博客&商业化双料专家/阿里云签约作者/腾讯云内容共创官/掘金&亚马逊&51CTO顶级博主

✔ 技术生态共建先锋:横跨鸿蒙、云计算、AI等前沿领域的技术布道者

🏆【荣誉殿堂】

🎖 连续三年蝉联"华为云十佳博主"(2022-2024)

🎖 双冠加冕CSDN"年度博客之星TOP2"(2022&2023)

🎖 十余个技术社区年度杰出贡献奖得主

📚【知识宝库】

覆盖全栈技术矩阵:

◾ 编程语言:.NET/Java/Python/Go/Node...

◾ 移动生态:HarmonyOS/iOS/Android/小程序

◾ 前沿领域:物联网/网络安全/大数据/AI/元宇宙

◾ 游戏开发:Unity3D引擎深度解析

文章目录


🚀前言

本章将介绍的是Android应用程序掌上杭州的开发。掌上杭州主要有首页、搜索、设置3大主项,其中首页包含美食、景点、住宿、医疗、娱乐、购物,设置中包含了设置字体、关于和帮助,搜索中可方便地搜索当前应用中的信息。接下来将对掌上杭州进行详细的介绍。

🚀一、辅助工具类的开发

前面已经介绍了掌上杭州功能的预览以及总体架构,下面将介绍项目所需要的工具类。工具类被项目其他 Java 文件多次调用,避免重复性开发,同时提高了程序的可维护性,可谓是一劳永逸。工具类在这个项目中十分常用,请读者仔细阅读。

🔎1.常量类的开发

本小节将向读者介绍掌上杭州中的常量类 Constant 的开发。软件内有许多地方需要重复调用的常量,为了避免重复在 Java 文件中定义常量,于是我们将多处需要的常量放在了 Constant.java 文件中方便开发者的管理和修改,其具体代码如下所示。

代码位置 :见随书源代码/第3章/HangZhou/app/src/main/java/com/cn/util 目录下的 Constant.java

java 复制代码
package com.cn.util;

public class Constant {
    public static final String ADD_PRE = "/sdcard/zshz/";           // 文件路径
    public static final int WAIT_DIALOG_REPAINT = 0;                // 等待对话框刷新消息编号
    public static final int WAIT_DIALOG = 0;                        // 等待对话框编号
    public static final int INFO_MYSQL = 1;                         // 编号
    public static int TEXT_SIZE = 16;                               // 文字的大小
    public static String snzy = "zhongn";                           // 中文文本
    public static int COLOR = R.color.black;                        // 字体颜色
    public static final int PHOTOHRAPH = 1;                         // 拍照调用系统照相机时使用
    public static Location myLocation;                              // 游客当前的经纬度位置
    public static final int SHOWMOREDIALOG = 1;                     // 显示更多对话框
    public static final int EXIT_DIALOG = 2;                        // 询问是否退出对话框
    public static String curSMP = null;                             // 记录当前正在播报的景点名
    public static String curScenicId = null;                        // 记录当前显示景点的编号
    public static final int DISTANCE_SCENIC = 200;                  // 景点范围的阈值
    public static final int DISTANCE_USER = 100;                    // 用户移动范围的阈值
    public static final double EARTH_RADIUS = 6378137.0;            // 地球半径
}

说明:常量类的开发是高效完成项目的一项十分必要的准备工作,这样可以避免在不同的 Java 文件中定义常量的重复性工作,提高了代码的可维护性。如果读者在下面的类或方法中有不明白具体含义的常量,可以在本类中查找。

🔎2.图片获取类的开发

上一小节中介绍了掌上杭州常量类的开发,本小节将介绍图片获取类的开发。软件中需要加载大量的图片,于是我们开发了从 SD 卡中加载指定的图片的 BitmapIOUtil 类。BitmapIOUtil 类供其他 Java 文件调用,提高了程序的可读性和可维护性,具体代码如下。

代码位置 :见随书源代码/第3章/HangZhou/app/src/main/java/com/cn/util 目录下的 BitmapIOUtil.java

java 复制代码
package com.cn.util;

// 此处省略了本类中导入类的代码,读者可自行查阅随书的源代码

public class BitmapIOUtil {          // 图片获取类
    static Bitmap bp = null;         // Bitmap对象

    public static Bitmap getSBitmap(String subPath) {
        String path = Constant.ADD_PRE + subPath;   // 获取路径字符串
        try {
            bp = BitmapFactory.decodeFile(path);    // 实例化Bitmap
        } catch (Exception e) {
            System.out.println("出现异常!");        // 打印字符串
        }
        return bp;                                   // 返回Bitmap对象
    }
}

说明 :上述代码表示利用 BitmapFactory 类的 decodeFile(String path) 方法来加载指定路径的位图,显示原图。path 表示要解码的文件路径名的完整路径名,最后返回获得的解码的位图。如果指定的文件名称 pathnull,则不能被解码成位图,该函数返回 null

🔎3.解压文件类的开发

上一小节中介绍了图片获取类的开发,本小节将继续给大家介绍本应用的第 3 个工具类 ZipUtil,该类为解压文件类。程序在初次运行时将调用该类,用于将 HangZhou/assets 中的 .zip 文件解压到 SD 卡中供程序中获取资源使用,具体代码如下。

代码位置 :见随书源代码/第3章/HangZhou/app/src/main/java/com/cn/util 目录下的 ZipUtil.java

java 复制代码
package com.cn.util;

// 此处省略了导入类的代码,读者可自行查阅随书的源代码

public class ZipUtil {
    // 解压.zip压缩文件方法
    public static void unZip(Context context, String assetName, String outputDirectory) throws IOException {
        File file = new File(outputDirectory);          // 创建解压目标目录
        if (!file.exists()) {                           // 如果目标目录不存在,则创建
            file.mkdirs();                              // 创建目录
        }

        InputStream inputStream = null;
        inputStream = context.getAssets().open(assetName);  // 打开压缩文件
        ZipInputStream zipInputStream = new ZipInputStream(inputStream);
        ZipEntry zipEntry = zipInputStream.getNextEntry();  // 读取一个条目

        byte[] buffer = new byte[1024 * 1024];          // 使用1M buffer
        int count = 0;                                  // 解压时字节计数

        while (zipEntry != null) {                      // 如果条目为空说明已经遍历完所有压缩包中文件和目录
            // 如果是一个目录
            if (zipEntry.isDirectory()) {
                file = new File(outputDirectory + File.separator + zipEntry.getName());
                file.mkdir();                           // 创建文件
            } else {                                    // 如果是文件
                file = new File(outputDirectory + File.separator + zipEntry.getName());
                file.createNewFile();                   // 创建该文件
                FileOutputStream fileOutputStream = new FileOutputStream(file);
                while ((count = zipInputStream.read(buffer)) > 0) {
                    fileOutputStream.write(buffer, 0, count);
                }
                fileOutputStream.close();               // 关闭文件输出流
            }
            zipEntry = zipInputStream.getNextEntry();   // 定位到下一个文件入口
        }
        zipInputStream.close();                         // 关闭流
    }
}
  • 第6~9行:用于创建解压目标目录,并且判断目标目录是否存在,不存在则创建。
  • 第11~13行 :用于打开压缩文件,创建 ZipInputStream 对象,并读取 .zip 文件中的内容。
  • 第14~15行:用于设置读取文本的 Byte 值和解压时字节计数。
  • 第16~30行:用于判断进入点是否为空,若为空,说明已经遍历完所有压缩包中文件和目录,则开始进行解压文本文件。
  • 第31行 :用于关闭 ZipInputStream 流。

🔎4.读取文件类的开发

上一小节中介绍了解压文件类的开发,本小节将继续介绍本应用的第 4 个工具类 PubMethod,该类为读取文件类。该类在程序中将多次被调用,用于获取各个界面中所需要的文本信息,极大地提高了程序的可读性和可维护性,具体实现代码如下。

代码位置 :见随书源代码/第3章/HangZhou/app/src/main/java/com/cn/util 目录下的 PubMethod.java

java 复制代码
package com.cn.util;   // 声明包

// 此处省略了导入类的代码,读者可自行查阅随书的源代码

public class PubMethod {
    Activity activity;   // 创建Activity对象

    // 无参构造器
    public PubMethod() {
    }

    public PubMethod(Activity activity) {
        this.activity = activity;   // 赋值
    }

    // 获取文件信息
    public String loadFromFile(String fileName) {
        String result = null;
        try {
            File file = new File(Constant.ADD_PRE + fileName);   // 创建File类对象
            int length = (int) file.length();                     // 获取文件长度
            byte[] buff = new byte[length];                       // 创建byte数组

            FileInputStream fin = new FileInputStream(file);      // 创建FileInputStream流对象
            fin.read(buff);                                       // 读取文本文件
            fin.close();                                          // 关闭文件流

            result = new String(buff, "UTF-8");                   // 文本字体设置为汉字
            result = result.replaceAll("\\r\\n", "\n");           // 替换转行字符
        } catch (Exception e) {                                   // 捕获异常
            Toast.makeText(activity, "对不起,没有找到该文件!", Toast.LENGTH_SHORT).show();
        }
        return result;                                            // 返回数据
    }
}
  • 第6~8行 :为构造函数,用于获得 Activity 对象。
  • 第12~14行:用于打开文本文件,获得文本文件的长度,设置读取文本的 Byte 数组值。
  • 第15~17行 :创建 FileInputStream 对象,并读取文本文件,读完文本文件后则关闭文件流。
  • 第18~19行 :用于将字体转换成汉字,并且将 \r\n 换成 \n
  • 第21~22行:提示用户该文件不存在。

🔎5.自定义字体类的开发

上一小节中介绍了读取文件类的开发,本小节将继续介绍本应用中用到的第 5 个工具类 FontManager,该类为自定义字体类。该类在程序中多次被调用,用来将各个界面中的字体设置为各种用户所需的字体,使界面更具艺术性,具体实现代码如下。

代码位置 :见随书源代码/第3章/HangZhou/app/src/main/java/com/cn/util 目录下的 FontManager.java

java 复制代码
package com.cn.util;   // 声明包

// 此处省略了导入类的代码,读者可自行查阅随书的源代码

public class FontManager {
    public static Typeface tf = null;   // 声明字体变量

    // 初始化字体
    public static void init(Activity act, String xx) {
        if (tf == null) {
            tf = Typeface.createFromAsset(act.getAssets(), "fonts/kaiti.ttf");
        } else {
            if (xx.equals("kaiti")) {
                // 设置楷体
            }
            // 此处省略了字体的多种类型,读者可自行查阅随书的源代码
        }
    }

    // 转换字体
    public static void changeFonts(ViewGroup root, Activity act) {
        for (int i = 0; i < root.getChildCount(); i++) {
            View v = root.getChildAt(i);                // 获取控件
            if (v instanceof TextView) {
                ((TextView) v).setTypeface(tf);         // 转换TextView控件中的字体
            } else if (v instanceof Button) {
                ((Button) v).setTypeface(tf);           // 转换Button控件中的字体
            } else if (v instanceof EditText) {
                ((EditText) v).setTypeface(tf);         // 转换EditText控件中的字体
            } else if (v instanceof ViewGroup) {
                changeFonts((ViewGroup) v, act);        // 重新调用changeFonts()方法
            }
        }
    }

    // 获取控件的方法
    public static ViewGroup getContentView(Activity act) {
        ViewGroup systemContent = (ViewGroup) act.getWindow().getDecorView().findViewById(android.R.id.content);  // 创建ViewGroup
        ViewGroup content = null;
        if (systemContent.getChildCount() > 0 && systemContent.getChildAt(0) instanceof ViewGroup) {
            content = (ViewGroup) systemContent.getChildAt(0);   // 给content赋值
        }
        return content;   // 返回获取的控件
    }
}
  • 第3~14行 :初始化 Typeface。第一次调用 FontManager 类时,调用 init() 方法,若 Typeface 为空,则创建 Typeface 对象。
  • 第15~26行:用于转换界面中的字体。用循环遍历界面中的各个控件,并将控件中的所有字体转换为卡通字体。
  • 第27~36行 :用于获得传过来的 Activity,若该 Activity 的内容大于 0 并且其中的控件属于 ViewGroup,则获取该控件并返回。
相关推荐
CodeSheep1 小时前
又一个华为天才少年,离职了!
前端·后端·程序员
kyriewen1 小时前
面试官说"打开你的AI工具"——我才发现,他考的根本不是写代码
前端·人工智能·面试
g10565591392 小时前
LAMP博客平台Wordpress实战
android·mysql·nginx·php
IT_陈寒2 小时前
Vue的双向绑定把我坑惨了,原来这个场景不能用
前端·人工智能·后端
hunterandroid3 小时前
[Android 从零到一] Compose LazyColumn 性能优化:key、稳定性与重组治理
android·前端
pengyu3 小时前
【Kotlin 协程修仙录 · 元婴境 · 中阶】 | 操作符真解:Flow 中间操作符与数据流变幻术
android·kotlin
lichenyang4533 小时前
从一次团队邀请开始:用 React、NestJS 与 Socket.IO 做可靠的实时通知
前端
vtian3 小时前
一篇文章吃透 Monorepo:pnpm + Turborepo + Changesets 全流程实战(含 8 个踩坑)
前端
默_笙3 小时前
❗ 点击计数按钮,为什么"峨眉队"也跟着重新渲染?React.memo 说:我记住了
前端·javascript