任务二 搭建登录页面
一、任务目标
创建登录页面并完成页面布局,使页面显示欢迎文字、用户名和密码输入框、用户协议、登录按钮及注册入口,并能够从初始页面打开登录页。
二、添加 ConstraintLayout 依赖
1. 添加依赖
打开 app/build.gradle.kts,在 dependencies 中添加 ConstraintLayout 依赖:
dependencies { // ... 省略已有依赖。 implementation("androidx.constraintlayout:constraintlayout:2.2.2")}点击 Android Studio 顶部提示栏中的 Sync Now,等待 Gradle 同步完成。同步成功后再创建布局文件。
三、创建登录页面
先创建只显示“登录页面”的简单页面,检查页面能否打开,再添加正式控件。
1. 创建 activity_login.xml
在 app/src/main/res/layout 目录中创建 activity_login.xml,写入以下完整内容。
<?xml version="1.0" encoding="utf-8"?><layout 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">
<androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="登录页面" android:textSize="24sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>最外层的 <layout> 是 Data Binding 布局的根标签。页面中间的“登录页面”是临时文字,只用于运行验证,完成检查后将被正式控件替换。布局文件准备好后,还需要创建 LoginActivity 来显示它。
2. 创建 LoginActivity
在 com.android.practice.food.feature.account 包中创建 login 包,然后创建 LoginActivity.kt,写入以下完整内容。
package com.android.practice.food.feature.account.login
import android.os.Bundleimport androidx.databinding.DataBindingUtilimport com.android.practice.food.Rimport com.android.practice.food.core.ui.base.BaseActivityimport com.android.practice.food.databinding.ActivityLoginBinding
class LoginActivity : BaseActivity() {
private lateinit var binding: ActivityLoginBinding
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 显示登录布局,并取得访问页面控件的 binding。 binding = DataBindingUtil.setContentView(this, R.layout.activity_login) // 后续绑定的数据会随当前页面的运行状态更新。 binding.lifecycleOwner = this }}在 onCreate() 中,DataBindingUtil.setContentView(...) 加载上一步创建的 activity_login.xml,让登录页显示其中的临时文字。它还会返回一个绑定对象,保存在 binding 中。后面添加控件时,可以通过 binding 操作它们。
接着用 binding.lifecycleOwner = this 告诉 binding 当前登录页的运行状态,为以后根据数据更新页面内容做准备。现在页面只有临时文字,所以这行代码不会改变显示效果。
3. 注册 LoginActivity
LoginActivity 已经能加载布局,还需要在清单文件中注册,应用才能打开它。打开 app/src/main/AndroidManifest.xml,在 <application> 标签内加入:
<manifest ...> <application ...> <activity android:name=".feature.main.MainActivity" ...> ... </activity>
<activity android:name=".feature.account.login.LoginActivity" /> </application></manifest>注册位置与 MainActivity 处于同一级,不能写在 MainActivity 的 <activity> 标签内部。
4. 从 MainActivity 打开登录页
当前项目还没有登录状态判断。为了便于查看页面,在 MainActivity.kt 中暂时直接打开 LoginActivity。
打开 MainActivity.kt,添加 Intent 和 LoginActivity 的导入语句,并在 onCreate() 末尾打开登录页:
import android.content.Intentimport com.android.practice.food.feature.account.login.LoginActivity
class MainActivity : BaseActivity() {
// ... 省略成员变量。
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = DataBindingUtil.setContentView(this, R.layout.activity_main) binding.lifecycleOwner = this
// 暂时跳过主页面,直接打开登录页检查布局。 startActivity(Intent(this, LoginActivity::class.java)) // 关闭主页面,避免按返回键时再次回到这里。 finish() }}startActivity() 打开登录页,finish() 关闭当前主页面。这是便于查看登录页的临时跳转,任务五将改为仅在未登录时跳转。
5. 运行验证
运行应用。屏幕中间应显示“登录页面”,表示 Activity、布局文件和页面跳转配置已生效。
如果应用仍停留在初始页面,检查 MainActivity 中是否已经调用 startActivity();如果打开页面时闪退,检查 AndroidManifest.xml 中是否已经注册 LoginActivity。
四、添加关闭按钮和欢迎文字
返回 activity_login.xml,在 ConstraintLayout 中加入关闭按钮和欢迎文字。
1. 删除临时文字
删除 ConstraintLayout 中显示“登录页面”的临时 TextView,保留外层布局标签。
<layout ...> <androidx.constraintlayout.widget.ConstraintLayout ...> <TextView android:text="登录页面" ... /> </androidx.constraintlayout.widget.ConstraintLayout></layout>2. 添加关闭按钮
在 activity_login.xml 的 ConstraintLayout 中添加关闭按钮,使用初始工程中的 ic_cancel_black 图标和 bg_circle_black 背景。
<layout ...> <androidx.constraintlayout.widget.ConstraintLayout ...> <ImageView android:id="@+id/close_btn" android:layout_width="45dp" android:layout_height="45dp" android:layout_marginStart="20dp" android:layout_marginTop="20dp" android:background="@drawable/bg_circle_black" android:padding="10dp" android:scaleType="centerInside" android:src="@drawable/ic_cancel_black" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout></layout>任务三将为该按钮添加关闭页面的点击事件。
3. 添加欢迎文字
在关闭按钮后加入:
<layout ...> <androidx.constraintlayout.widget.ConstraintLayout ...> <ImageView android:id="@+id/close_btn" ... />
<TextView android:id="@+id/welcome" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="35dp" android:layout_marginTop="50dp" android:layout_marginEnd="35dp" android:text="@string/label_login_welcome" android:textColor="@color/black_80" android:textSize="30dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/close_btn" /> </androidx.constraintlayout.widget.ConstraintLayout></layout>label_login_welcome 已经定义在初始工程的 strings.xml 中,直接使用即可。
layout_width="0dp" 配合左右约束使用,表示控件宽度由两侧约束共同确定。欢迎文字距离页面左右两侧各 35dp,并放置在关闭按钮下方。
4. 运行验证
重新运行应用。关闭按钮应位于页面左上角,欢迎文字位于按钮下方。
五、添加账号输入区
登录页包含用户名和密码两个输入框。输入框样式 EditText_Single_Line、提示文字 hint_username 和 hint_password 均已在初始工程中提供。
1. 添加用户名输入框
在欢迎文字后加入:
<layout ...> <androidx.constraintlayout.widget.ConstraintLayout ...> <TextView android:id="@+id/welcome" ... />
<EditText android:id="@+id/et_username" style="@style/EditText_Single_Line" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="50dp" android:hint="@string/hint_username" app:layout_constraintEnd_toEndOf="@id/welcome" app:layout_constraintStart_toStartOf="@id/welcome" app:layout_constraintTop_toBottomOf="@id/welcome" tools:text="123892" /> </androidx.constraintlayout.widget.ConstraintLayout></layout>输入框的左右约束与欢迎文字相同,因此二者具有相同的左右边界。tools:text 只在 Android Studio 的布局预览中显示,运行应用时输入框仍为空。
2. 添加密码输入框
在用户名输入框后加入:
<layout ...> <androidx.constraintlayout.widget.ConstraintLayout ...> <EditText android:id="@+id/et_username" ... />
<EditText android:id="@+id/et_password" style="@style/EditText_Single_Line" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="30dp" android:hint="@string/hint_password" android:inputType="textPassword" app:layout_constraintEnd_toEndOf="@id/et_username" app:layout_constraintStart_toStartOf="@id/et_username" app:layout_constraintTop_toBottomOf="@id/et_username" tools:text="" /> </androidx.constraintlayout.widget.ConstraintLayout></layout>android:inputType="textPassword" 用于指定密码输入方式。运行时,密码内容会以隐藏字符显示。
3. 运行验证
运行应用,分别在两个输入框中输入内容。用户名应直接显示,密码应隐藏显示;两个输入框的宽度和左右位置应保持一致。
六、完成页面操作区
页面下半部分依次放置用户协议、登录按钮和账号注册入口。所需文字和样式已经包含在初始工程中。
1. 添加用户协议
在 activity_login.xml 中,接在密码输入框之后添加复选框和协议文字:
<layout ...> <androidx.constraintlayout.widget.ConstraintLayout ...> <EditText android:id="@+id/et_password" ... />
<CheckBox android:id="@+id/cb_agreement" style="@style/CheckBox_Common" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="30dp" android:gravity="center_vertical" android:text="@string/login_agreement_prefix" app:layout_constraintStart_toStartOf="@id/et_password" app:layout_constraintTop_toBottomOf="@id/et_password" />
<TextView android:id="@+id/agreement_url" style="@style/CheckBox_Common" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/login_agreement_postfix" android:textColor="@color/link_text" app:layout_constraintBottom_toBottomOf="@id/cb_agreement" app:layout_constraintStart_toEndOf="@id/cb_agreement" app:layout_constraintTop_toTopOf="@id/cb_agreement" /> </androidx.constraintlayout.widget.ConstraintLayout></layout>link_text 设置协议文字的颜色。
2. 添加登录按钮
在 activity_login.xml 中,将登录按钮放在协议文字之后,并约束在协议复选框下方:
<layout ...> <androidx.constraintlayout.widget.ConstraintLayout ...> <TextView android:id="@+id/agreement_url" ... />
<Button android:id="@+id/login_btn" style="@style/Primary_Button" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="40dp" android:text="@string/label_login_btn" app:layout_constraintEnd_toEndOf="@id/et_username" app:layout_constraintStart_toStartOf="@id/et_username" app:layout_constraintTop_toBottomOf="@id/cb_agreement" /> </androidx.constraintlayout.widget.ConstraintLayout></layout>Primary_Button 已经设置按钮背景、文字颜色和字号。登录按钮的左右约束与用户名输入框一致。
3. 添加账号注册入口
在登录按钮后加入:
<layout ...> <androidx.constraintlayout.widget.ConstraintLayout ...> <Button android:id="@+id/login_btn" ... />
<TextView android:id="@+id/register_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:padding="10dp" android:text="@string/label_go_register" android:textColor="@color/black_70" android:textSize="14dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/login_btn" /> </androidx.constraintlayout.widget.ConstraintLayout></layout>注册入口位于登录按钮下方,并在页面中水平居中。本单元先保留入口,注册功能将在拓展任务中完成。
4. 运行验证
运行应用,对照下图检查登录页各控件的位置和显示效果。
输入用户名和密码,确认密码隐藏显示;勾选用户协议,确认复选框状态变化。本任务暂不处理按钮和链接点击。
任务小结
本任务创建了 LoginActivity,使用 ConstraintLayout 完成登录页布局,并通过临时跳转查看页面效果。