I'm trying to implement a menu on Apple Watch using SwiftUI but I can't find a way to do it. Even on the interface.storyboard, I can't drag/drop the menu.
Did you manage to make it work with SwiftUI? If yes, how?
I searched online but nothing so far.
Yes, this is possible. It's important to remember that unlike on iOS, a view can have only one single context menu, individual elements within the view can not have their own context menu.
Anyway, to implement a context menu (force touch menu) on Apple Watch with SwiftUI, add the .contextMenu() modifier to top-most view in your body
Example:
var body: some View {
Group {
Text("Hello Daymo")
}
.contextMenu(menuItems: {
Button(action: {
print("Refresh")
}, label: {
VStack{
Image(systemName: "arrow.clockwise")
.font(.title)
Text("Refresh view")
}
})
})
}
Edit the button (or add buttons) as you see fit.
Related
I am new in SwiftUI developing, In a SwiftUI project, I created a list of items then I followed the tips in this link to enabled edit button for this,
https://developer.apple.com/documentation/swiftui/editbutton
It works properly for iPhone interface, But in iPad, It has a very strange behaviour. Look at this video below to see how it works in iPad.
https://imgur.com/a/0CLkqiz
If you check this, the way it shows in iPad, when the Edit button text wants to turn to Done, the text steps forward and also creates a transparency with done and edit while it works properly and smooth and fixed in iPhone. I wonder if there might be any special settings for iPad interface in SwiftUI that would fix this problem.
This is my code for this:
struct QRCreator: View {
#State var showingCreateView = false
#State public var fruits = [
"Apple",
"Banana",
"Papaya",
"Mango"
]
var body: some View {
NavigationView {
List {
ForEach(fruits, id: \.self) { fruit in
Text(fruit)
}
.onDelete { fruits.remove(atOffsets: $0) }
.onMove { fruits.move(fromOffsets: $0, toOffset: $1) }
}
.navigationTitle("Fruits2")
.navigationBarItems(trailing:
Button(action: {
showingCreateView = true
}){
Image(systemName: "plus.viewfinder")
.font(.largeTitle)
}
)
.toolbar {
EditButton()
}
}
}
and here is ContentView which I define three tabs in it like this
TabView
{
NavigationView{
QRScanner()
}
.tabItem
{
Image(systemName: "qrcode.viewfinder")
Text("Scanner")
}
NavigationView {
QRCreator()
}
.tabItem
{
Image(systemName: "doc.fill.badge.plus")
Text("Creator")
}
NavigationView
{
QRSetting()
}
.tabItem
{
Image(systemName: "gear")
Text("Setting")
}
}
There seem to be two layers at play:
From the screen recording, it would appear that your NavigationView is actually wrapped by another NavigationView (or NavigationStack/SplitView) somewhere further up the view hierarchy in your implementation. Besides the odd layout, this also creates a tricky situation in regards to toolbar items like your buttons, and the EditMode environment value that EditButton manipulates.
There is an iPad-specific animation bug in SwiftUI's implementation of EditButton. When clicked with a mouse/trackpad as in your screen recording, the button briefly shows both labels ("Edit" & "Done") at the same time. This doesn't happen when you tap the button directly.
It is only when issues 1 & 2 collide, that I actually run into the more problematic behavior that you've captured: the button jumps and the list also jumps.
If I keep everything as you have shown it (including the doubled-up NavigationViews), but tap the button instead of clicking it with a cursor, things seem fine (although I would expect other possible issues down the road).
If I get rid of the outer NavigationView, but click the button, the button itself still exhibits a slightly odd animation, but it is nowhere near as bad as before. And most importantly, the list animates and behaves correctly.
I tried a couple of approaches to work around the button's remaining animation bug, but nothing short of re-implementing a custom edit button worked.
PS: I know you might've already come across this, but since you said that you're just starting out with iOS 16 introduced new views and APIs for navigation (and in typical fashion for SwiftUI's documentation, older pages like the one for EditButton have not been updated). Depending on how complex your app is, switching later on can be a bit of a pain, so here's a good WWDC video introducing the new API: The SwiftUI cookbook for navigation as well as some blog posts.
I am creating a iOS app with XCode. All source code has been written and compiled.
The app runs in the iOS simulator.
The user interface was created in SwiftUI and it appears as expected.
The navigation seems to be working across the screens but I cannot have the menu as designed and I see a double toolbar where the back button appears.
The navigation happens by NavigationLinks associated to buttons.
If I navigate one screen deep I have a back button and a back icon. It seems that the back button is a menu in fact.
If I navigate two screens deep the back button shows a menu with two back options, one lets the user navigate back one level, the other lets the user navigate back two levels.
The main problem is that in the main screen no menu appears.
It doesn't depend on the content of the main view. Indeed if it is stripped down from the View still I do not have the menu, but I do not have the double toolbar either.
var body: some View {
NavigationView {
VStack{
Text("HELLO")
/*here was a sort of master-detail layout*/
}
}.navigationViewStyle(StackNavigationViewStyle()).navigationTitle("SwiftUI").toolbar {
ToolbarItem(placement: .primaryAction) {
Menu
{ //this is what the menu content is like but it never appeared
NavigationLink(destination:HelpView())
{ Label(help_menu_item, systemImage: "")
}
Button(action: {}) {
Label(liability_disclaimer_menu_item, systemImage: "")
}
Button(action: {}) {
Label(about_menu_item, systemImage: "")
}
//other buttons
}//menu
label: {
Label("Menu", systemImage: "ellipsis")
}
}
}
} //body
What changes or checks can be done? I want the menu and a single toolbar.
I also tried commenting things and trying step by step additions but even the simplest case does not work.
Put the toolbar modifier on the top-level view within the NavigationView, not on the NavigationView itself.
SwiftUI helpfully gives you NavigationView which easily lets you define a sidebar and main content for iPad apps that automatically collapse for iPhones.
I have an app and everything works as expected except on iPad, in portrait mode, the sidebar is hidden by default and you are forced click a button to show it.
All I want is to force the sidebar to always be visible, even in portrait mode. And make it work the same way as the settings app.
I’m even willing to use a UIKit view wrapped for SwiftUI, but wrapping NavigationController seems very very challenging.
Is there a better way?
Without your specific code I can't be sure but I think you are describing the initial screen that shows on iPad. That is actually a "ThirdView". You can see it with the code below.
And I am answering the "better way" portion of your question. Which for me is a way of just "graciously" dealing with it.
struct VisibleSideBar2: View {
var body: some View {
NavigationView{
List(0..<10){ idx in
NavigationLink("SideBar \(idx)", destination: Text("Secondary \(idx)"))
}
Text("Welcome Screen")
}
}
}
It is even more apparent if you have a default selection in your "Secondary View" because now you have to click "Back" twice to get to the SideBar
struct VisibleSideBar1: View {
#State var selection: Int? = 1
var body: some View {
NavigationView{
List(0..<10){ idx in
NavigationLink(
destination: Text("Secondary \(idx)"),
tag: idx,
selection: $selection,
label: {Text("SideBar \(idx)")})
}
Text("Third View")
}
}
}
A lot of the "solutions" out there for this just turn the NavigationView into a Stack but then you can't get the double column.
One way of dealing with it is the what is depicted in VisibleSideBar2. You can make/embrace a nice "Welcome Screen" so the user isn't greeted with a blank screen and then the natural navigation instincts kick in. You only see the "Welcome Screen" on iPad Portrait and on Catalyst/MacOS where Stack is unavailable.
Or you can bypass the third screen by using isActive in a NavigationLink and using the Sidebar as a menu like View
struct VisibleSidebar3: View{
#State var mainIsPresented = true
var body: some View {
NavigationView {
ScrollView{
NavigationLink(
destination: Text("Main View").navigationTitle("Main"),
isActive: $mainIsPresented,
label: {
Text("Main View")
})
NavigationLink("List View", destination: ListView())
}.navigationTitle("Sidebar")
//Not visible anymore
Text("Welcome Screen")
}
}
}
struct ListView: View{
var body: some View {
List(0..<10){ idx in
NavigationLink("SideBar \(idx)", destination: Text("Secondary \(idx)"))
}.navigationTitle("List")
}
}
Like I said my answer isn't really a way of "fixing" the issue. Just dealing with it. To fix it we would have to somehow dismiss the "Third Screen/Welcome Screen". Then manipulate the remaining UISplitViewController (Several SO questions on this) to show both the SideBar/Master and the Detail View.
In UIKit it seems to have been done a lot, if you search SO, you will find a way to create a UISplitViewController that behaves like Settings.
I am just wondering what are a component to make a Ui design card for ios apps? cause I saw a lot of these cool card design on pinterest and I was wondering how to make it. Like what are the component to make such a design.
I surf the web and found that mostly they using the new SwiftUI to make that kinda design, but i was wondering is there any possible way to make it with just a regular Storyboard? and i still don't get it the component like is it using button that custom design with Xib or it using regular tableview or what?
If there's any good Library from cocoapods I would like to know either.
this is the type of card design that I want to ask :
[
also there's a link of the kinda same design as well that I saw from pinterest :
https://pin.it/694Q8hb
If anyone knows how to make this with a standard Storyboard, like what the components are and maybe if there are any libraries from cocoapods please let me know okay, cause i wanna make this type of design for my thesis, which I'm already half way of development and I just want to make a good design, and I think this card design type looks perfect on my apps. Cheers Guys :)
This can be done pretty easily in SwiftUI. You can use a VStack (or LazyVStack or LazyVGrid) to set up the list view (much easier than TableViews) and then make a custom, reusable view that looks like one of the views and set it as the Label in a Button. Here's some code (simplified) to get you started:
import SwiftUI
struct CustomView: View {
var body: some View {
VStack {
Button(action: {
print("First button pressed")
}, label: {
CustomRowView(buttonTitle: "First Button")
})
Button(action: {
print("Second button pressed")
}, label: {
CustomRowView(buttonTitle: "Second Button")
})
Button(action: {
print("Third button pressed")
}, label: {
CustomRowView(buttonTitle: "Third Button")
})
Spacer()
}
.padding()
}
}
struct CustomRowView: View {
#State var buttonTitle: String
var body: some View {
Text(buttonTitle)
.frame(maxWidth: .infinity)
.foregroundColor(.white)
.padding(.vertical, 40)
.background(Color.blue)
.cornerRadius(12)
}
}
struct CustomViewsz_Previews: PreviewProvider {
static var previews: some View {
CustomView()
}
}
The easiest way to get the look from those images is a UIView with:
A custom background
Set the corner radius with view.layer.cornerRadius
A shadow effect
UILabels and UIImageViews as children views
Probably a custom touchesBegan and touchesEnded implementation to make it behave like a button.
The views can be contained in a tableview, removing the custom dividers and stuff.
Also:
Code reuse is your friend! Put these specifications in a reusable class that you can reuse whenever you need that design.
I am Giving you the view hierarchy I hope you understand it.
Addressing First Screen from first Pic
View
TableView
Section 1 : User Profile
Section 2 : Bucket
TableViewCell.xib
Header
CollectionView
CollectionViewCell1.xib
Section 3 : Shots
TableViewCell.xib
Header
CollectionView
CollectionViewCell2.xib
Addressing the Second Screen from first pic
View
CollectionView for Options (change tableview datasource on didSelectItem)
TableView
TableViewCell.xib
Addressing Screen from Second pic
View
TableView
Header
TableViewCell
Label
CollectionView
CollectionViewCell
in the HIG Apple writes: In iOS 14 and later, a button can display a pull-down menu that lists items or actions from which people can choose
This is exactly what I want for my project. This picture where they have a "more" bar button with a drop-down menu fits the bill perfectly. Does anyone have an example, though, of how to create a pull-down menu (not context-menu) from a button with SwiftUI?
You can simply use the Menu view that is new for iOS in iOS 14.
It acts as a button and when pressed presents the context menu. You can use a Label if you want an image and even nest different views, as shown in the
example in the documentation.
struct ContentView: View {
#State var text = "Hello World"
var body: some View {
NavigationView {
Text("Hello World")
.navigationTitle("Hello")
.navigationBarItems(trailing: {
Menu {
Button(action: { text = "Hello there" }) {
Label("Hello", systemImage: "pencil")
}
} label: {
Image(systemName: "ellipsis.circle")
}
}())
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
Instead of navigationBarItems one should probably use toolbar, however I found that to be quite unreliable starting with Beta 4.