# 第六个项目——登陆界面

## 实验目的

* 掌握布局的组合使用方式；
* 掌握**Vector Asset**资源的使用方式；
* 掌握**Image View**、**View**等控件的使用方式；

## 实验要求

* 创建布局文件并对根据要求对布局进行设置；

## 实验内容

### 步骤一，创建**Android**工程

打开**Android Studio**创建名为**Code05**的工程，选择**Empty Activity**模板。

本次项目需要实现应用的登录界面布局，登录界面效果图如[图1. Code05登录界面效果](#code05_screenshot)所示。

![图1. Code05登录界面效果](http://www.funnycode.net/guet/img/ch02/Code05_running_screenshot.png)

### 步骤二，构建页面布局

**1. 页面所需控件，根据效果图可知，需要如下控件进行布局：**

* **ImageView**，显示**Logo**、账号、密码、密码样式等四个图标；
* **EditText**，输入用户名、密码等；
* **Button**，登录按钮。

**2. 根据效果图可将页面分为三个部分：**

* 页面顶部，包含应用的**Logo**。可采用**RelativeLayout**；
* 页面中部，包含账号、密码输入框等。可采用**RelativeLayout**；
* 页面底部，包含登录按钮。可采用**RelativeLayout**；

页面整体可采用**LinearLayout**进行布局，代码如下所示，对于页面三个部分的高度可通过指定页面顶部元素、底部元素的**android:layout\_weight**，使得顶部和底部占满页面，而中部则根据控件实际大小进行设置。

```markup
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".LoginActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1">
        ...
    </RelativeLayout>
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="40dp">
        ...
    </RelativeLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="40dp">
        ...
    </RelativeLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_weight="1"
        android:layout_height="wrap_content">
        ...
    </RelativeLayout>
</LinearLayout>
```

**3. 加入应用的Logo图标资源。**

将名为**ic\_logo.png**按照像素密度分别放入**res/mipmap-XXXXX**等文件夹中。

**4. 在activity\_main.xml加入ImageView控件显示Logo。**

**ImageView**作为整个页面的顶部显示的元素，把其放入顶部的**RelativeLayout**中。通过设置**ImageView**的**android:layout\_centerInParent**属性可以**ImageView**在其父容器中居中。设置**android:src**属性则 可设置为**ImageView**控件设置图片源。

通过设置顶部的**RelatvieLayout**的**android:layout\_marginTop**属性， 可调整**ImageView**距离顶部的位置，使得整个页面空间更加协调，代码下所所示。

```markup
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".LoginActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:layout_marginTop="48dp">
        <ImageView
            android:layout_width="108dp"
            android:layout_height="108dp"
            android:src="@mipmap/ic_logo"
            android:layout_centerInParent="true"
            />
    </RelativeLayout>
    ...
```

**5. 加入用户账号、密码图标Vector Asset资源。**

用户账号、密码的图标采用**Android Studio**提供的内置**Vector Asset**资源。在工程窗口右击**app**模块，选择【New】-> 【Vector Asset】菜单，弹出的**Asset Studio**窗口中按照以下步骤进行设置：

* 在**Asset Type**中选择**Clip Art**；
* 点击**Clip Art** 图标选项，弹出如[图2. Select Icon窗口](#code05_select_icon)所示的**Select Icon**窗口；
* 选择**person outline**图标，点击确定；
* 在**res/drawable**目录下看到**ic\_person\_outline\_black\_24dp.xml** drawable图标资源；

使用同样的方式添加**lock outline**、**visibility**、**visibility off**三个图标。

![图2. Select Icon窗口](http://www.funnycode.net/guet/img/ch02/Code05_select_icon.png)

**6. 设置用户账户、密码布局。**

对于布局中用户账号一栏，使用了2个控件，分别是**ImageView**、**EditText**，这两个控件均在**RelativeLayout**中。 设置两个控件的**android:layout\_alignParentBottom**属性可以使得2个控件底部与父容器**RelativeLayout**对齐。

设置**ImageView**控件的**android:layout\_width**和**android:layout\_height**属性为*32dp*。

设置**EditText**控件的**android:layout\_marginStart**和**android:layout\_marginEnd**属性为*48dp*。

%由于**EditText**控件的样式（例如：底部横线颜色，文本光标颜色等）与App的主题色不符，在此可通过一些属性设置来改变。

%首先设置**EditText**控件的**android:background**属性为\`\`@null''用于取消该控件的底部横线以及背景，文本光标的颜色则通过设置**android:textCursorDrawable**

以同样的方式设置用户密码一栏的布局。不同的是密码栏的右侧还增加了一个**ImageView**用于设置密码可见操作。因此这一栏实际上有三个控件，分别是**ImageView**、**EditText**、**ImageView**。页面中部的布局代码下所示。

```markup
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".LoginActivity">

    ...
      <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_marginTop="48dp">

        <ImageView
            android:layout_width="32dp"
            android:layout_height="32dp"
            android:layout_marginBottom="4dp"
            android:layout_alignParentBottom="true"
            android:src="@drawable/ic_person_outline_black_24dp"/>

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="4dp"
            android:layout_alignParentBottom="true"
            android:layout_gravity="center"
            android:inputType="text"
            android:hint="Email/Account"
            android:layout_marginStart="48dp"
            android:layout_marginEnd="48dp"
            android:maxLines="1"/>
    </RelativeLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_marginTop="16dp">

        <ImageView
            android:layout_width="32dp"
            android:layout_height="32dp"
            android:layout_marginBottom="4dp"
            android:layout_alignParentBottom="true"
            android:src="@drawable/ic_lock_outline_black_24dp"/>

        <EditText
            android:id="@+id/et_pwd"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="4dp"
            android:layout_alignParentBottom="true"
            android:inputType="textPassword"
            android:hint="Password"
            android:layout_marginStart="48dp"
            android:layout_marginEnd="48dp"
            android:maxLines="1"/>

        <ImageView
            android:id="@+id/iv_pwd_switch"
            android:layout_width="24dp"
            android:layout_height="24dp"
            android:layout_marginBottom="6dp"
            android:layout_alignParentBottom="true"
            android:layout_alignParentEnd="true"
            android:src="@drawable/ic_visibility_off_black_24dp"/>
    </RelativeLayout>
    ...
```

**7. 设置登录按钮布局。**

登录按钮的布局相对较简单，将**Button**控件置于底部的**RelativeLayout**中，并设置其 **android:textColor**、**android:layout\_alignParentTop**等属性，具体代码如下所示。

```markup
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".LoginActivity">

    ...

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_marginBottom="32dp"
        android:layout_weight="1"
        android:layout_height="wrap_content">
        <Button
            android:text="Login"
            android:textColor="@android:color/white"
            android:background="@color/colorPrimary"
            android:layout_marginTop="32dp"
            android:layout_alignParentTop="true"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </RelativeLayout>
</LinearLayout>
```

### 步骤三，设置App启动图标

工程窗口中右击工程的**app**模块，在弹出的菜单中选择【New】-> 【Image Asset】，弹出如[图3. Asset Studio窗口](#asset_studio)所示的**Asset Studio**窗口。 按照以下步骤进行设置：

* 在**Icon Type**中选择**Launcher Icons (Adaptive and Legacy)**。
* 设置**Name**为**ic\_launcher**。
* 在**Foreground Layer**标签中的**Source Asset**中选择**Asset Type**为**Image**，并在**Path**中选择所需要使用的图标文件（在本例中为ic\_logo.png）。
* 在**Background Layer**标签中的**Source Asset**中选择**Color**，并设置**Color**为白色。
* 点击确定完成**Logo**图标的导入。

![图3. Asset Studio窗口](http://www.funnycode.net/guet/img/ch02/Code05_asset_studio.png)

### 步骤四，实现密码明文切换图标动作

当用户点击密码栏中的密码明文切换图标时，可将密码**EditText**控件中的输入类型进行切换，这需要在**LoginActivity**活动中增加**ImageView**控件的**OnClickListener**事件侦听器并对**EditText**控件的**inputType**属性进行设置即可，具体代码如下所示。

```java
public class LoginActivity extends AppCompatActivity {

    private Boolean bPwdSwitch = false;
    private EditText etPwd;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...

        final ImageView ivPwdSwitch = findViewById(R.id.iv_pwd_switch);
        etPwd = findViewById(R.id.et_pwd);

        ivPwdSwitch.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                bPwdSwitch = !bPwdSwitch;
                if (bPwdSwitch) {
                    ivPwdSwitch.setImageResource(
                            R.drawable.ic_visibility_black_24dp);
                    etPwd.setInputType(
                            InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
                } else {
                    ivPwdSwitch.setImageResource(
                            R.drawable.ic_visibility_off_black_24dp);
                    etPwd.setInputType(
                        InputType.TYPE_TEXT_VARIATION_PASSWORD | 
                        InputType.TYPE_CLASS_TEXT);
                    etPwd.setTypeface(Typeface.DEFAULT);
                }
            }
        });
```

## 实验小结

通过本次实验，你应该掌握了如下知识内容：

* 使用**LinearLayout**，**Relative Layout**进行页面布局；
* 使用**Vector Asset**添加图标资源；
* 使用**Image Asset**导入应用启动图标；
