I wanted to use the PageTabViewStyle
added in SwiftUI 2.0, so I created something like a custom tab.
I would like to make something like this. GitHub is here. https://github.com/hoshi005/custom-tab
--I'm using SDWebImageSwiftUI because I wanted to use animated gifs. -Piyokoyarou uses an animated gif file.
Since the animated gif file is named and placed like this, the enum is defined by matching the names.
enum TabItem: String, CaseIterable {
case piyo
case pen
case neko
case tobipen
var name: String {
"\(self.rawValue).gif"
}
}
I added TabItemView
to represent each tab and defined it as follows.
struct TabItemView: View {
let tabItem: TabItem
@Binding var selected: TabItem
var body: some View {
//SDWebImageSwiftUI import required.
AnimatedImage(name: tabItem.name)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 40)
.onTapGesture {
selected = tabItem //Tap to select yourself.
}
}
}
In the main ContentView
, the tab view is defined as follows.
struct ContentView: View {
//Tab selection and initial values.
@State private var selected: TabItem = .piyo
var body: some View {
//Tab view part.
HStack {
ForEach(TabItem.allCases, id: \.self) { tabItem in
TabItemView(tabItem: tabItem, selected: $selected)
}
}
.padding(.vertical, 10.0)
.padding(.horizontal, 20.0)
.background(Color.white.clipShape(Capsule()))
.shadow(color: Color.black.opacity(0.3), radius: 5, x: -5, y: 5)
}
}
Here is the finished product. At this rate, you don't really understand the selection status.
Rewrite TabItemView
as follows to switch the appearance when selected / not selected.
--Adjust frame --Adjust padding --Adjust offset --Animation is added to the tapping process
var body: some View {
AnimatedImage(name: tabItem.name)
.resizable()
.aspectRatio(contentMode: .fit)
//Adjust the size and spacing according to the selection status.
.frame(width: tabItem == selected ? 100 : 40)
.padding(.vertical, tabItem == selected ? -30 : 0)
.padding(.horizontal, tabItem == selected ? -14 : 16)
.offset(y: tabItem == selected ? -15 : 0)
.onTapGesture {
withAnimation(.spring()) {
selected = tabItem //Tap to select yourself.
}
}
}
It looks like this. You can now see the selection status at a glance.
Adjust the appearance of ContentView
.
--Enclose the whole with ZStack
--Place Color ("bg"). IgnoresSafeArea ()
on the back to make it the background color
--Place the tab view part at the bottom of the screen using VStack
and Spacer
var body: some View {
ZStack {
//Background color.
Color("bg").ignoresSafeArea()
VStack {
Spacer(minLength: 0)
//Tab view part.
HStack {
ForEach(TabItem.allCases, id: \.self) { tabItem in
TabItemView(tabItem: tabItem, selected: $selected)
}
}
.padding(.vertical, 10.0)
.padding(.horizontal, 20.0)
.background(Color.white.clipShape(Capsule()))
.shadow(color: Color.black.opacity(0.3), radius: 5, x: -5, y: 5)
}
}
}
It looks like this. It's becoming more like that.
I have prepared a tab, so I will switch the screen in conjunction with this tab.
First, prepare the screen part with a dummy. It's suitable, so I think you can make it as you like.
struct HomeView: View {
var body: some View {
Text("Home")
.font(.largeTitle)
.fontWeight(.heavy)
.foregroundColor(.red)
}
}
struct ListView: View {
var body: some View {
Text("List")
.font(.largeTitle)
.fontWeight(.heavy)
.foregroundColor(.green)
}
}
struct SearchView: View {
var body: some View {
Text("Search")
.font(.largeTitle)
.fontWeight(.heavy)
.foregroundColor(.blue)
}
}
struct SettingView: View {
var body: some View {
Text("Setting")
.font(.largeTitle)
.fontWeight(.heavy)
.foregroundColor(.yellow)
}
}
Finally, define these Views with TabView
to work with your custom tabs.
--By specifying selected
in the argument of TabView
, it works with the custom tab.
--By specifying PageTabViewStyle
, you can switch by swiping horizontally.
ZStack {
//Background color.
Color("bg").ignoresSafeArea()
//The main screen part is defined by TabView.
TabView(selection: $selected) {
HomeView()
.tag(TabItem.piyo)
ListView()
.tag(TabItem.pen)
SearchView()
.tag(TabItem.neko)
SettingView()
.tag(TabItem.tobipen)
}
//Use PageTab style(Indicator is hidden).
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
VStack {
//abridgement.
}
}
I get the impression that tab definition is quite easy, but I'm happy that it's even easier to create a "switching UI". It seems that the same thing can be done with the switching view created by this article. Please try it if you like.
Recommended Posts