前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >安卓软件开发:用Java和Kotlin构建MDC-UI框架实现LoginUI(基础)

安卓软件开发:用Java和Kotlin构建MDC-UI框架实现LoginUI(基础)

原创
作者头像
Nimyears
修改2024-09-14 17:10:32
4150
修改2024-09-14 17:10:32

一、项目背景

Material Components (MDC) 是Google的工程师和用户体验设计团队打造的一套UI组件库,为了方便帮助开发者实现Material Design风格。MDC提供了多种精美和实用的界面组件,让开发者快速构建现代化的应用界面。在本项目中,利用MDC框架实现一个登录页面,详细展示开发过程中的技术细节和遇到的问题。

1.1 项目需求分析

登录页面的基本结构:

  • 两个文本字段:用于输入用户名和密码。
  • 两个按钮:分别为“Cancel”按钮和“Next”按钮。
  • 应用Logo:显示Shrine的徽标图片。

二、项目开发过程

2.1 添加项目依赖项

代码语言:graphql
复制
api 'com.google.android.material:material:1.1.0-alpha06'

dependencies {
    api 'com.google.android.material:material:1.1.0-alpha06'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'com.android.volley:volley:1.1.1'
    implementation 'com.google.code.gson:gson:2.8.5'
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.21"
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:core:1.1.0'
    androidTestImplementation 'androidx.test.ext:junit:1.1.0'
    androidTestImplementation 'androidx.test:runner:1.2.0-alpha05'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0-alpha05'
}

2.2运行Gradle

依赖项添加完成后,运行Gradle任务下载所有依赖包,工作做好准备,接下来开始开发

2.3 添加XML布局文件

nim_login_fragment.xml文件中,使用MDC的TextInputLayoutTextInputEditText创建用户名和密码输入的字段:

代码语言:xml
复制
<com.google.android.material.textfield.TextInputLayout
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:layout_margin="4dp"
   android:hint="@string/shr_hint_username">

   <com.google.android.material.textfield.TextInputEditText
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:inputType="text"
       android:maxLines="1" />
</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.textfield.TextInputLayout
   android:id="@+id/password_tv_input"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:layout_margin="4dp"
   android:hint="@string/shr_hint_password">

   <com.google.android.material.textfield.TextInputEditText
       android:id="@+id/password_edit_tv"
       android:layout_width="match_parent"
       android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>

在字符串资源包创建名称:

代码语言:xml
复制
...
<string name="shr_hint_username">Username</string>
<string name="shr_hint_password">Password</string>
...

2.4 添加输入验证功能

TextInputLayout 主要功能是错误反馈,代码业务逻辑实现错误提示,设置密码字段类型为“textPassword”:

代码语言:xml
复制
<com.google.android.material.textfield.TextInputLayout
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:layout_margin="4dp"
   android:hint="@string/hint_username">

   <com.google.android.material.textfield.TextInputEditText
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:inputType="text"
       android:maxLines="1" />
</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.textfield.TextInputLayout
   android:id="@+id/password_tv_input"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:layout_margin="4dp"
   android:hint="@string/hint_password"
   app:errorEnabled="true">

   <com.google.android.material.textfield.TextInputEditText
       android:id="@+id/password_edit_tv"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:inputType="textPassword"/>
</com.google.android.material.textfield.TextInputLayout>

2.5 添加按钮XML

在XML布局文件中,添加“Cancel”和“Next”按钮,操作登录功能:

代码语言:xml
复制
<RelativeLayout
   android:layout_width="match_parent"
   android:layout_height="wrap_content">

   <com.google.android.material.button.MaterialButton
       android:id="@+id/next_btn"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_alignParentEnd="true"
       android:layout_alignParentRight="true"
       android:text="@string/btn_next" />

   <com.google.android.material.button.MaterialButton
       android:id="@+id/cancel_btn"
       style="@style/Widget.MaterialComponents.Button.TextButton"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_marginEnd="12dp"
       android:layout_marginRight="12dp"
       android:layout_toStartOf="@id/next_btn"
       android:layout_toLeftOf="@id/next_btn"
       android:text="@string/btn_cancel" />

</RelativeLayout>

2.6 实现导航到下一个fragment

这段代码中实现密码有效性验证方法,设置按钮点击事件监听器:

实现核心业务逻辑

确保密码长度至少8个字符以上

代码语言:java
复制
private boolean isPasswordValid(@Nullable Editable tv) {
   return tv != null && tv.length() >= 8;
}
实现功能
  • onCreateView() 方法中初始化布局和控件。
  • 添加“Next”按钮的点击监听器,根据isPasswordValid() 方法实现密码验证。
  • 当验证通过时,清除错误信息和导航到下一个Fragment。
  • 为密码输入框添加键盘事件监听器,实时清除错误状态。
代码语言:java
复制
@Override
public View onCreateView(
       @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    // 加载布局文件
    View v = inflater.inflate(R.layout.nim_login_fragment, container, false);
   
   // 获取布局中的控件
   final TvInputLayout passwordTvInput = v.findViewById(R.id.password_tv_input);
   final TvInputEditTv passwordEditTv = v.findViewById(R.id.password_edit_tv);
   MaterialButton nextBtn = v.findViewById(R.id.next_btn);

   nextBtn .setOnClickListener(new View.OnClickListener() {
       @Override
       public void onClick(View view) {
           //检查密码是不是有效
           if (!isPasswordValid(passwordEditTv.getText())) {
               passwordTvInput.setError(getString(R.string.error_password));
           } else {
               // 清除错误信息
               passwordTvInput.setError(null); 
               
               navigateToProductGrid();
           }
       }
   });

   passwordEditTv.setOnKeyListener(new View.OnKeyListener() {
       @Override
       public boolean onKey(View view, int i, KeyEvent keyEvent) {
           if (isPasswordValid(passwordEditTv.getText())) {
               passwordTvInput.setError(null);
           }
           return false;
       }
   });
   return view;
}            



 //导航到下一个 Fragment
private void navigateToProductGrid() {
    ((NavigationHost) getActivity()).navigateTo(new ProductGridFragment(), false);
}

三、分析技术难点

3.1 MDC组件的兼容性和版本管理

  • 难点:MDC是Google官方提供的组件库,版本经常更新,不同版本之间存在很多不兼容性的问题,特别是和其他库(如 AndroidXKotlin 扩展)混合使用。
  • 解决方法:需要仔细检查 MDC 版本和项目中其他库的兼容性,尽量使用稳定版;别忘了要提醒,定期查看更新日志,多了解新版本带来的改变和修复。

3.2 Fragment导航和状态管理

  • 难点:Fragment 导航过程中需要输入的状态和避免重复创建 Fragment 实例。错误的导航实现导致应用崩溃或导航异常。
  • 解决方法:通过 NavigationHostNavController 等方式实现 Fragment 的导航管理,保证界面跳转的流畅性。可以使用 ViewModel 保存用户输入的状态,在 Fragment 之间共享数据。

3.3 输入验证与用户体验

  • 难点:实现用户输入验证时,需要保证错误提示的实时性和准确性。需要多考虑边缘情况,比如密码为空、快速输入时的延迟反应。
  • 解决方法:通过 setOnKeyListener 实时监听用户输入,结合 MDC 的错误提示功能 (errorEnabled) 动态更新错误状态。

3.4 混合语言开发(Java、Kotlin)

  • 难点:在项目中使用 Kotlin 和 Java 混合开发时,经常会遇到很多语言互操作性的问题,如 Kotlin 的空安全和Java传统空指针处理的冲突。
  • 解决方法:在 Kotlin中要考虑是不是合适用空安全操作符(如 ?.!!),利用 Kotlin 的语言特性简化代码逻辑。

3.5 UI 组件和业务逻辑的解耦

  • 难点:MDC 提供的 UI 组件功能强大,但在项目中容易出现业务逻辑和 UI 代码混杂的问题,影响代码的可读性和维护性。
  • 解决方法:用 ViewModelLiveData业务逻辑与 UI 逻辑分离,通过观察者模式实现界面和数据的同步。

四、学习笔记

在开发过程中,积累了MDC框架技术的学习心得:

4.1.Material Components (MDC)
  • 深入学习了MDC组件如TextInputLayoutMaterialButtonSnackbar等,掌握了通过属性实现复杂的界面布局。
  • 了解了MDC通过设计系统统一界面风格,提升了项目的整体一致性。

4.2Kotlin和Java混合开发

通过学习Kotlin的简洁语法,如letapply等,让我们看一下Kotlin代码完整代码所示

代码语言:java
复制

    override fun onCreateView (
        @NonNull inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.nim_login_fragment, container, false)

        val passwordTvInput = view.findViewById<TextInputLayout>(R.id.password_tv_input)
        val passwordEditTv = view.findViewById<TextInputEditText>(R.id.password_edit_tv)
        val nextBtn = view.findViewById<MaterialButton>(R.id.next_btn)

        nextBtn.setOnClickListener {
            if (!isPasswordValid(passwordEditTv.text)) {
                passwordTvInput.error = getString(R.string.error_password)
            } else {
                passwordTvInput.error = null
                navigateToProductGrid()
            }
        }

        passwordEditTv.setOnKeyListener { _, _, _ ->
            if (isPasswordValid(passwordEditTv.text)) {
                passwordTvInput.error = null
            }
            false
        }

        return view
    }

    private fun isPasswordValid(text: Editable?): Boolean {
        return text != null && text.length >= 8
    }

    private fun navigateToProductGrid() {
        (activity as? NavigationHost)?.navigateTo(ProductGridFragment(), false)
    }

五、总结

通过本篇文章的实践,成功构建MDC框架开发了一个简洁和美观的登录页面。在整个过程中,掌握了MDC各组件的用法,提升了界面设计和开发效率。

有任何问题欢迎提问,感谢大家阅读 )

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、项目背景
    • 1.1 项目需求分析
    • 二、项目开发过程
      • 2.1 添加项目依赖项
        • 2.2运行Gradle
          • 2.3 添加XML布局文件
            • 2.4 添加输入验证功能
              • 2.5 添加按钮XML
                • 2.6 实现导航到下一个fragment
                • 三、分析技术难点
                  • 3.1 MDC组件的兼容性和版本管理
                    • 3.2 Fragment导航和状态管理
                      • 3.3 输入验证与用户体验
                        • 3.4 混合语言开发(Java、Kotlin)
                          • 3.5 UI 组件和业务逻辑的解耦
                          • 四、学习笔记
                            • 4.1.Material Components (MDC)
                              • 4.2Kotlin和Java混合开发
                              • 五、总结
                              领券
                              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档