Fragment 实现底部导航栏的切换(Kotlin语言)

2023-05-16

整个过程

  • 1、整体结构图与效果图
  • 2、引入Kotlin扩展插件
  • 3、创建各页面布局文件
    • (1)底端导航栏
    • (2)信息,联系人,个人信息界面
      • ① 信息页面布局:
      • ② 联系人界面布局
      • ③个人信息界面布局
    • (3)activity_main.xml界面
  • 4、编写Java文件代码
    • (1)信息,联系人,个人信息kotlin文件
      • ①message.kt文件
      • ②contact.kt文件
      • ③myinfo.kt
    • (2)MainActivity.kt文件
  • 5、 小提示

1、整体结构图与效果图

(1)整体结构图
整体结构图

(2)页面效果图
效果图

2、引入Kotlin扩展插件

在根目录下的build.gradle添加kotlin-android-extensions插件

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'kotlin-android-extensions'
}

3、创建各页面布局文件

(1)底端导航栏

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white"
    android:baselineAligned="false">

    <LinearLayout
        android:id="@+id/id_info_tab"
        android:layout_width="136dp"
        android:layout_height="200px"
        android:gravity="center"
        android:orientation="vertical">

        <ImageButton
            android:id="@+id/id_info_img"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@color/white"
            android:clickable="false"
            android:scaleType="fitCenter"
            app:srcCompat="@drawable/message_selected"/>

        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:clickable="false"
            android:saveEnabled="false"
            android:text="消息"/>

    </LinearLayout>

    <LinearLayout
        android:id="@+id/id_contact_tab"
        android:layout_width="136dp"
        android:layout_height="200px"
        android:gravity="center"
        android:orientation="vertical">

        <ImageButton
            android:clickable="false"
            android:id="@+id/id_contact_img"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@color/white"
            android:scaleType="fitCenter"
            app:srcCompat="@drawable/friend_unselected" />

        <TextView
            android:clickable="false"
            android:id="@+id/textView3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:saveEnabled="false"
            android:text="朋友"/>

    </LinearLayout>

    <LinearLayout
        android:id="@+id/id_my_tab"
        android:layout_width="136dp"
        android:layout_height="200px"
        android:gravity="center"
        android:orientation="vertical">

        <ImageButton
            android:clickable="false"
            android:id="@+id/id_my_img"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@color/white"
            android:scaleType="fitCenter"
            app:srcCompat="@drawable/myinfo_unselected" />

        <TextView
            android:clickable="false"
            android:id="@+id/textView4"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:saveEnabled="false"
            android:text="我的" />

    </LinearLayout>
</LinearLayout>

(2)信息,联系人,个人信息界面

① 信息页面布局:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#F0F8FF">

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

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/white">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="60dp"
                android:background="#009FCC"
                android:gravity="center"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/textView"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_horizontal"
                    android:gravity="center_horizontal"
                    android:text="消息"
                    android:textColor="#ffffff"
                    android:textFontWeight="30"
                    android:textSize="25dp" />
            </LinearLayout>
        </RelativeLayout>
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/white">
            <TextView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_gravity="center"
                android:gravity="center"
                android:text="消息界面"
                />
        </RelativeLayout>
    </LinearLayout>
</FrameLayout>

② 联系人界面布局

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#F0F8FF">

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

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/white">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="60dp"
                android:background="#009FCC"
                android:gravity="center"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/textView"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_horizontal"
                    android:gravity="center_horizontal"
                    android:text="联系人"
                    android:textColor="#ffffff"
                    android:textFontWeight="30"
                    android:textSize="25dp" />
            </LinearLayout>
        </RelativeLayout>
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/white">
            <TextView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_gravity="center"
                android:gravity="center"
                android:text="联系人界面"
                />
        </RelativeLayout>
    </LinearLayout>
</FrameLayout>

③个人信息界面布局

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#F0F8FF">

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

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/white">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="60dp"
                android:background="#009FCC"
                android:gravity="center"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/textView"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_horizontal"
                    android:gravity="center_horizontal"
                    android:text="个人信息"
                    android:textColor="#ffffff"
                    android:textFontWeight="30"
                    android:textSize="25dp" />
            </LinearLayout>
        </RelativeLayout>
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/white">
            <TextView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_gravity="center"
                android:gravity="center"
                android:text="个人信息界面"
                />
        </RelativeLayout>
    </LinearLayout>
</FrameLayout>

(3)activity_main.xml界面

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

    <FrameLayout
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1" />


    <include layout = "@layout/bottom_navbar"/>

</LinearLayout>

4、编写Java文件代码

(1)信息,联系人,个人信息kotlin文件

①message.kt文件

package com.example.we_chatting

import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup


class message : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_message, container, false)
    }

}

②contact.kt文件

package com.example.we_chatting

import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup


class contact : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_contact, container, false)
    }
}

③myinfo.kt

package com.example.we_chatting

import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup


class myinfo : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_myinfo, container, false)
    }

}

(2)MainActivity.kt文件

package com.example.we_chatting


import android.support.v4.app.Fragment
import android.support.v4.app.FragmentManager
import android.support.v4.app.FragmentTransaction
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity
import android.util.Log;
import android.view.View;
import android.widget.ImageButton;
import android.widget.LinearLayout;

class MainActivity : AppCompatActivity(), View.OnClickListener {
    private val mTab01: Fragment = message()
    private val mTab02: Fragment = contact()
    private val mTab03: Fragment = myinfo()

    private var mTabInfo: LinearLayout? = null
    private var mTabContact: LinearLayout? = null
    private var mTabMy: LinearLayout? = null

    private var mImgInfo: ImageButton? = null
    private var mImgContact: ImageButton? = null
    private var mImgMy: ImageButton? = null
    private var fm: FragmentManager? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        if (supportActionBar != null) {
            supportActionBar!!.hide()
        }
        setContentView(R.layout.activity_main)

        initFragment()
        initView()
        initEvent()
        selectFragment(0)

    }

    //添加界面
    private fun initFragment() {
        var fm = supportFragmentManager
        val transaction: FragmentTransaction = fm.beginTransaction()
        transaction.add(R.id.content, mTab01)
        transaction.add(R.id.content, mTab02)
        transaction.add(R.id.content, mTab03)
        transaction.commit()
    }

    private fun resetImgs() {
        mImgInfo!!.setImageResource(R.drawable.message_unselected)
        mImgContact!!.setImageResource(R.drawable.friend_unselected)
        mImgMy!!.setImageResource(R.drawable.myinfo_unselected)
    }

    private fun initView() {
        mTabInfo = findViewById<View>(R.id.id_info_tab) as LinearLayout
        mTabContact = findViewById<View>(R.id.id_contact_tab) as LinearLayout
        mTabMy = findViewById<View>(R.id.id_my_tab) as LinearLayout

        mImgInfo = findViewById<View>(R.id.id_info_img) as ImageButton
        mImgContact = findViewById<View>(R.id.id_contact_img) as ImageButton
        mImgMy = findViewById<View>(R.id.id_my_img) as ImageButton
    }

    private fun selectFragment(i: Int) {
        var fm = supportFragmentManager
        val transaction: FragmentTransaction = fm.beginTransaction()
        hideFragment(transaction)
        when (i) {
            0 -> {
                Log.d("setSelect", "1")
                transaction.show(mTab01)
                mImgInfo!!.setImageResource(R.drawable.message_selected)
            }
            1 -> {
                transaction.show(mTab02)
                mImgContact!!.setImageResource(R.drawable.friend_selected)
            }
            2 -> {
                transaction.show(mTab03)
                mImgMy!!.setImageResource(R.drawable.myinfo_selected)
            }
            else -> {
            }
        }
        transaction.commit()
    }

    private fun initEvent() {
        mTabInfo!!.setOnClickListener(this)
        mTabContact!!.setOnClickListener(this)
        mTabMy!!.setOnClickListener(this)
    }

    private fun hideFragment(transaction: FragmentTransaction) {
        transaction.hide(mTab01)
        transaction.hide(mTab02)
        transaction.hide(mTab03)
    }

    override fun onClick(v: View) {
        Log.d("onClick", "1")
        resetImgs()
        when (v.id) {
            R.id.id_info_tab -> {
                Log.d("onClick", "2")
                selectFragment(0)
            }
            R.id.id_contact_tab -> selectFragment(1)
            R.id.id_my_tab -> selectFragment(2)
            else -> {
            }
        }
    }
}

5、 小提示

(1)创建fragment文件通过下图方法创建,创建完的kotlin文件中可删除多余方法,只留下onCreateView方法
在这里插入图片描述在这里插入图片描述(2)图标的下载可在阿里巴巴矢量图标库下载

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Fragment 实现底部导航栏的切换(Kotlin语言) 的相关文章

  • visual studio中头文件和库文件路径设置

    在程序开发中 xff0c 很多时候需要用到别人开发的工具包 xff0c 如OpenCV和itk 一般而言 xff0c 在vs中 xff0c 很少使用源文件 xff0c 大部分是使用对类进行声明的头文件和封装了类的链接库 xff08 静态li
  • LNK2001: 无法解析的外部符号的几种情况

    一般来说 xff0c 我们引用第三方库时 xff0c 需要进行指定依赖项配置 xff0c 若没有进行相关配置 xff0c 则编译器会出现 LNK2001 无法解析的外部符号 错误 这个是最常见的问题 xff0c 具体步骤 xff1a 项目
  • JMeter

    Apache JMeter 压力测试工具 一 什么是Apache JMeter Apache JMeter 是 Apache 组织基于 Java 开发的压力测试工具 xff0c 用于对软件做压力测试 JMeter 最初被设计用于 Web 应
  • C++11向线程函数传递参数

    template span class token operator lt span class Function span class token punctuation span class span class token punct
  • C++11之std::future对象使用说明

    std future介绍 在前面几篇文章中基本都用到thread对象 xff0c 它是C 43 43 11中提供异步创建多线程的工具 但是我们想要从线程中返回异步任务结果 xff0c 一般需要依靠全局变量 xff1b 从安全角度看 xff0
  • delete 和 delete[]真正区别

    我们通常从教科书上看到这样的说明 xff1a delete 释放new分配的单个对象指针指向的内存 delete 释放new分配的对象数组指针指向的内存 那么 xff0c 按照教科书的理解 xff0c 我们看下下面的代码 xff1a spa
  • Activity的onNewIntent

    一个应用的Activity可供多种方式调用启动 xff0c 当多个调用希望只有一个Activity的实例存在 xff0c 并且还要区分是被谁启动或是已经启动被谁拉到前台来的 xff0c 这就需要Activity的onNewIntent In
  • at 与 crontab调度命令详解

    目录 1 At调度 只执行一次 1 1准备任务 xff1a 查看at服务是否开启 1 2绝对时间定制任务 1 3相对时间定制任务 1 4查看at进程 1 5删除at任务 2 crontab调度 可重复执行 2 1简述 2 2crontab调
  • [计算机网络] --- STP (下篇) 工作原理及配置

    文章目录 前言一 stp工作原理二 stp计算过程 工作步骤1 选举根桥2 选举根端口3 选举指定端口4 确立阻塞端口 三 例题 xff1a 前言 上一篇文章我们介绍了stp的起源和一些相关术语 xff0c 接下来我们就正式开始介绍stp的
  • iOS富文本实现(一):私密阅读效果

    废话不多说 xff0c 咱们直接先看效果 xff01 看是不是咱想要的哈 目录 xff1a 一 前言 xff1a 二 核心需求说明 三 实现效果核心代码片段 四 几个注意的小细节 一 前言 xff1a 我的第一篇CSDN文章就这样发布了 x
  • 登录 注册 servlet基础

    工具类 页面与数据库的交换 span class token keyword package span org span class token punctuation span lizhenhua span class token pun
  • 解决Ubuntu开机之后不显示桌面图标,只显示桌面文件的问题

    Ubuntu开机之后不显示桌面图标 xff08 指左侧那一栏 xff09 xff0c 但桌面上的文件可以使用 xff0c 鼠标可以使用 鼠标右键 gt 打开终端 xff1b xff08 如果鼠标不能使用 xff0c 按ctl 43 alt
  • yii2中登录后跳转回登录前请求的页面

    yii2中登录后跳转回登录前请求的页面 作者 php 发布时间 2017 06 16 浏览 1030次 转发请备注原文地址 xff1a www niwoxuexi com blog php article 158 html yii2中登录后
  • Gateway

    Gateway SpringCloud微服务网关组件 一 Spring Cloud Gateway简介 1 为什么要用Gateway xff1f 在微服务架构中 xff0c 通常一个系统会被拆分为多个微服务 xff0c 微服务之间的调用可以
  • Android(安卓)时间戳和日期之间的转化

    注 xff1a 转发请注明原地址 xff1a https www niwoxuexi com blog android article 170 在Android开发过程中 xff0c 经常会遇到日期的各种格式转换 xff0c 主要使用Sim
  • 如何判断Activity是否在前台显示

    转发请备注原文地址 xff1a https www niwoxuexi com blog android00 article 223 html 我们在Android开发过程中 xff0c 经常会判断Activity是否在前台显示 xff0c
  • Android 获取cache缓存的目录路径

    转发请备注原文地址 xff1a https www niwoxuexi com blog android00 article 224 html Android开发中 xff0c 有时需要知道cache缓存的路径 我写了一个静态类 xff0c
  • objc[8715]: Class JavaLaunchHelper is implemented in both...

    在Mac上 xff0c 升级IntelliJ Idea 2017 01后 xff0c 运行的时候出现了一个红色的警告 xff1a objc 8715 Class JavaLaunchHelper is implemented in both
  • mac上使用dex2jar遇到的权限问题的解决

    本文来自 xff1a https www niwoxuexi com blog android article 235 html 摘要 在dex2jar目录下执行sudo sh d2j dex2jar sh classes dex时报错如下
  • Android Studio将module变为library

    本文来源你我学习网 xff1a 地址 https www niwoxuexi com blog android article 244 html 我们在开发的时候如在在Android Studio中的module打包成library方便模块

随机推荐

  • Navicat Premium实现mysql数据库备份/还原

    转发请备注原文地址 xff1a https www niwoxuexi com blog php article 161 htm Navicat Premium 是一个非常好用的数据库 xff08 支持 MySQL SQLite Oracl
  • 在vue中获取dom元素

    转发请备注原文链接地址 xff1a https www niwoxuexi com blog web article 307 html 在vue中经常会通过js操作dom对象 xff0c 可以通过给标签添加ref属性实现 xff0c 下面通
  • HIVE总结

    一 xff1a hive作用 Hive是基于Hadoop的一个数据仓库工具 xff0c 可以将结构化的数据文件映射为一张表 xff0c 并提供类SQL 查询功能 Hive本质 xff1a 将HQL转化成MapReduce程序 xff08 1
  • 微软2014校园招聘笔试题

  • Seata

    Seata 微服务分布式事务组件 一 什么是分布式事务 1 什么是事务 事务指的是一个操作单元 xff0c 在这个操作单元中的所有操作最终要保持一致的行为 xff0c 要么所有操作都成功 xff0c 要么所有的操作都被撤销 2 本地事务 本
  • 测试用例优先级与三轮测试的结合

    测试用例优先级与三轮测试的结合 发布时间 2009 7 10 15 01 作者 meizhu 来源 Taobao QA Team 字体 小 中 大 上一篇 下一篇 打印 我要投稿 每周一问 xff0c 答贴有奖 测试用例优先级 三轮测试 x
  • Windows 10 家庭中文版,电脑文件夹背景、Word背景全变成黑色的解决方案

    电脑桌面空白处点击鼠标右键 gt 个性化 gt 颜色 xff1b 在 选择颜色 下拉菜单中选择 浅色 选项 这样 xff0c 电脑文件夹的背景和其他界面颜色就都回归了正常的亮白色
  • AbstractApplicationContext.refresh()方法

    refresh public void refresh throws BeansException IllegalStateException synchronized this startupShutdownMonitor 准备好刷新上下
  • HBase StoreFile原理总结

    HBase StoreFile原理总结 1 StoreFile是什么 在hbase架构设计中 xff0c 本身hbase基于hdfs进行数据存储 同时为了提升效率 xff0c 数据会有一个memstore block cache来做数据缓存
  • ubuntu设置关机时自动执行任务

    背景说明 本机环境 xff1a ubuntu16 04 需求 本机关机时调用远程服务用来记录日志等操作 systemd说明 ubuntu16 04采用的是systemd作为系统管理的子系统 xff0c 关于systemd的更多说明 xff0
  • Linux下zabbix_proxy实施部署

    简介 zabbix proxy 可以代替 zabbix server 收集性能和可用性数据 然后把数据汇报给 zabbix server 并且在一定程度上分担了zabbix server 的压力 zabbix agent可以指向多个prox
  • 巧用nautilus解决ubuntu文件目录、文件的权限问题

    有没有遇到这样的烦恼 xff1a 有时想给一个目录的文件进行增删 xff0c 单是因为权限问题 xff0c 无法进行操作 虽然可以用sudo 43 命令行来解决 xff0c 但是觉得操作起来还是不太方便 如果可以跟平时一样 xff0c 在图
  • Android 屏幕旋转的处理

    1 不做任何处理的情况下 如果没有针对性地做任何处理的话 xff0c 默认情况下 xff0c 当用户手机的重力感应器打开后 xff0c 旋转屏幕方向 xff0c 会导致app的当前activity发生onDestroy gt onCreat
  • Python txt文件创建,写入,保存

    实现功能介绍 xff1a 新建文本文件 xff0c 以日期命名 xff0c 判断如果存在则后缀加1 xff0c 循环按行写入内容并保存 首先指定要写入文件的内容 xff0c 并使用 datetime 模块获取当前日期 然后 xff0c 我们
  • Centos 7 / 8 安装oracle jdk 和jenkins步骤及一些常见的问题。

    废话不多说 xff0c 先说自己总结的经验 xff0c 不推荐用解压jdk压缩包 xff08 jdk 8u321 linux x64 tar gz xff09 然后配置环境变量的方式安装java 最好用yum包安装java或者是用rpm方式
  • adobe xd_如何在Adobe XD中创建Finance App UI设计

    adobe xd 在本教程中 xff0c 您将学习如何在Adobe XD中创建财务应用程序设计 xff0c 以及 xff08 更重要的是 xff09 如何轻松对其UI的各个部分进行动画处理 您将在本Adobe XD教程中学到什么 如何在Ad
  • 今天配置问题总结2023/3.13

    关于SSL库的安装 openssl和openssl devel Ubuntu系统上 首先安装openssl sudo apt get install openssl 在安装openssl devel sudo apt get install
  • 分辨率PPI(Pixel Per Inch)与DPI(Dot Per Inch)

    分辨率PPI与DPI xff0c 关于这个问题 xff0c 现在很多人容易混淆 xff0c 现摘录几份资料 图像分辨率所使用的单位是PPI xff08 Pixel Per Inch xff09 xff0c 意思是 xff1a 在图像中每英寸
  • 【自动驾驶技术】优达学城无人驾驶工程师学习笔记(七)——计算机视觉基础

    计算机视觉基础目录 前言颜色选择 xff08 Color Selection xff09 理论基础代码实践 区域筛选 xff08 Region Masking xff09 理论基础代码实践 Canny边缘检测问题背景Canny边缘检测原理代
  • Fragment 实现底部导航栏的切换(Kotlin语言)

    整个过程 1 整体结构图与效果图2 引入Kotlin扩展插件3 创建各页面布局文件 xff08 1 xff09 底端导航栏 xff08 2 xff09 信息 xff0c 联系人 xff0c 个人信息界面 信息页面布局 xff1a 联系人界面