Узнайте, как создать и настроить панель вкладок

Если и есть что-то примечательное, что есть в большинстве популярных мобильных приложений, так это то, что все они используют панель вкладок, которая появляется в нижней части экрана. Что делает панель вкладок, так это то, что она позволяет пользователю удобно переключаться между различными важными разделами приложения. В SwiftUI легко создать пользовательский интерфейс панели вкладок благодаря TabView.

В этом уроке я покажу вам, как создать панель вкладок и настроить ее внешний вид.

Это руководство является частью моей серии Руководство по SwiftUI.

Прежде всего, убедитесь, что новый проект открыт для практики. Вы можете использовать эту ссылку, если вам нужен пошаговый процесс, как это сделать.

Давайте создадим простой TabView, содержащий одну вкладку. Измените ContentView следующим образом:

struct ContentView: View {
    
    var body: some View {
        
        TabView {
            
            Text("Home view")
                .tabItem {
                    Image(systemName: "house.fill")
                }
            
        } //TabView
        
    } //body
    
} //ContentView

Вот как это будет выглядеть на холсте:

Вы разместили все представления внутри TabView. В приведенном выше примере представление, которое мы поместили внутрь, представляет собой текст. Добавляя модификатор .tabItem, мы также устанавливаем, какую кнопку он будет представлять на панели вкладок. В этом примере я использую образ системы в качестве дизайна кнопки вкладки.

Наличие одной вкладки бесполезно, так как это устранит цель использования панели вкладок. Итак, давайте создадим несколько элементов вкладок. Измените код в ContentView следующим образом:

struct ContentView: View {
    
    var body: some View {
        
        TabView {
            
            Text("Home view")
                .tabItem {
                    Image(systemName: "house.fill")
                }
            
            Text("Search view")
                .tabItem {
                    Image(systemName: "magnifyingglass")
                }

            Text("Photo view")
                .tabItem {
                    Image(systemName: "photo.fill")
                }

            Text("Message view")
                .tabItem {
                    Image(systemName: "envelope.fill")
                }

            Text("Profile view")
                .tabItem {
                    Image(systemName: "person.crop.circle.fill")
                }
            
        } //TabView
        
    } //body
    
} //ContentView

Вот как будет выглядеть приложение после изменения кода:

Запустите приложение и попробуйте нажимать вкладки. Вы заметите, что он меняет представления в зависимости от соответствующих элементов вкладок.

Пользовательский интерфейс можно сделать более удобным, добавив метки к каждому элементу вкладки. Давайте добавим немного текста, изменив код в ContentView следующим образом:

struct ContentView: View {
    
    var body: some View {
        
        TabView {
            
            Text("Home view")
                .tabItem {
                    Image(systemName: "house.fill")
                    Text("Home")
                }
            
            Text("Search view")
                .tabItem {
                    Image(systemName: "magnifyingglass")
                    Text("Search")
                }

            Text("Photo view")
                .tabItem {
                    Image(systemName: "photo.fill")
                    Text("Photos")
                }

            Text("Message view")
                .tabItem {
                    Image(systemName: "envelope.fill")
                    Text("Messages")
                }

            Text("Profile view")
                .tabItem {
                    Image(systemName: "person.crop.circle.fill")
                    Text("Profile")
                }
            
        } //TabView
        
    } //body
    
} //ContentView

Вот как это будет выглядеть после модификации кода:

В реальном приложении одна вкладка будет состоять из нескольких представлений. Поэтому лучше всего здесь создавать отдельную структуру для каждой вкладки. Напишите этот код вне ContentView:

struct HomeView: View {
    
    var body: some View {
        
        List(1...50, id: \.self) {
            Text("Content \($0)")
        }
        
    } //body
    
} //HomeView

Это простое представление ForEach List для имитации типичной домашней страницы контентного приложения.

Давайте сделаем еще один отдельный вид. Например, для вкладки фотографий. Создайте еще одну отдельную структуру с этим кодом:

struct PhotosView: View {
    
    private var imageList = [
        "hare.fill",
        "tortoise.fill",
        "pawprint.fill",
        "ant.fill",
        "ladybug.fill"
    ]
    
    var body: some View {
        
        ScrollView(showsIndicators: false) {
            ForEach(imageList, id: \.self) { index in
                Image(systemName: "\(index)")
                    .font(.system(size: 150))
                    .padding()
            }
        }
        
    } //body
    
} //PhotosView

Это скриншот отдельных структур, которые мы написали:

Затем отредактируйте ContentView, заменив представления Home и Photos следующим образом:

struct ContentView: View {
    
    var body: some View {
        
        TabView {
            
            HomeView()
                .tabItem {
                    Image(systemName: "house.fill")
                    Text("Home")
                }
            
            Text("Search view")
                .tabItem {
                    Image(systemName: "magnifyingglass")
                    Text("Search")
                }

            PhotosView()
                .tabItem {
                    Image(systemName: "photo.fill")
                    Text("Photos")
                }

            Text("Message view")
                .tabItem {
                    Image(systemName: "envelope.fill")
                    Text("Messages")
                }

            Text("Profile view")
                .tabItem {
                    Image(systemName: "person.crop.circle.fill")
                    Text("Profile")
                }
            
        } //TabView
        
    } //body
    
} //ContentView

Запустите приложение и попробуйте перейти на разные вкладки, особенно на «Дом» и «Фото».

Настройка цвета панели вкладок

Цвет активного элемента панели вкладок по умолчанию — синий. Допустим, мы хотели изменить его на черный. Вот как это сделать:

TabView {
    //Code
}
.accentColor(.black)

На момент написания этой статьи в SwiftUI еще не было модификатора для настройки цвета панели вкладок. Чтобы изменить его цвет, нам нужно коснуться UITabBar.appearance UIKit, а затем поместить код в init(). Например, мы хотели изменить цвет панели вкладок на systemBlue. Напишите ниже код внутри ContentView:

init() {
    UITabBar.appearance().barTintColor = UIColor.systemBlue
}

По умолчанию невыбранные вкладки окрашены в серый цвет. Допустим, мы хотели изменить его на белый. Вот код:

UITabBar.appearance().unselectedItemTintColor = UIColor.white

Если вам не нравится, чтобы панель вкладок была прозрачной, вы можете установить для параметра opaque значение false следующим образом:

UITabBar.appearance().isOpaque = false

Давайте соберем весь этот код вместе, чтобы создать наш индивидуальный пользовательский интерфейс.

А вот так будет выглядеть приложение:

Программно переключаться между вкладками

Вид вкладок уже запрограммирован на переключение между вкладками в зависимости от того, какой элемент вкладки ему назначен. Как насчет создания кнопки вне панели вкладок, которая имеет ту же функциональность, что и кнопки вкладок. Скажем, кнопка, которая мгновенно перейдет к просмотру сообщений из просмотра профиля, например:

Давайте сначала закодируем дизайн профиля. Вне ContentView создайте отдельную структуру, содержащую этот код:

struct ProfileView: View {
    
    var selection: () -> Void
    
    var body: some View {
        
        VStack {
            
            Image(systemName: "person.crop.circle")
                .font(.system(size: 100))
                .padding()
            
            Button(action: selection) {
                Image(systemName: "envelope.fill")
                    .font(.system(size: 50))
            }
            .padding()
            
        } //ZStack
        
    } //body
    
} //ProfileView

Возвращаясь к ContentView, нам сначала нужна переменная состояние, которая будет содержать значение. Добавьте это внутри ContentView:

@State private var selection = 0

Затем добавьте метод в TagView и привяжите туда переменную выбора. Измените код следующим образом:

TabView(selection: $selection)

Затем определите значение тега для каждого элемента вкладки. Добавьте модификатор .tag для каждого представления, а также замените Text("Profile") на ProfileView, который мы создали ранее. Код будет выглядеть так:

TabView(selection: $selection) {
    
    HomeView()
        .tabItem {
            Image(systemName: "house.fill")
            Text("Home")
        }
        .tag(0)
    
    Text("Search view")
        .tabItem {
            Image(systemName: "magnifyingglass")
            Text("Search")
        }
        .tag(1)

    PhotosView()
        .tabItem {
            Image(systemName: "photo.fill")
            Text("Photos")
        }
        .tag(2)

    Text("Message view")
        .tabItem {
            Image(systemName: "envelope.fill")
            Text("Messages")
        }
        .tag(3)

    ProfileView(selection: {

    })
        .tabItem {
            Image(systemName: "person.crop.circle.fill")
            Text("Profile")
        }
        .tag(4)
    
} //TabView

Недостающая часть здесь — это действие, которое вызовет переключение вкладок. Измените ProfileView и добавьте этот код:

selection = (selection + 4) % 5

Позвольте мне разбить важную часть кода. % 5 — это место, где вы указываете количество элементов вкладок на панели вкладок. Например, если у вас их всего 3, напишите % 3. Потом под скобками где выбор + та вкладка куда вы хотели переключиться. Просмотр сообщения — 4-й, поэтому мы поставили 4.

Запустите приложение сейчас и попробуйте нажать кнопку в режиме просмотра профиля. Он должен переключаться в режим просмотра сообщений каждый раз, когда нажимается кнопка.

Я загрузил весь исходный код этого проекта на github. Просто нажмите на эту ссылку.

Да пребудет с вами код,

-Дуга