Различные способы создания плавающей кнопки действия

В современных стандартах пользовательского интерфейса приложения плавающая кнопка действия (FAB) служит основной кнопкой приложения. Обычно это самая заметная и доступная кнопка, выполняющая важные функции приложения, например создание новой заметки для приложения для создания заметок или нового поста для приложения для социальных сетей.

Этот туториал является частью моей серии SwiftUI Tutorial.

Руководство предполагает, что вы уже умеете работать с кнопками в SwiftUI. В принципе легко создать FAB в SwiftUI с образом системы. Запишите этот код внутри ContentView:

struct ContentView: View {
    
    var body: some View {
        
        Button(action: {
            //Place your action here
        }) {
            Image(systemName: "plus.circle.fill")
                .font(.system(size: 100))
                .foregroundColor(.purple)
                .shadow(color: .gray, radius: 0.2, x: 1, y: 1)
                .padding()
        }
        
    } //body
    
} //ContentView

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

Совмещение с другими представлениями

Когда дело доходит до внешнего вида, FAB обычно находится поверх другого вида, чтобы создать плавающий эффект. Предпочтительно прокручиваемый, чтобы все еще можно было получить доступ к закрытым элементам. Давайте сделаем что-то подобное, встроив кнопку с ZStack вот так:

struct ContentView: View {
    
    var body: some View {
        
        ZStack {
            
            Button(action: {
                //Place your action here
            }) {
                Image(systemName: "plus.circle.fill")
                    .font(.system(size: 100))
                    .foregroundColor(.purple)
                    .shadow(color: .gray, radius: 0.2, x: 1, y: 1)
                    .padding()
            }
            
        } //ZStack
        
    } //body
    
} //ContentView

Если вы впервые имеете дело со стеками и встраиванием представлений, настоятельно рекомендую сначала пройти этот туториал.

Теперь добавим прокручиваемый вид с текстом. В этом уроке мы будем использовать длинный макет текста. Вставьте эту константу вне ContentView:

let sampleText = """
Lorem ipsum dolor sit amet. Cum enim sapiente ut officiis perspiciatis qui tenetur placeat? Et similique corporis ut quia nobis ex error aperiam ut amet deleniti et dolorum inventore non quam eaque. Aut consequatur adipisci aut placeat vitae et voluptate laboriosam aut harum deleniti ut quia enim id recusandae dolores. Hic dolorem sunt aut vitae consequatur et numquam sint. Vel expedita ipsa hic repudiandae eveniet aut fugit fugiat.

Qui neque sequi et consequatur fugit eos impedit libero. Eos velit maiores aut reprehenderit maxime qui dolores dicta est quasi illo et aspernatur impedit. A minus corporis sint sapiente non nemo dolorem ut officia ut odio natus et nobis dignissimos eos dicta asperiores. Et incidunt esse eos nisi repudiandae aut commodi optio sit ipsam distinctio et incidunt voluptatem rem dolorem molestiae qui reiciendis ullam. Aut galisum incidunt et maxime commodi qui odit dolorum et vitae aspernatur. Vel possimus aspernatur cum corporis dolorum consequuntur modi cum alias voluptates ea quia quia. Eum quam consequatur in galisum enim et esse error nam magni quas. Ut consequuntur similique est fugiat sapiente hic eveniet vero quo perspiciatis dolorum. Et alias pariatur ea dolor corrupti quo iusto vitae ut voluptas vitae ut reiciendis recusandae sed similique illo.

Nam maxime impedit et dolorem voluptas qui neque iure. Hic amet tenetur ad voluptatum fugit et voluptatem nesciunt. In nesciunt illo qui voluptas molestias qui dolorem voluptas sit iusto consequatur a magni maxime. Quo galisum accusamus id omnis maxime qui labore molestiae. Recusandae molestias et sequi iure a reiciendis neque sit facilis fuga sit fuga omnis qui reiciendis totam rem omnis eius? Sed molestias nulla qui reprehenderit quibusdam est ipsam iusto est iste enim et nihil maxime ea atque vitae! Et recusandae quos eum nihil ducimus est dolorem quaerat qui rerum iusto.
"""

Затем добавьте TextView и ScrollView внутрь ZStack ContentView следующим образом:

struct ContentView: View {
    
    var body: some View {
        
        ZStack {
            
            ScrollView {
                Text(sampleText)
                    .padding()
            }
            
            Button(action: {
                //Place your action here
            }) {
                Image(systemName: "plus.circle.fill")
                    .font(.system(size: 100))
                    .foregroundColor(.purple)
                    .shadow(color: .gray, radius: 0.2, x: 1, y: 1)
                    .padding()
            }
            
        } //ZStack
        
    } //body
    
} //ContentView

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

Хотя приложение работает по назначению, пользовательский интерфейс действительно плохой. FAB обычно размещают под экраном, чтобы он был легко доступен и не мешал контенту. Отредактируйте выравнивание ZStack по низу следующим образом:

struct ContentView: View {
    
    var body: some View {
        
        ZStack(alignment: .bottom) {
            
            ScrollView {
                Text(sampleText)
                    .padding()
            }
            
            Button(action: {
                //Place your action here
            }) {
                Image(systemName: "plus.circle.fill")
                    .font(.system(size: 100))
                    .foregroundColor(.purple)
                    .shadow(color: .gray, radius: 0.2, x: 1, y: 1)
                    .padding()
            }
            
        } //ZStack
        
    } //body
    
} //ContentView

Запустите приложение еще раз. Теперь это выглядит лучше.

Исходный код доступен на Github. Просто нажмите на эту ссылку.

Кнопка создания круга

В нашем предыдущем примере мы использовали встроенный системный образ для создания круглой кнопки. Однако он имеет некоторые ограничения. Если вы используете системное изображение, такое как «фото», оно выглядит не очень хорошо. Позвольте мне показать вам, изменив код следующим образом:

Button(action: {
    //Place your action here
}) {
    Image(systemName: "photo")
        .font(.system(size: 100))
        .foregroundColor(.purple)
        .shadow(color: .gray, radius: 0.2, x: 1, y: 1)
        .padding()
}

Не выглядит хорошо, верно?

Есть также те, кто не предпочитает отверстия в пуговицах. Я имею в виду вот этот:

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

Используя ту же кодовую базу, что и в предыдущем примере. Измените ImageView, изменив символ SF, который мы используем (plus), затем обработайте системное изображение как изображение, где мы делаем его изменяемым по размеру, масштабируемым для заполнения и настраиваем его размер с помощью модификатора кадра. Вот код:

Image(systemName: "plus")
    .resizable()
    .scaledToFill()
    .frame(width: 50, height: 50)
    .padding(30)

Мы также добавили некоторые отступы, чтобы дать некоторое пространство между изображением и рамкой.

Он еще не выглядит круглым, верно? Потому что мы еще не закончили. Что мы только сделали, так это изменили внешний вид изображения. Мы еще не модифицировали кнопку. Поместите этот модификатор под вид кнопки:

.background(.purple)
.foregroundColor(.white)
.cornerRadius(.infinity)
.padding()

Здесь мы настраиваем цвета и устанавливаем для угла angleRadius значение бесконечности, чтобы преобразовать кнопку в круглую форму. Теперь вот скриншот исходного кода на случай, если вы заблудились.

Запустите код сейчас. Теперь приложение выглядит так, как показано на рисунке 7.

Давайте попробуем снова использовать «фото» в SF Symbols с нашим новым исходным кодом кнопки.

Button(action: {
    //Place your action here
}) {
    Image(systemName: "photo")
        .resizable()
        .scaledToFill()
        .frame(width: 50, height: 50)
        .padding(30)
}
.background(.purple)
.foregroundColor(.white)
.cornerRadius(.infinity)
.padding()

Выглядит лучше по сравнению с тем, что на рисунке 5.

Бонусный контент: Размещение FAB с правой стороны

Вы правильно прочитали. Мы еще не закончили. Вы заметите, что FAB многих часто используемых приложений расположен справа, вот так:

Для этого вам нужно снова встроить кнопку в HStack, а затем поместить структуру Spacer() перед кнопкой. Вот код:

struct ContentView: View {

    var body: some View {

        ZStack(alignment: .bottom) {

            ScrollView {
                Text(sampleText)
                    .padding()
            }

            HStack {
                
                Spacer()
                
                Button(action: {
                    //Place your action here
                }) {
                    Image(systemName: "plus")
                        .resizable()
                        .scaledToFill()
                        .frame(width: 50, height: 50)
                        .padding(30)
                }
                .background(.purple)
                .foregroundColor(.white)
                .cornerRadius(.infinity)
                .padding()
                
            } //HStack

        } //ZStack

    } //body

} //ContentView

Теперь приложение будет выглядеть так, как показано на рисунке 9.

В качестве совета вы также должны отдать должное левшам, предоставив им возможность поместить FAB на левую сторону, например:

Код почти такой же, вам просто нужно сначала поместить кнопку, а затем структуру Spacer, например:

HStack {
    
    Button(action: {
        //Place your action here
    }) {
        Image(systemName: "plus")
            .resizable()
            .scaledToFill()
            .frame(width: 50, height: 50)
            .padding(30)
    }
    .background(.purple)
    .foregroundColor(.white)
    .cornerRadius(.infinity)
    .padding()
    
    Spacer()
    
} //HStack

Я также залил исходный код на github.

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

-Дуга