基于 Android Studio 仿故宫博物院(馆)App--原创

2024-08-21 13:20

本文主要是介绍基于 Android Studio 仿故宫博物院(馆)App--原创,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一、项目演示

二、开发环境

三、项目简介

四、项目详情

五、项目完整源码


一、项目演示

基于 Android Studio仿故宫博物院(馆)App--原创

二、开发环境

三、项目简介

       该项目隶属于编程乐学团队原创 Android Studio 项目,其中页面素材和布局来自于故宫博物院小程序和故宫展览APP。

        该项目中文注释高达95%,如下图所示部分注释展示:

四、项目详情

1.启动页

这段代码是一个简单的Android应用程序启动活动(Activity),具体功能如下:

1. **延迟进入登录页面:**
   - 在 `onCreate()` 方法中,使用 `Handler` 和 `Runnable` 实现了一个延迟执行的功能,延迟时间为3秒。
   - `runnable` 对象的 `run()` 方法调用了 `tomainActive()` 方法,在延迟结束后启动 `LoginRegisterActivity` 并关闭当前的 `StartActivity`。

2. **计时器功能:**
   - 定义了一个内部类 `TimeCount`,继承自 `CountDownTimer`,用于执行一个四秒的倒计时操作,每隔一秒触发一次。
   - `onFinish()` 方法中,倒计时结束后移除了 `handler` 中的 `runnable` 对象,确保不会在倒计时结束后再次跳转到登录页面。

3. **Activity 生命周期方法:**
   - `onCreate()` 方法中,设置了布局文件 `activity_start.xml` 作为界面显示内容,并启动了延迟执行和计时器。
   - `onDestroy()` 方法中未显示重写,但在 `toMainActive()` 方法中的 `finish()` 方法确保了在跳转完成后关闭当前 Activity。

总体来说,该代码实现了在应用启动后延迟3秒进入登录页面,并在倒计时4秒后取消延迟,确保用户在启动页面停留不超过指定时间后自动跳转到登录页面。

<?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"android:background="@drawable/start"tools:context=".Activity.StartActivity"><Buttonandroid:id="@+id/btn_skip"android:layout_width="70dp"android:layout_height="30dp"android:layout_marginTop="24dp"android:layout_marginEnd="16dp"android:background="@drawable/start_bg"android:text="跳过"android:textColor="#fff"android:textSize="12sp"android:textStyle="bold"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

2.登陆、注册、忘记密码

主要实现了登陆注册找回密码功能,全部使用到SQLite数据库进行操作

   // 定义一个私有方法login,用于处理用户登录逻辑private void login() {// 为btnLogin按钮设置点击事件监听器btnLogin.setOnClickListener(v -> {// 从etMail(可能是一个EditText控件)中获取文本内容,并转换为字符串,赋值给mail变量String mail = etMail.getText().toString();// 从etPassword(可能是一个EditText控件)中获取文本内容,并转换为字符串,赋值给password变量String password = etPassword.getText().toString();// 判断mail或password是否为空if (mail.isEmpty() || password.isEmpty()) {// 如果其中之一为空,则显示一个Toast提示信息“请确保所有内容不为空!”Toast.makeText(this, "请确保所有内容不为空!", Toast.LENGTH_SHORT).show();// 提前返回,不再执行后续代码return;}// 检查RadioButton(rb)是否被选中boolean isRbChecked = rb.isChecked();// 判断RadioButton是否未被选中if (!isRbChecked) {// 如果未被选中,则显示一个Toast提示信息“请勾选同意注册协议!”Toast.makeText(this, "请勾选同意注册协议!", Toast.LENGTH_SHORT).show();// 提前返回,不再执行后续代码return;}// 调用userHelper的validateUser方法验证用户的邮箱和密码是否正确,结果赋值给b变量boolean b = userHelper.validateUser(mail, password);// 判断用户验证是否成功if (b) {// 如果验证成功,则显示一个Toast提示信息“登录成功!”Toast.makeText(this, "登录成功!", Toast.LENGTH_SHORT).show();// 获取SharedPreferences对象,名称为"User",模式为私有模式SharedPreferences sharedPreferences = getSharedPreferences("User", Context.MODE_PRIVATE);// 获取SharedPreferences.Editor对象,用于编辑SharedPreferences数据SharedPreferences.Editor editor = sharedPreferences.edit();// 将邮箱和密码存储到SharedPreferences中editor.putString("mail", mail);editor.putString("password", password);// 提交修改editor.apply();// 结束当前Activityfinish();} else {// 如果验证失败,则显示一个Toast提示信息“登录失败,请重试!”Toast.makeText(this, "登录失败,请重试!", Toast.LENGTH_SHORT).show();// 清空etPassword和etMail的文本内容etPassword.setText("");etMail.setText("");}});}// 定义一个私有方法register,用于处理注册页面的跳转private void register() {// 为tvRegister(可能是一个TextView控件)设置点击事件监听器tvRegister.setOnClickListener(v -> {// 创建一个Intent,用于从当前Activity跳转到RegisterActivityIntent intent = new Intent(LoginActivity.this, RegisterActivity.class);// 启动RegisterActivitystartActivity(intent);});}// 定义一个私有方法back,用于处理返回操作private void back() {// 为imgBack(可能是一个ImageView控件)设置点击事件监听器imgBack.setOnClickListener(v -> {// 结束当前Activityfinish();});}// 定义一个私有方法forgot,用于处理忘记密码页面的跳转private void forgot() {// 为tvForget(可能是一个TextView控件)设置点击事件监听器tvForget.setOnClickListener(v -> {// 创建一个Intent,用于从当前Activity跳转到ForgotPasswordActivityIntent intent = new Intent(LoginActivity.this, ForgotPasswordActivity.class);// 启动ForgotPasswordActivitystartActivity(intent);});}

`LoginActivity` 是一个 Android 应用中的登录界面,提供用户登录、注册和忘记密码功能。主要功能包括:

- **登录处理**:检查用户输入的邮箱和密码是否为空,验证是否勾选了协议,使用 `UserHelper` 验证用户信息,验证成功后保存信息到 `SharedPreferences`。
- **注册和忘记密码跳转**:点击相应的按钮跳转到注册页面或忘记密码页面。
- **返回操作**:点击返回按钮结束当前页面。

该活动在 `onCreate` 方法中初始化视图组件,并设置了相应的点击事件处理。

    private void register() {// 设置注册按钮的点击事件监听器btnRegister.setOnClickListener(v -> {// 获取用户输入的邮箱、用户名和密码String mail = etMail.getText().toString();String name = etName.getText().toString();String password = etPassword.getText().toString();// 检查邮箱、用户名和密码是否为空if (mail.isEmpty() || name.isEmpty() || password.isEmpty()) {// 如果有任何字段为空,显示提示消息Toast.makeText(this, "请确保所有内容不为空!", Toast.LENGTH_SHORT).show();return; // 退出方法}// 检查密码长度是否在6到16个字符之间if (password.length() < 6 || password.length() > 16) {// 如果密码长度不符合要求,显示提示消息Toast.makeText(this, "密码长度应为6到16个字符!", Toast.LENGTH_SHORT).show();return; // 退出方法}// 检查同意注册协议的 RadioButton 是否被选中boolean isRbChecked = rb.isChecked();if (!isRbChecked) {// 如果没有勾选同意注册协议,显示提示消息Toast.makeText(this, "请勾选同意注册协议!", Toast.LENGTH_SHORT).show();return; // 退出方法}// 调用 userHelper 的 addUser 方法注册用户,并获取返回结果boolean b = userHelper.addUser(mail, name, password);if (b) {// 如果注册成功,显示成功消息并关闭当前活动Toast.makeText(this, "注册成功!", Toast.LENGTH_SHORT).show();finish(); // 关闭当前活动} else {// 如果注册失败,显示失败消息,清空输入框内容Toast.makeText(this, "注册失败,请重试!", Toast.LENGTH_SHORT).show();etPassword.setText(""); // 清空密码输入框etMail.setText(""); // 清空邮箱输入框etName.setText(""); // 清空用户名输入框}});}

`register()` 方法用于处理用户注册逻辑。其功能包括:

1. **设置注册按钮点击事件监听器**:当点击注册按钮时,执行以下操作。

2. **获取用户输入**:从输入框中获取用户的邮箱、用户名和密码。

3. **输入验证**:
   - 检查邮箱、用户名和密码是否为空;若为空,显示提示消息。
   - 验证密码长度是否在 6 到 16 个字符之间;若不符合要求,显示提示消息。

4. **协议勾选验证**:检查用户是否勾选了同意注册协议的 `RadioButton`;若未勾选,显示提示消息。

5. **调用注册方法**:
   - 使用 `UserHelper` 的 `addUser()` 方法注册用户,并根据返回结果显示相应的消息。
   - 注册成功则显示成功消息并关闭当前活动。
   - 注册失败则显示失败消息,并清空输入框内容。

这个方法确保用户在注册前填写所有必要的信息,并符合基本的验证要求。

3.用户首页、购票约展览、地图导览

这个项目是一个预约系统的功能实现,主要包括以下几个功能点:

1. **预约按钮点击事件**:
   - 设置预约按钮的点击事件监听器。

2. **日期选择检查**:
   - 获取用户选择的参观日期,并检查是否选择了有效的日期。如果没有选择,弹出提示信息。

3. **时间选择检查**:
   - 获取用户选择的参观时间,并检查是否选择了有效的时间。如果没有选择,弹出提示信息。

4. **订单ID生成**:
   - 生成一个唯一的订单ID,格式为“D”加上当前时间的年月日时分秒。

5. **订单时间记录**:
   - 获取当前时间,并格式化为“yyyy-MM-dd HH:mm:ss”的字符串,记录为订单时间。

6. **票务信息初始化**:
   - 初始化各种票务信息,包括票种、票数和总价,用于后续的数据库插入操作。

7. **票务信息处理**:
   - 遍历适配器中的数据,检查票数,计算每种票的总价,并将相关信息存入对应的 `StringBuilder` 中。

8. **数据库插入操作**:
   - 如果有选择票种,将订单数据(包括用户邮箱、订单ID、订单时间、参观日期、参观时间以及各票种的票数和总价)插入到数据库中,并设置订单状态为“待支付”。

9. **预约成功提示及页面跳转**:
   - 弹出预约成功的提示信息,并跳转到订单页面。

10. **票种选择检查**:
    - 如果没有选择任何票种,弹出提示信息提醒用户选择票种。

 private void reserve() {// 设置预约按钮的点击事件btnReserve.setOnClickListener(v -> {// 获取选择的参观日期String visitDate = selectedDateText.getText().toString();// 检查参观日期是否被选择if (visitDate.equals("点击选择参观日期")) {Toast.makeText(this, "请选择参观日期!", Toast.LENGTH_SHORT).show();return; // 退出方法}// 获取选中的参观时间单选按钮的 IDint selectedId = rb.getCheckedRadioButtonId();// 根据 ID 查找选中的单选按钮RadioButton selectedRadioButton = findViewById(selectedId);// 检查是否选择了参观时间if (selectedRadioButton == null) {Toast.makeText(this, "请选择参观时间", Toast.LENGTH_SHORT).show();return; // 退出方法}// 获取选中的参观时间String visitTime = selectedRadioButton.getText().toString();// 生成订单 IDString orderId = "D" + new SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault()) {{setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); // 设置时区为上海}}.format(new Date());// 获取当前时间作为订单时间String orderTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()) {{setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); // 设置时区为上海}}.format(new Date());// 初始化票务信息boolean hasTickets = false;StringBuilder ticketType1 = new StringBuilder();StringBuilder ticketCount1 = new StringBuilder();StringBuilder totalPrice1 = new StringBuilder();StringBuilder ticketType2 = new StringBuilder();StringBuilder ticketCount2 = new StringBuilder();StringBuilder totalPrice2 = new StringBuilder();StringBuilder ticketType3 = new StringBuilder();StringBuilder ticketCount3 = new StringBuilder();StringBuilder totalPrice3 = new StringBuilder();StringBuilder ticketType4 = new StringBuilder();StringBuilder ticketCount4 = new StringBuilder();StringBuilder totalPrice4 = new StringBuilder();int count = 0; // 票种计数器// 遍历适配器中的数据for (Map<String, String> item : adapter.getData()) {String ticketCountStr = item.get("ticketCount"); // 获取票数int ticketCount = Integer.parseInt(ticketCountStr); // 转换为整数// 检查票数是否大于零if (ticketCount > 0) {hasTickets = true; // 标记有票String ticketType = item.get("ticketLabel"); // 获取票种String totalPrice = calculateTotalPrice(ticketType, ticketCount); // 计算总价count++;// 根据票种计数器,将票务信息保存到相应的 StringBuilder 中if (count == 1) {ticketType1.append(ticketType);ticketCount1.append(ticketCount);totalPrice1.append(totalPrice);} else if (count == 2) {ticketType2.append(ticketType);ticketCount2.append(ticketCount);totalPrice2.append(totalPrice);} else if (count == 3) {ticketType3.append(ticketType);ticketCount3.append(ticketCount);totalPrice3.append(totalPrice);} else if (count == 4) {ticketType4.append(ticketType);ticketCount4.append(ticketCount);totalPrice4.append(totalPrice);}}}// 如果有票if (hasTickets) {// 将订单数据插入到数据库buyHelper.insertOrderData(mail,orderId,orderTime,visitDate,visitTime,ticketType1.toString(),ticketCount1.toString(),totalPrice1.toString(),ticketType2.toString(),ticketCount2.toString(),totalPrice2.toString(),ticketType3.toString(),ticketCount3.toString(),totalPrice3.toString(),ticketType4.toString(),ticketCount4.toString(),totalPrice4.toString(),"待支付" // 设置订单状态为待支付);// 预约成功提示并跳转到订单页面Intent intent = new Intent(BuyActivity.this, OrderActivity.class);Toast.makeText(this, "预约成功!", Toast.LENGTH_SHORT).show();startActivity(intent);} else {// 没有选择票种提示Toast.makeText(this, "请选择需要的票种!", Toast.LENGTH_SHORT).show();}});}

4.游故宫、故宫建筑、故宫建筑详情页、参观须知

该页面可以实现跳转购票约展览、故宫建筑、地图导览页。 

1. **加载 JSON 数据**:调用 `loadJSONFromAsset()` 方法从资产中加载 JSON 数据,并将其存储在 `json` 变量中。如果 JSON 数据不为空,则继续处理。

2. **解析 JSON 数据**:
   - 创建 `Gson` 实例用于解析 JSON 数据。
   - 使用 `TypeToken` 定义 JSON 数据的类型(这里是 `List<UnitBean>`)。`TypeToken` 是 Gson 库中用于处理泛型的工具。
   - 调用 `Gson` 的 `fromJson` 方法,将 JSON 数据解析成 `unitList`(`List<UnitBean>` 类型)。

3. **配置 RecyclerView**:
   - 设置 `RecyclerView` 的布局管理器为 `GridLayoutManager`,并指定列数为 2,意味着 `RecyclerView` 将以网格形式显示数据,每行有 2 列。
   - 创建 `UnitAdapter` 实例并将其与 `RecyclerView` 关联。`UnitAdapter` 负责将 `unitList` 中的数据绑定到 `RecyclerView` 的视图上。

  • collect() 方法处理收藏和取消收藏逻辑,包括对用户进行登录提示。
  • back() 方法处理返回按钮的点击事件。
  • show() 方法负责显示和更新界面内容,包括加载图片和设置文本
  private void show() {// 从资产中加载 JSON 数据String json = loadJSONFromAsset();if (json != null) {// 创建 Gson 实例用于解析 JSONGson gson = new Gson();// 定义用于解析的类型TypeToken<List<UnitBean>> token = new TypeToken<List<UnitBean>>() {};// 解析 JSON 数据并保存到 unitListunitList = gson.fromJson(json, token.getType());// 设置 RecyclerView 的布局管理器为 GridLayoutManager,设置列数为 2rv.setLayoutManager(new GridLayoutManager(this, 2)); // 2 列布局// 初始化适配器并与 RecyclerView 关联adapter = new UnitAdapter(this, unitList);rv.setAdapter(adapter);}}

5.看文物、数字文物库、文物详情页

1. **加载数据**:
   - 从应用的资产目录中读取 JSON 格式的数据文件。

2. **解析数据**:
   - 使用 Gson 库将 JSON 数据解析为 `List<FigureBean>` 对象,以便于在应用中使用。

3. **显示数据**:
   - 使用 `RecyclerView` 组件显示解析后的数据。
   - `RecyclerView` 的布局管理器设置为 `GridLayoutManager`,以 2 列网格的方式展示数据项。
   - 使用自定义适配器 `FigureAdapter` 将数据绑定到 `RecyclerView` 的视图中,以便在界面上展示数据列表。

   // 初始化显示数据的方法private void show() {// 从资产目录中加载 JSON 数据String json = loadJSONFromAsset();// 如果 JSON 数据不为空if (json != null) {// 创建 Gson 对象用于解析 JSON 数据Gson gson = new Gson();// 定义数据类型TypeToken<List<FigureBean>> token = new TypeToken<List<FigureBean>>() {};// 将 JSON 数据解析为 List<FigureBean> 对象,并赋值给 figureListfigureList = gson.fromJson(json, token.getType()); // 保存原始数据到 figureList// 设置 RecyclerView 的布局管理器为 GridLayoutManager,显示为 2 列布局rv.setLayoutManager(new GridLayoutManager(this, 2)); // 2 列布局// 初始化适配器,并将 figureList 传递给适配器adapter = new FigureAdapter(this, figureList);// 设置 RecyclerView 的适配器rv.setAdapter(adapter);}}

1. **设置收藏按钮的点击事件** (`collect` 方法):
   - **检查用户登录状态**:判断用户的 `mail` 是否为空,确保用户已登录。
   - **处理收藏状态**:
     - 如果当前状态是“已收藏”,则执行取消收藏操作:
       - 调用 `collectHelper` 的 `deleteData` 方法删除收藏记录。
       - 根据删除结果,显示相应的提示信息,并更新按钮的文本和图标。
     - 如果当前状态是“收藏”,则执行收藏操作:
       - 调用 `collectHelper` 的 `insertData` 方法插入收藏记录。
       - 根据插入结果,显示相应的提示信息,并更新按钮的文本和图标。

2. **展示收藏状态和相关信息** (`show` 方法):
   - **获取并显示收藏状态**:
     - 从 `collectHelper` 获取收藏记录,检查收藏状态是否为“已收藏”。
     - 根据收藏状态更新 `tvCollect` 的文本和 `imgCollect` 的图标。
   - **加载和显示图片及相关信息**:
     - 使用 Glide 加载 `imgPath` 中的图片并显示在 `img` 组件上。
     - 设置 `tvName`、`tvNum`、`tvCategory` 和 `tvEra` 的文本内容为相应的数据。

 // 定义一个方法 collect(),用于设置收藏按钮的点击事件private void collect() {// 设置 llCollect 的点击事件监听器llCollect.setOnClickListener(v -> {// 检查 mail 是否为空,表示用户是否登录if (mail.isEmpty()) {// 如果 mail 为空,弹出提示框提醒用户先登录Toast.makeText(this, "请先进行登录!", Toast.LENGTH_SHORT).show();} else {// 获取 tvCollect 上的文本内容String s = tvCollect.getText().toString();// 如果文本内容是 "已收藏",则执行取消收藏的操作if (s.equals("已收藏")) {// 调用 collectHelper 的 deleteData 方法,删除收藏记录boolean b = collectHelper.deleteData(mail, name);// 如果删除成功,弹出提示框并更新 UIif (b) {Toast.makeText(this, "已取消收藏!", Toast.LENGTH_SHORT).show();// 更新 tvCollect 的文本为 "收藏"tvCollect.setText("收藏");// 更新 imgCollect 的图片资源为收藏的图标imgCollect.setImageResource(R.drawable.collect);} else {// 如果删除失败,弹出提示框Toast.makeText(this, "取消收藏失败!", Toast.LENGTH_SHORT).show();}} else {// 如果文本内容是 "收藏",则执行收藏的操作// 调用 collectHelper 的 insertData 方法,插入收藏记录boolean collect = collectHelper.insertData(mail, "文物", "已收藏", imgPath, name, num, era, category, "", " ");// 如果插入成功,弹出提示框并更新 UIif (collect) {Toast.makeText(this, "收藏成功!", Toast.LENGTH_SHORT).show();// 更新 tvCollect 的文本为 "已收藏"tvCollect.setText("已收藏");// 更新 imgCollect 的图片资源为已收藏的图标imgCollect.setImageResource(R.drawable.collectd);} else {// 如果插入失败,弹出提示框Toast.makeText(this, "收藏失败!", Toast.LENGTH_SHORT).show();}}}});}// 定义一个方法 show(),用于展示收藏的状态和相关信息private void show() {// 从 collectHelper 获取收藏记录CollectBean collectBean = collectHelper.getCollect(mail, name);// 如果获取到收藏记录if (collectBean != null) {// 判断收藏记录的状态是否为 "已收藏"if (collectBean.getCollect().equals("已收藏")) {// 如果是 "已收藏",更新 UI 显示已收藏状态tvCollect.setText("已收藏");imgCollect.setImageResource(R.drawable.collectd);} else {// 如果不是 "已收藏",更新 UI 显示未收藏状态tvCollect.setText("收藏");imgCollect.setImageResource(R.drawable.collect);}} else {// 如果没有收藏记录,设置默认的未收藏状态tvCollect.setText("收藏");imgCollect.setImageResource(R.drawable.collect);}// 使用 Glide 加载 imgPath 中的图片并设置到 img 组件上Glide.with(this).load(imgPath).into(img);// 设置 tvName、tvNum、tvCategory 和 tvEra 的文本内容tvName.setText(name);tvNum.setText(num);tvCategory.setText(category);tvEra.setText(era);}

6.我的页面、我的收藏、我的订单

1. **TabLayout 设置**:
   - 添加了两个 Tab(选项卡),分别标记为“建筑”和“文物”。
   - 为 TabLayout 设置了选项卡选择监听器,根据用户选择的 Tab 执行不同的方法。

2. **数据加载方法**:
   - `JZData()` 方法:加载与“建筑”相关的数据,创建并设置相应的适配器(`CollectAdapter`),然后调用 `updateUI()` 方法更新界面。
   - `WWData()` 方法:加载与“文物”相关的数据,创建并设置相应的适配器(`FigureAdapter`),然后调用 `updateUI()` 方法更新界面。

3. **UI 更新方法**:
   - `updateUI()` 方法:根据数据列表是否为空来决定如何更新界面。如果数据列表为空,显示提示消息并显示占位视图;如果数据列表不为空,隐藏占位视图并设置 `RecyclerView` 的布局管理器和适配器,显示数据列表。

    private void setupTabLayout() {// 添加 Tabtablayout.addTab(tablayout.newTab().setText("建筑")); // 添加“建筑”Tabtablayout.addTab(tablayout.newTab().setText("文物")); // 添加“文物”Tab// 设置 Tab 选择监听器tablayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {@Overridepublic void onTabSelected(TabLayout.Tab tab) {// 获取被选中的 Tab 的文本String tabText = tab.getText().toString();// 判断选中的 Tab 文本,执行相应方法if (tabText.equals("建筑")) {JZData(); // 如果是“建筑”Tab,调用 JZData 方法} else {WWData(); // 否则,调用 WWData 方法}}@Overridepublic void onTabUnselected(TabLayout.Tab tab) {// 不需要处理此回调,暂时留空}@Overridepublic void onTabReselected(TabLayout.Tab tab) {// 不需要处理此回调,暂时留空}});}private void JZData() {// 获取“建筑”相关的数据List<CollectBean> collectBeans = collectHelper.getJZ(mail, "建筑");// 创建 CollectAdapter 适配器CollectAdapter collectAdapter = new CollectAdapter(this, collectBeans);// 更新 UIupdateUI(collectBeans, collectAdapter, "您还没有收藏!");}private void WWData() {// 获取“文物”相关的数据List<FigureBean> figureBeans = collectHelper.getWW(mail, "文物");// 创建 FigureAdapter 适配器FigureAdapter figureAdapter = new FigureAdapter(this, figureBeans);// 更新 UIupdateUI(figureBeans, figureAdapter, "您还没有收藏!");}private <T> void updateUI(List<T> dataList, RecyclerView.Adapter<?> adapter, String emptyMessage) {// 判断数据列表是否为空if (dataList.isEmpty()) {// 显示提示消息Toast.makeText(this, emptyMessage, Toast.LENGTH_SHORT).show();// 隐藏 RecyclerViewrv.setVisibility(View.GONE);// 显示占位视图tvNoData.setVisibility(View.VISIBLE);} else {// 显示 RecyclerViewrv.setVisibility(View.VISIBLE);// 隐藏占位视图tvNoData.setVisibility(View.GONE);// 设置 RecyclerView 的布局管理器为 GridLayoutManager,横排两个显示rv.setLayoutManager(new GridLayoutManager(this, 2));// 设置 RecyclerView 的适配器rv.setAdapter(adapter);}}

1. **TabLayout 设置**:
   - 添加了三个选项卡:`"全部"`、`"待支付"` 和 `"已支付"`。

2. **选项卡选择监听器**:
   - 当用户选择不同的选项卡时,触发 `onTabSelected` 方法,执行相应的操作:
     - 选择 `"全部"` 选项卡时,调用 `loadData()` 方法来加载所有订单数据。
     - 选择 `"待支付"` 或 `"已支付"` 选项卡时,根据选项卡的文本(状态)从数据库中获取相应状态的订单列表,并将这些订单数据反转,使得最新的订单显示在列表顶部。

3. **订单数据展示**:
   - 为 `"待支付"` 和 `"已支付"` 选项卡加载的数据创建 `OrderAdapter` 实例,并将订单数据传递给适配器,然后设置给 `ListView` 控件,展示订单列表。

**总结功能点**:
- 支持在 TabLayout 中切换不同的订单状态选项卡。
- 根据选中的选项卡加载不同的数据,`"全部"` 选项卡加载所有订单数据,其余选项卡根据订单状态筛选数据。
- 在 `ListView` 中展示订单列表,并确保最新的订单显示在顶部。

private void setupTabLayout() {// 向 TabLayout 添加 "全部" 选项卡tabLayout.addTab(tabLayout.newTab().setText("全部"));// 向 TabLayout 添加 "待支付" 选项卡tabLayout.addTab(tabLayout.newTab().setText("待支付"));// 向 TabLayout 添加 "已支付" 选项卡tabLayout.addTab(tabLayout.newTab().setText("已支付"));// 为 TabLayout 添加选项卡选中监听器tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {@Overridepublic void onTabSelected(TabLayout.Tab tab) {// 获取被选中的选项卡的文本String tabText = tab.getText().toString();// 根据选项卡的文本决定加载哪种数据if (tabText.equals("全部")) {// 如果选中的是 "全部",加载所有订单数据loadData();} else {// 如果选中的是 "待支付" 或 "已支付",根据状态获取订单列表List<OrderBean> orders = dbHelper.getOrdersByStatusAndMail(tabText, mail);// 将订单列表反转,使得最新的订单显示在列表顶部Collections.reverse(orders);// 创建 OrderAdapter 实例,并将订单数据传递给适配器OrderAdapter adapter = new OrderAdapter(OrderActivity.this, orders);// 将适配器设置给 ListView 控件lv.setAdapter(adapter);}}@Overridepublic void onTabUnselected(TabLayout.Tab tab) {// 选项卡未被选中时的操作,可以为空}@Overridepublic void onTabReselected(TabLayout.Tab tab) {// 选项卡被重新选中时的操作,可以为空}});}

7.账户设置、修改密码、修改用户名、退出

这个项目主要实现了用户信息更新功能,包含密码和用户名的修改。具体功能点总结如下:

1. **获取用户信息**:
   - 从 `SharedPreferences` 中获取用户的邮件地址,并将其设置到 `EditText` 控件 `etMail` 中。

2. **根据状态设置视图和按钮事件**:
   - 从 `Intent` 中获取 `state` 参数,根据其值("1" 或 "2")来确定要执行的操作:
     - **状态为 "1"**:调用 `setupPasswordUpdate()` 方法设置密码更新界面的视图和点击事件。
     - **状态为 "2"**:调用 `setupUsernameUpdate()` 方法设置用户名更新界面的视图和点击事件。

3. **密码更新功能** (`setupPasswordUpdate()` 方法):
   - 设置界面控件的提示文本,提示用户输入原密码和新密码。
   - 设置修改按钮的点击事件,执行以下操作:
     - 检查新密码长度是否在 6 到 16 个字符之间。
     - 验证原密码是否正确。如果正确,则尝试更新密码。
     - 更新密码成功后,跳转到主界面,并显示成功消息;失败时,显示失败消息。

4. **用户名更新功能** (`setupUsernameUpdate()` 方法):
   - 设置界面控件的提示文本,提示用户输入原用户名和新用户名。
   - 设置修改按钮的点击事件,执行以下操作:
     - 验证原用户名是否正确。如果正确,则尝试更新用户名。
     - 更新用户名成功后,清空输入框并显示成功消息;失败时,显示失败消息。

**总结**:
- 实现了基于用户状态的动态界面设置,支持密码和用户名的更新。
- 提供了用户输入验证和错误处理机制,以确保数据的正确性和用户体验。

  // 显示方法,根据不同的状态设置视图和按钮点击事件private void show() {// 从SharedPreferences中获取用户的邮件地址SharedPreferences sharedPreferences = getSharedPreferences("User", Context.MODE_PRIVATE);mail = sharedPreferences.getString("mail", "");// 将获取到的邮件地址设置到etMail(一个EditText控件)中etMail.setText(mail);// 获取Intent传递过来的“state”参数String state = getIntent().getStringExtra("state");// 根据“state”的值设置不同的视图和点击事件if (state.equals("1")) {setupPasswordUpdate(); // 如果state为"1",调用设置密码更新的函数} else if (state.equals("2")) {setupUsernameUpdate(); // 如果state为"2",调用设置用户名更新的函数}}// 设置密码更新的相关视图和点击事件private void setupPasswordUpdate() {// 设置原密码和新密码的提示文本tvOld.setText("原密码");etOld.setHint("请输入原密码");tvNew.setText("新密码");etNew.setHint("请输入新密码(6-16个字符)");// 设置修改按钮的点击事件btnModify.setOnClickListener(v -> {String oldPassword = etOld.getText().toString();String newPassword = etNew.getText().toString();// 检查新密码的长度是否在6到16个字符之间if (newPassword.length() < 6 || newPassword.length() > 16) {Toast.makeText(this, "密码长度应为6到16个字符!", Toast.LENGTH_SHORT).show();return;}// 验证原密码是否正确if (userHelper.isUserValid(mail, oldPassword)) {// 更新密码if (userHelper.updateUserPasswordByEmail(mail, newPassword)) {showToast("更新成功");navigateToMainActivity("3"); // 密码更新成功后,跳转到主界面} else {showToast("更新失败");}} else {showToast("原密码错误!");}});}// 设置用户名更新的相关视图和点击事件private void setupUsernameUpdate() {// 设置原用户名和新用户名的提示文本tvOld.setText("原用户名");etOld.setHint("请输入原用户名");tvNew.setText("新用户名");etNew.setHint("请输入新用户名");// 设置修改按钮的点击事件btnModify.setOnClickListener(v -> {String oldUsername = etOld.getText().toString();String newUsername = etNew.getText().toString();// 验证原用户名是否正确if (userHelper.isUserValidByEmailAndUsername(mail, oldUsername)) {// 更新用户名if (userHelper.updateUsernameByEmail(mail, newUsername)) {showToast("更新成功");etOld.setText(""); // 清空输入框etNew.setText("");} else {showToast("更新失败");}} else {showToast("原用户名错误!");}});}

五、项目完整源码

👇👇👇👇👇快捷获取方式👇👇👇👇👇

这篇关于基于 Android Studio 仿故宫博物院(馆)App--原创的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1093279

相关文章

Android实现打开本地pdf文件的两种方式

《Android实现打开本地pdf文件的两种方式》在现代应用中,PDF格式因其跨平台、稳定性好、展示内容一致等特点,在Android平台上,如何高效地打开本地PDF文件,不仅关系到用户体验,也直接影响... 目录一、项目概述二、相关知识2.1 PDF文件基本概述2.2 android 文件访问与存储权限2.

Android Studio 配置国内镜像源的实现步骤

《AndroidStudio配置国内镜像源的实现步骤》本文主要介绍了AndroidStudio配置国内镜像源的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、修改 hosts,解决 SDK 下载失败的问题二、修改 gradle 地址,解决 gradle

在Android平台上实现消息推送功能

《在Android平台上实现消息推送功能》随着移动互联网应用的飞速发展,消息推送已成为移动应用中不可或缺的功能,在Android平台上,实现消息推送涉及到服务端的消息发送、客户端的消息接收、通知渠道(... 目录一、项目概述二、相关知识介绍2.1 消息推送的基本原理2.2 Firebase Cloud Me

Android中Dialog的使用详解

《Android中Dialog的使用详解》Dialog(对话框)是Android中常用的UI组件,用于临时显示重要信息或获取用户输入,本文给大家介绍Android中Dialog的使用,感兴趣的朋友一起... 目录android中Dialog的使用详解1. 基本Dialog类型1.1 AlertDialog(

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda

Android自定义Scrollbar的两种实现方式

《Android自定义Scrollbar的两种实现方式》本文介绍两种实现自定义滚动条的方法,分别通过ItemDecoration方案和独立View方案实现滚动条定制化,文章通过代码示例讲解的非常详细,... 目录方案一:ItemDecoration实现(推荐用于RecyclerView)实现原理完整代码实现

Android App安装列表获取方法(实践方案)

《AndroidApp安装列表获取方法(实践方案)》文章介绍了Android11及以上版本获取应用列表的方案调整,包括权限配置、白名单配置和action配置三种方式,并提供了相应的Java和Kotl... 目录前言实现方案         方案概述一、 androidManifest 三种配置方式

Android WebView无法加载H5页面的常见问题和解决方法

《AndroidWebView无法加载H5页面的常见问题和解决方法》AndroidWebView是一种视图组件,使得Android应用能够显示网页内容,它基于Chromium,具备现代浏览器的许多功... 目录1. WebView 简介2. 常见问题3. 网络权限设置4. 启用 JavaScript5. D

Android如何获取当前CPU频率和占用率

《Android如何获取当前CPU频率和占用率》最近在优化App的性能,需要获取当前CPU视频频率和占用率,所以本文小编就来和大家总结一下如何在Android中获取当前CPU频率和占用率吧... 最近在优化 App 的性能,需要获取当前 CPU视频频率和占用率,通过查询资料,大致思路如下:目前没有标准的

Android开发中gradle下载缓慢的问题级解决方法

《Android开发中gradle下载缓慢的问题级解决方法》本文介绍了解决Android开发中Gradle下载缓慢问题的几种方法,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、网络环境优化二、Gradle版本与配置优化三、其他优化措施针对android开发中Gradle下载缓慢的问