Android Fragment 实现对蓝牙设备的参数配置页面

更新日期: 2023-08-25 阅读次数: 1156 字数: 592 分类: Android

新建 fragment

新建一个 Blank Fragment。会自动创建对应的 layout xml 文件,但是 binding 需要自己手写。

layout binding

package com.sunzhongwei.ble.settings

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.sunzhongwei.ble.databinding.FragmentSettingsBinding


class SettingsFragment : Fragment() {
    private var _binding: FragmentSettingsBinding? = null
    private val binding get() = _binding!!

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentSettingsBinding.inflate(inflater, container, false)
        return return binding.root
    }

}

增加 navigation 配置

app/src/main/res/navigation/mobile_navigation.xml

<fragment
        android:id="@+id/nav_settings"
        android:name="com.sunzhongwei.ble.settings.SettingsFragment"
        android:label="参数设置"
        tools:layout="@layout/fragment_settings"></fragment>

点击图标跳转进入

binding.topBar.settingIcon.setOnClickListener {
	(activity as MainActivity).navController.navigate(R.id.nav_settings)
}

添加一个编辑框小试牛刀

顺便将 layout/fragment_settings.xml 改成 LinearLayout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="10dp"
    android:orientation="vertical"
    tools:context=".SettingsFragment">

    <com.google.android.material.textfield.TextInputLayout
        android:id="@+id/time"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="执行时间"
        app:suffixText="分钟"
        android:maxLines="1">

        <com.google.android.material.textfield.TextInputEditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="number" />

    </com.google.android.material.textfield.TextInputLayout>

</LinearLayout>

注意这里使用了 material design 的组件,需要确保以下配置:

build.gradle

implementation 'com.google.android.material:material:1.7.0'

app/src/main/res/values/themes.xml

<!--
    <style name="Theme.Test" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
-->

<style name="Theme.Test" parent="Theme.Material3.DayNight.NoActionBar">

获取配置

这里分两大类配置

  • 从 SharedPreferences 获取的配置
  • 从蓝牙设备获取的配置

从 SharedPreferences 获取的配置

binding.mac.editText?.setText(getCacheDeviceMac())

从蓝牙设备获取的配置

这个就相对复杂一点。

复杂的原因是,有一个全局的 ViewModel 在每秒发送一次查询请求。 返回的数据中,包含了所有配置项的信息。

如果通过 livedata 监听每个配置项的值,会出现编辑过程中,值被覆盖的情况。

解决方案:

  • 初始化时,监听一次配置项的值;
  • 或者一直监听值的变化,只在编辑具体项目时,不更新 edit text 的值
  • focus 时,弹个对话框出来,里面包含一个输入框,输入新值,提交。这样就不需要担心 edit text 值被刷新的情况了。而且实现也简单 (最终我用了这个方案)

配置项过多时

在 EditText 控件外层再套一层 ScrollView,由于 ScrollView 内只能有一个元素,所以增加一个 LinearLayout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="10dp"
    android:orientation="vertical"
    tools:context=".ui.settings.SettingsFragment">

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

			... 多个输入框

效果图

Android 蓝牙参数配置页

Android 蓝牙参数配置页弹窗

界面布局优化

为了有效利用界面的空间,可以考虑一行展示多个输入框,例如

  • 相关的设置项放在一行。高低阈值
  • 重要的配置项放在前面

微信关注我哦 👍

大象工具微信公众号

我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式