Is it possible to include a TabView in SwiftUI that doesn’t change views? I need a bottom menu bar that has 4 items in, but these items do not all need to move to a new view. Can I change the expected behaviour of TabView and utilise the buttons it provides or do I need to just make my own?
If you're using the newest beta (2020), you could use a toolbar.
On iOS you can set the placement of the a ToolbarItem as the bottom bar, and make look similar to a bottom tab bar. Back in UIKit you would probably have used a toolbar as well, since TabBars are associated with navigation.
Anyway, here's an example:
HStack {
ForEach(1..<5) { number in
Text("\(number)")
}
}
.toolbar(items: {
ToolbarItem(placement: .bottomBar) {
Button("Test", action: {})
}
})
Add a toolbar modifier to your view, then add the items with whatever content you want. Since the ToolbarItem uses a view builder, you can give it any view.
If you want multiple buttons spread out nicely, replace the Button inside the ToolbarItem with an HStack and have multiple buttons/spacers/whatever you need to get the layout you want.
Note: the .bottomBar placement might not be available on all platforms
Related
I am trying to display a two column NavigationView in my app exactly like the settings on the iPad. With no way to collapse the sidebar on an iPad. I would have thought using a NavigationView with DoubleColumnStyle would work but it doesn't and it's deprecated. I can use a NavigationSplitView like before to control the initial look however the user is still able to collapse the navigation sidebar.
I thought there would be a simple solution to this but have been looking for a while and haven't found any approach that works.
So far I have the following:
struct SettingsView: View {
#State private var columnVisibility = NavigationSplitViewVisibility.doubleColumn
var body: some View {
NavigationSplitView(columnVisibility: $columnVisibility) {
Text("Sidebar")
} detail: {
Text("Detail")
}
}
}
Here both the icon in the top left to hide the sidebar is generated automatically and also dragging the sidebar to the left closes it.
I'm making a recipe app in SwiftUI and I'm trying to add a keyboard toolbar to only specific TextFields, but it applies to every TextField even though I added the toolbar to a specific TextField.
Here is my code for the toolbar.
ForEach(ingredients.indices, id: \.self) { index in
TextField("Add Ingredient", text: $ingredients[index].ingredient)
.toolbar {
ToolbarItem(placement: .keyboard) {
KeyboardToolbarView(text:$ingredients[index].ingredient)
}
}
}
This works but it's applied to every time whenever I am typing in a TextField. I only want it to be applied to specific TextFields throughout the whole app. Here is a screenshot of the toolbar.Image of working toolbar
I only want the toolbar to show when the user is typing in one of the ingredient TextFields not any of the other ones, but if I go to type in any of the others the toolbar is present. Is there anyway to only show it for specific TextFields or hide it on the others?
I have selectable Text, so when the user right clicks the text they see an edit menu with various options. I'd like to add some custom options to this menu but I'm not sure how to do this. If I can't add custom options, I'm also ok with completely replacing the menu altogether with my own custom menu.
Here is some sample code:
struct TestView: View {
var body: some View {
Text("Hello")
.textSelection(.enabled)
}
}
Here are some things I've tried:
adding a context menu with .contextMenu(). But right clicking will still only show the edit menu and not the context menu.
I've also tried disabling overriding right click behavior to stop the native edit menu from showing up (i.e. Override right click in SwiftUI), but that doesn't work.
I select the systemImage "map" and "person" for the tabItem, but the images are in filled format which must be in hollow format. What's the reason?
struct TestView: View {
var body: some View {
TabView {
Text("Map!")
.tabItem {
Label("Map", systemImage: "map")
}
Text("Profile")
.tabItem {
Label("Person", systemImage: "person")
}
}
}
}
Xcode: 13.1
SF Symbols: 3.1
This is standard SwiftUI behaviour in iOS 15, as it implements by default the recommendations from Apple’s Human Interface Guidelines, which says tab bars should use filled variants of SF Symbols, while sidebars on iPad should use the outline variant.
The effect is achieved by iOS automatically applying the .symbolVariants environment value, as noted in the symbol variants documentation:
SwiftUI sets a variant for you in some environments. For example, SwiftUI automatically applies the fill symbol variant for items that appear in the content closure of the swipeActions(edge:allowsFullSwipe:content:) method, or as the tab bar items of a TabView.
If you absolutely want to get rid of the fill mode, it’s deliberately made tricky but not impossible. You have to override the supplied \.symbolVariants environment variable directly on the Label element, inside your tabItem declaration:
Text("Map!")
.tabItem {
Label("Map", systemImage: "map")
.environment(\.symbolVariants, .none)
}
Using the .symbolVariants(.none) modifier, or trying to set the environment value higher up the view graph, won’t work.
Now that you see how to override the effect, I would still advise using the filled forms in the tab bar. Given that the tab bar no longer has a background colour difference from the rest of the page in many cases, the extra visual weight given to tab items by use of the filled variant lends the right amount of visual weight to those elements.
I am testing out the SwiftUI's feature .searchable(). But seems that the search bar would always has a space above it. Since the searchable is embedded in the naviagation bar, I understand the space as where the Navigation bar items go. But is there a way to remove that space and make the searchbar looking like that in Instagram? I have tried changing the navbar style to inline,as the code below, but there is still some space above it. Is there any logic behind the search bar's position?
NavigationView{
SearchView(searchText: $searchText)
.navigationBarTitleDisplayMode(.inline)
}
.searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always), suggestions: {
ForEach(searchResults, id: \.self){result in
Text(result).searchCompletion(result)
}
})
The Space Marked with Brown