SwiftUI极简教程13:NavigationView导航栏使用

简介: SwiftUI极简教程13:NavigationView导航栏使用

在本章中,你将学会如何使用NavigationView构建基础的导航栏,以及基于导航栏的页面跳转。


如果你恰好用过UIkit,应该尝试过用storyboard或者UINavigationController来构建页面导航。


而在SwiftUI中,我们使用NavigationView,而它的使用方法和上一章List基本一样。

本章节将分成3个部分讲解。


1、构建一个简单的导航栏;

2、基于导航栏的页面跳转;

3、导航栏自定义返回;


第一部分:构建一个简单的导航栏


我们先尝试在原来的List上增加NavigationView看看导航栏的效果。

UI稿如下:

image.png

首先,我们先创建一个新项目,命名为SwiftUINavigationView。

image.png

然后,我们把上一章的代码拿过来作为示例讲解。

代码如下:

import SwiftUI
struct ContentView: View {
    // 定义数组,存放数据
    var Messages = [
        Message(name: "这是微信", image: "weixin"),
        Message(name: "这是微博", image: "weibo"),
        Message(name: "这是QQ", image: "qq"),
        Message(name: "这是电话", image: "phone"),
        Message(name: "这是邮箱", image: "mail")
    ]
    var body: some View {
        // 列表
        List(Messages) { Message in
            HStack {
                Image(Message.image)
                    .resizable()
                    .frame(width: 40, height: 40)
                    .cornerRadius(5)
            Text(Message.name)
            }
        }
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
struct Message: Identifiable {
    var id = UUID()
    var name: String
    var image: String
}

image.png

NavigationView的构建和List方法一样,将我们需要的内容包裹在NavigationView里面就行了。


NavigationView{  }
复制代码


这里注意的是,需要把整个List包裹起来。

包裹完成后,我们可以看到整个List顶部留出了导航栏的位置。


//导航栏
NavigationView{
    // 列表
    List(Messages) { Message in
        HStack {
            Image(Message.image)
                .resizable()
                .frame(width: 40, height: 40)
                .cornerRadius(5)
            Text(Message.name)
            }
        }
    }


image.png

我们尝试加个标题,这里我们用的修饰符是:


.navigationBarTitle("我是标题")
复制代码


修饰符需要加在内容最外层,而不是NavigationView外层。

这样,我们就得到了一个拥有大标题的列表。


//导航栏
NavigationView {
    // 列表
    List(Messages) { Message in
        HStack {
            Image(Message.image)
                .resizable()
                .frame(width: 40, height: 40)
                .cornerRadius(5)
            Text(Message.name)
        }
    }.navigationBarTitle("我是标题")
}


image.png

是不是挺简单!

SwiftUI将很多事情都简单化了,以至于我们在使用不同的控件的方法基本都差不多。


第二部分:基于导航栏的页面跳转


下面进阶一下。

我们尝试从一个页面跳转到第二个页面,并且还能返回。

UI稿如下:

image.png

我们先完成第二个页面的内容,然后再从第一个页面点击对应的列表进入第二个页面。

我们在ContentView页面最后创建一个新的页面,命名为DetailView。

代码如下:

//详情页面
struct DetailView: View {
    var message: Message
    var body: some View {
        VStack {
            Image(message.image)
                .resizable()
                .frame(width: 80, height: 80)
            Text(message.name)
                .font(.system(.title, design: .rounded))
                .fontWeight(.black)
            Spacer()
        }
    }
}
复制代码

我们在DetailView里面引用Message数组的数据,将Image图片和Text文字换成数组的参数。

这样我们就可以第一个页面点击哪一个列表,然后就能将对应的图片和文字带入到第二个页面,也就是所谓的传参。

image.png

然后回到第一个页面里。

我们需要点击List列表,然后跳转到第二个页面。

这时候我们需要使用一个新的参数,叫做NavigationLink。

NavigationLink(destination: DetailView()) {
    //点击跳转的内容
}

destination表明我们要跳转的页面,这里我们需要跳转的页面是DetailView。

我们需要点击List里面的一行,然后跳转到第二个页面,因此NavigationLink需要放在List里面,而不是包裹住整个List。

如果NavigationLink包裹住List,那么就变成了点击整个List跳转了,这里我们需要的是点击List单独一行对应跳转。

NavigationView {
    // 列表
    List(Messages) { Message in
        NavigationLink(destination: DetailView(message: Message)) {
            HStack {
                Image(Message.image)
                    .resizable()
                    .frame(width: 40, height: 40)
                    .cornerRadius(5)
                Text(Message.name)
            }
        }
    }.navigationBarTitle("我是标题")
}


image.png

我们可以看到,跳转的目标是DetailView,并且我们把Message结构体的参数传递给了DetailView页面的message变量。

这样就实现了我们Message结构体里的参数传递给message,也就实现了,我们点击的Message是哪一个,DetailView页面的message对应传递哪一个参数。

我们点击模拟器上面的Preview运行下模拟器,尝试点击List其中一行,就可以体验下点击跳转页面,再点击返回到主页的效果。

image.png

科普一个知识点。

我们在常用的App当中看到的顶部导航栏文字是居中的,这是怎么实现的呢?

也很简单,ios默认的是大标题效果(.automatic),也就是:


.navigationBarTitle("我是标题", displayMode: .automatic)
复制代码


我们只需要给.navigationBarTitle("我是标题”)里加入参数控制(.inline),就可以实现文字标题居中效果。


.navigationBarTitle("我是标题", displayMode: .inline)


image.png

好了,至此我们就完成了基于导航栏的页面跳转方式啦!

第三部分:导航栏自定义返回


接下来,让我们看看DetailView页面,我们会发现,这个“返回”的操作似乎没那么好看。

image.png

很多时候,我们的“返回”操作可能是一个图标按钮,也可能是“文字”按钮。

我们有没有办法美化下这个返回首页的操作?

让我们分析下。

我们只需要把系统自带的返回操作隐藏,然后再自己“写”一个返回操作就可以了。

这里我们用到了隐藏导航返回按钮的参数:


.navigationBarBackButtonHidden(true)

image.png

下一步,我们自己写一个返回的按钮,在这里,我们需要用到另一个参数:


.navigationBarItems(leading: Button(action : {
    // 点击按钮后的操作
    }){
    //按钮及其样式
    Image(systemName: "chevron.left")
        .foregroundColor(.gray)
})
复制代码


我们试试用图标按钮作为返回按钮。

这里使用的是系统自带的图片,填充颜色为灰色。

image.png

运行看看,我们可以点击主页列表数据进入详情页。

但是,我们点击返回操作没有反应。

这是因为我们还没有实现返回的方法。

SwiftUI提供了(.presentationMode)内置环境值,我们可以用这个环境值实现返回到前一个视图的操作。


@Environment(\.presentationMode) var mode
复制代码


然后在返回按钮的点击操作时调用环境值的dismiss()函数,就可以实现返回的操作。


self.mode.wrappedValue.dismiss()
复制代码


DetailView页面完整代码如下:


// 详情页面
struct DetailView: View {
    //环境值
    @Environment(\.presentationMode) var mode
    var message: Message
    var body: some View {
        VStack {
            Image(message.image)
                .resizable()
                .frame(width: 80, height: 80)
            Text(message.name)
                .font(.system(.title, design: .rounded))
                .fontWeight(.black)
            Spacer()
        }
        .navigationBarBackButtonHidden(true)
        .navigationBarItems(leading: Button(action : {
            // 点击按钮后的操作
            self.mode.wrappedValue.dismiss()
            }){
            //按钮及其样式
            Image(systemName: "chevron.left")
                .foregroundColor(.gray)
        })
    }
}


image.png

运行下代码,我们发现实现自定义按钮的返回操作啦!

好了,今天的知识点就到这里了。

相关文章
|
2月前
|
容器
QT基础入门——界面布局和常用控件(四)
QT基础入门——界面布局和常用控件(四)
57 0
QT基础入门——界面布局和常用控件(四)
|
2月前
|
XML Java Android开发
Android Studio App开发中高级控件下拉列表Spinner的讲解及实战(附源码 超详细必看)
Android Studio App开发中高级控件下拉列表Spinner的讲解及实战(附源码 超详细必看)
101 0
|
2月前
|
XML Java Android开发
Android Studio App开发中工具栏Toolbar、溢出菜单OverflowMenu、标签布局TabLayout的讲解及实战(实现京东App的标签导航栏,附源码)
Android Studio App开发中工具栏Toolbar、溢出菜单OverflowMenu、标签布局TabLayout的讲解及实战(实现京东App的标签导航栏,附源码)
200 0
|
11月前
Pyside6-第十一篇-QComboBox下拉列表
Pyside6-第十一篇-QComboBox下拉列表
547 0
|
程序员 索引
SwiftUI极简教程18:SwipeCard卡片滑动效果的使用(上)
SwiftUI极简教程18:SwipeCard卡片滑动效果的使用(上)
902 0
SwiftUI极简教程18:SwipeCard卡片滑动效果的使用(上)
|
存储 索引
SwiftUI极简教程19:SwipeCard卡片滑动效果的使用(下)
SwiftUI极简教程19:SwipeCard卡片滑动效果的使用(下)
578 0
SwiftUI极简教程19:SwipeCard卡片滑动效果的使用(下)
|
XML Android开发 数据格式
Material Design 实战 之第二弹——滑动菜单详解&实战(DrawerLayout & NavigationView)
Material Design 实战 之第二弹——滑动菜单详解&实战(DrawerLayout & NavigationView)
Material Design 实战 之第三弹—— 悬浮按钮和可交互提示(FloatingActionButton & Snackbar & CoordinatorLayout)
Material Design 实战 之第三弹—— 悬浮按钮和可交互提示(FloatingActionButton & Snackbar & CoordinatorLayout)
Material Design 实战 之第四弹 —— 卡片布局以及灵动的标题栏(CardView & AppBarLayout)
Material Design 实战 之第四弹 —— 卡片布局以及灵动的标题栏(CardView & AppBarLayout)
|
iOS开发
SwiftUI极简教程08: Button按钮的使用
SwiftUI极简教程08: Button按钮的使用
1172 0
SwiftUI极简教程08: Button按钮的使用