Kotlin APP首页主流框架搭建DrawerLayout+NavigationView+Toolbar+ViewPager+BottomNavigationView

简介: Kotlin APP首页主流框架搭建DrawerLayout+NavigationView+Toolbar+ViewPager+BottomNavigationView

效果

https://ucc.alicdn.com/images/user-upload-01/20200114163153229.gif

image.png

页面结构解析

这是一个比较常见的APP首页的结构,侧边栏+主页,侧边栏里是一些菜单,主页由底部菜单控制内容区,内容区是可滑动的子页面。整体比较舒服合理,各自为阵,却又能关联在一起,加上又是大众喜爱的Material Design风格,所以成为了当下APP首页的主流结构。


image.png


上图是做的一个简单的思维导图,并不复杂,理清了结构就能事半功倍。



页面布局

1.首页

即整个大的容器。

image.png


<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
    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"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context=".module.MainActivity"
    tools:openDrawer="start">
    <include
        layout="@layout/app_bar_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <com.google.android.material.navigation.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/activity_main_drawer" />
</androidx.drawerlayout.widget.DrawerLayout>
  • DrawerLayout包裹着include的主页和侧边栏内容NavigationView。
  • app_bar_main是主页内容,采用include的方式引用是为了结构清晰,避免混乱。
  • 侧边栏NavigationView分为头部布局headerLayout和菜单menu,注意一个是layout一个是menu。
  • 其他需要注意的是,NavigationView的位置应与主内容app_bar_main同级,且在主内容之后。
  • 关于DrawerLayout更多使用可以查看:DrawerLayout使用详解。

2.主页

这里主页说的是首页除侧边栏以外的页面。

image.png

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
    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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".module.MainActivity">
    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">
        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay"/>
    </com.google.android.material.appbar.AppBarLayout>
    <include layout="@layout/content_main"/>
    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_marginRight="@dimen/dp_20"
        android:layout_marginEnd="@dimen/dp_20"
        android:layout_marginBottom="@dimen/dp_70"
        app:srcCompat="@android:drawable/ic_dialog_email"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

上面是标题,中间是内容区,FloatingActionButton可以忽略。

3.主页内容区

效果同2一样

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".module.MainActivity"
    tools:showIn="@layout/app_bar_main">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <androidx.viewpager.widget.ViewPager
            android:id="@+id/view_pager"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1" />
        <com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@+id/bottom_navigation"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:background="?android:attr/windowBackground"
            app:layout_constraintBottom_toTopOf="@+id/viewPager"
            app:menu="@menu/bottom_navigation" />
    </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

上面是ViewPager,可滑动的内容区,填充一个一个的Fragment子页面。

下面是BottomNavigationView底部菜单,与上面的ViewPager关联。

到此页面布局的部分介绍完毕,下面开始说代码部分。



代码部分

1.侧边栏

我们要在toolbar上加一个按钮,把侧边栏关联起来,让其点击可以弹出侧边栏。

    /**
     * Drawer关联Toolbar
     */
    private fun initActionBarDrawer() {
        val toggle = ActionBarDrawerToggle(
            this,
            drawer_layout,
            toolbar,
            R.string.navigation_drawer_open,
            R.string.navigation_drawer_close
        )
        drawer_layout.addDrawerListener(toggle)
        toggle.syncState()
    }

2.内容区

关联了侧边栏,我们来看内容区,上面说过内容区是ViewPager包含的一个个子页面Fragment,来看代码的实现

    /**
     * 初始化Fragment
     */
    private fun initFragments() {
        val viewPagerAdapter = CommonViewPagerAdapter(supportFragmentManager)
        viewPagerAdapter.addFragment(HomeFragment())
        viewPagerAdapter.addFragment(TreeFragment())
        viewPagerAdapter.addFragment(NaviFragment())
        viewPagerAdapter.addFragment(ProjectFragment())
        view_pager.offscreenPageLimit = 1
        view_pager.adapter = viewPagerAdapter
    }

处理事件

1.侧边栏点击事件

        /**
         * 侧边栏点击事件
         */
        nav_view.setNavigationItemSelectedListener {
            // Handle navigation view item clicks here.
            when (it.itemId) {
                R.id.nav_collect -> {
                    ToastUtilKt.showToast("收藏")
                }
                R.id.nav_share -> {
                    ToastUtilKt.showToast("分享")
                }
                R.id.nav_about -> {
                    ToastUtilKt.showToast("关于")
                }
                R.id.nav_logout -> { 
                    ToastUtilKt.showToast("退出") 
                }
            }
            //关闭侧边栏
            drawer_layout.closeDrawer(GravityCompat.START)
            true
        }

根据itemId判断触发事件,并关闭侧边栏,这一步可选,也可以不关闭 保持侧边栏打开的状态。

2.view_pager 滑动监听

        /**
         * view_pager 滑动监听
         */
        view_pager.addOnPageChangeListener(object : OnPageChangeListener {
            override fun onPageScrollStateChanged(state: Int) {
            }
            override fun onPageScrolled(
                position: Int,
                positionOffset: Float,
                positionOffsetPixels: Int
            ) {
            }
            override fun onPageSelected(position: Int) {
                bottom_navigation.menu.getItem(position).isChecked = true
                //设置checked为true,但是不能触发ItemSelected事件,所以滑动时也要设置一下标题
                when (position) {
                    0 -> {
                        toolbar.title = resources.getString(R.string.app_name)
                    }
                    1 -> {
                        toolbar.title = resources.getString(R.string.title_tree)
                    }
                    2 -> {
                        toolbar.title = resources.getString(R.string.title_navi)
                    }
                    else -> {
                        toolbar.title = resources.getString(R.string.title_project)
                    }
                }
            }
        })

view_pager滑动之后底部对应的菜单选中,并重新设置标题。

3.bottom_navigation 底部菜单点击事件

        /**
         * bottom_navigation 点击事件
         */
        bottom_navigation.setOnNavigationItemSelectedListener {
            when (it.itemId) {
                R.id.navigation_home -> {
                    view_pager.currentItem = 0
                    return@setOnNavigationItemSelectedListener true
                }
                R.id.navigation_tree -> {
                    view_pager.currentItem = 1
                    return@setOnNavigationItemSelectedListener true
                }
                R.id.navigation_navi -> {
                    view_pager.currentItem = 2
                    return@setOnNavigationItemSelectedListener true
                }
                R.id.navigation_project -> {
                    view_pager.currentItem = 3
                    return@setOnNavigationItemSelectedListener true
                }
            }
            false
        }

底部菜单点击的时候也让view_pager滑动的响应的位置,同第2步其实是相互关联的。



到此,整个搭建就完成了,从页面布局到初始化控件,再到处理事件,整体思路要清晰,搭建起来就很快,小的功能细节再调试完善完善就ok了。



完整代码

https://github.com/yechaoa/wanandroid_kotlin


写作不易,有用就点个赞呗 ^ _ ^

目录
相关文章
|
11天前
|
Java 测试技术 持续交付
【入门思路】基于Python+Unittest+Appium+Excel+BeautifulReport的App/移动端UI自动化测试框架搭建思路
本文重点讲解如何搭建App自动化测试框架的思路,而非完整源码。主要内容包括实现目的、框架设计、环境依赖和框架的主要组成部分。适用于初学者,旨在帮助其快速掌握App自动化测试的基本技能。文中详细介绍了从需求分析到技术栈选择,再到具体模块的封装与实现,包括登录、截图、日志、测试报告和邮件服务等。同时提供了运行效果的展示,便于理解和实践。
47 4
【入门思路】基于Python+Unittest+Appium+Excel+BeautifulReport的App/移动端UI自动化测试框架搭建思路
|
2月前
|
API 调度 Android开发
告别回调地狱,拥抱流畅开发体验:Kotlin协程带你解锁异步编程新姿势,让App响应速度飙升!
【9月更文挑战第11天】随着移动互联网的发展,用户对应用体验的要求不断提高,异步编程因此变得尤为重要。Kotlin凭借简洁的语法和强大的功能,在Android开发中脱颖而出。协程作为Kotlin的核心特性之一,简化了异步代码编写,提高了程序性能与可维护性。
66 5
|
2月前
|
移动开发 定位技术 Android开发
「揭秘高效App的秘密武器」:Kotlin Flow携手ViewModel,打造极致响应式UI体验,你不可不知的技术革新!
【9月更文挑战第12天】随着移动开发领域对响应式编程的需求增加,管理应用程序状态变得至关重要。Jetpack Compose 和 Kotlin Flow 的组合提供了一种优雅的方式处理 UI 状态变化,简化了状态管理。本文探讨如何利用 Kotlin Flow 增强 ViewModel 功能,构建简洁强大的响应式 UI。
46 3
|
2月前
|
开发框架 JavaScript 前端开发
uni-app x 跨平台开发框架
uni-app x 是一个强大的跨平台开发框架 uni-app x 是一个庞大的工程,它包括uts语言、uvue渲染引擎、uni的组件和API、以及扩展机制。
85 1
|
3月前
|
Python Windows 内存技术
【Azure 应用服务】Azure App Service (Windows) 使用Flask框架部署Python应用,如何在代码中访问静态文件呢?如何设置文件路径?是相对路径还是绝对路径呢?
【Azure 应用服务】Azure App Service (Windows) 使用Flask框架部署Python应用,如何在代码中访问静态文件呢?如何设置文件路径?是相对路径还是绝对路径呢?
|
4月前
|
Android开发 Kotlin
kotlin开发安卓app,如何让布局自适应系统传统导航和全面屏导航
使用`navigationBarsPadding()`修饰符实现界面自适应,自动处理底部导航栏的内边距,再加上`.padding(bottom = 10.dp)`设定内容与屏幕底部的距离,以完成全面的布局适配。示例代码采用Kotlin。
127 15
|
4月前
|
存储 API Android开发
kotlin开发安卓app,使用webivew 触发 onShowFileChooser, 但只能触发一次,第二次无法触发,是怎么回事。 如何解决
在Android WebView开发中,`onShowFileChooser`方法用于开启文件选择。当用户只能选择一次文件可能是因为未正确处理选择回调。解决此问题需确保:1) 实现`WebChromeClient`并覆写`onShowFileChooser`;2) 用户选择文件后调用`ValueCallback.onReceiveValue`传递URI;3) 传递结果后将`ValueCallback`设为`null`以允许再次选择。下面是一个Kotlin示例,展示如何处理文件选择和结果回调。别忘了在Android 6.0+动态请求存储权限,以及在Android 10+处理分区存储。
|
4月前
|
存储 移动开发 Android开发
使用kotlin Jetpack Compose框架开发安卓app, webview中h5如何访问手机存储上传文件
在Kotlin和Jetpack Compose中,集成WebView以支持HTML5页面访问手机存储及上传音频文件涉及关键步骤:1) 添加`READ_EXTERNAL_STORAGE`和`WRITE_EXTERNAL_STORAGE`权限,考虑Android 11的分区存储;2) 配置WebView允许JavaScript和文件访问,启用`javaScriptEnabled`、`allowFileAccess`等设置;3) HTML5页面使用`<input type="file">`让用户选择文件,利用File API;
|
5月前
|
开发框架 小程序 前端开发
uni-app前端应用开发框架
uni-app对做移动端开发的来说应该无人不知、无人不晓了吧?!从名字就能看出来这个框架要干啥,unify app——没错,就是统一前端应用开发,不管你是小程序、app、还是H5、公众号,用这个框架都能做。uni-app让开发者编写一套代码,就可以编译为安卓app、ios app、微信小程序、抖音小程序、支付宝小程序等十几个平台,而且马上支持纯血鸿蒙了,这简直是个人、开发工作室、小型开发公司的福音,开发一些常规的app、小程序,用这个框架足够了。
70 7
|
1月前
|
JSON 小程序 JavaScript
uni-app开发微信小程序的报错[渲染层错误]排查及解决
uni-app开发微信小程序的报错[渲染层错误]排查及解决
484 7

热门文章

最新文章