I would like to modify the font size and color of the text in an Alert in SwiftUI. Adding
modifiers does not seem to work. I must be missing something simple here. I created
the most basic of alert screens, added text modifiers and they are ignored. I created
my own view to show the kind of result I would like. Obviously, since I can make what
I want, I could go that route though it is a lot of work and it just seems like the
built-in alert ought to be able to do this.
struct ContentView: View {
#State private var showAlert = false
#State private var showMyAlert = false
var body: some View {
GeometryReader { geo in
ZStack {
VStack {
Text("Make Some Font Business")
.font(.title)
.foregroundColor(.red)
Button(action: {
self.showAlert.toggle()
}) {
Text("Toggle System Alert")
}
Button(action: {
self.showMyAlert.toggle()
}) {
Text("Show MyAlert")
}
}
if self.showMyAlert {
MyAlert(showMyAlert: self.$showMyAlert)
.animation(.easeInOut)
}
}//vstack
.frame(width: geo.size.width, height: geo.size.height)
.background(self.showMyAlert ? Color.gray.opacity(0.2) : Color.white)
.alert(isPresented: self.$showAlert) {
Alert(title: Text("Important"),
message: Text("This text should be large and it should be green")
.font(.system(size: 36))
.foregroundColor(.green),
dismissButton: .default(Text("Ok")))
}//.alert
}//geo
.edgesIgnoringSafeArea(.all)
}
}
struct MyAlert: View {
#Binding var showMyAlert: Bool
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 20)
.frame(width: 275, height: 180, alignment: .center)
.foregroundColor(.white).opacity(1.0)
VStack {
Text("Important")
//.fontWeight(.bold)
.font(.system(size: 20))
Divider()
Text("This text should be large and it should be green")
.font(.system(size: 20))
.foregroundColor(.green)
.multilineTextAlignment(.center)
Divider()
Button(action: {
self.showMyAlert.toggle()
} ) {
Text("Ok")
.foregroundColor(.blue)
.font(.system(size: 20))
}
}//vstack
.frame(width: 225, height: 150, alignment: .center)
}//zstack
}
}
Any guidance would be appreciated.
Xcode 11.3.1 (11C504)
As I know modifiers did not work on build-in Alert in SwiftUI. It's a standard system font and size to show on default alert view and not changeable like UIKit default alert. I think the best way is implementing the custom modifier to show the custom alert
Related
I'm struggling with a view where I want to have multiple pickers embedded in
other views. When I wrap the pickers in a Form, I get the desired behavior for the
picker but there is a lot of extra space around the pickers that I can't seem to
automatically adjust.
This is an example - the space in the red outline seems to be determined by the other
view elements not the size of the picker.
I can, of course, hard-code a frame height for the Form but that is trial and error
and would only be specific to the device and orientation. I have tried multiple
versions of Stacks inside Stacks with padding, GeometryReader etc, but I have not come up with any
solution. As an aside, I DO want the picker labels, otherwise I could just remove
the Form.
I also tried setting UITableView.appearance().tableFooterView in an init() but that did not work either.
Here is a simplified version:
struct ContentView4: View {
#State var selectedNumber1: Int = 1
#State var selectedNumber2: Int = 2
#State var selectedNumber3: Int = 3
var body: some View {
NavigationView {
VStack(alignment: .leading) {
HStack {
Spacer()
Text("Compare up to 3")
.font(.caption)
Spacer()
}//h
Form {//for pickers
Picker(selection: $selectedNumber1, label: Text("A")) {
ForEach(0..<10) {
Text("\($0)")
}
}//picker
Picker(selection: $selectedNumber2, label: Text("B")) {
ForEach(0..<10) {
Text("\($0)")
}
}//picker
Picker(selection: $selectedNumber3, label: Text("C")) {
ForEach(0..<10) {
Text("\($0)")
}
}//picker
}//form for pickers
.padding(.horizontal, 10)
//.frame(height: 200) //don't want to hard code this
VStack(alignment: .leading) {
HStack {
Text("A")
.frame(width: 100)
Text("B")
.frame(width: 100)
Text("C")
.frame(width: 100)
}
.padding(.horizontal, 10)
ScrollView(.vertical, showsIndicators: false) {
VStack(alignment: .leading){
Text("A title line")
.font(.headline)
.padding(.vertical, 5)
HStack {
Text("Number")
.frame(width: 100)
Text("Number")
.frame(width: 100)
Text("Number")
.frame(width: 100)
}
Text("Another title line")
.font(.headline)
.padding(.vertical, 5)
HStack {
Text("Something")
.frame(width: 100)
Text("Something")
.frame(width: 100)
Text("Something")
.frame(width: 100)
}
Text("A Third title line")
.font(.headline)
.padding(.vertical, 5)
HStack {
Text("More")
.frame(width: 100)
Text("More")
.frame(width: 100)
Text("More")
.frame(width: 100)
}
}
}//scroll
.padding(.horizontal, 10)
}
.navigationBarTitle("Compare Three", displayMode: .inline)
}
}//nav
}//body
}//struct
Interestingly, I am able to get a solution by removing the form and wrapping each
picker in a menu, like this:
Menu {
Picker(selection: $selectedNumber2, label: EmptyView()) {
ForEach(0..<10) {
Text("\($0)")
}
}//picker
} label: {
HStack {
Text("B")
Spacer()
Image(systemName: "chevron.right")
.resizable()
.frame(width: 14, height: 14)
}//h
}//menu label
However, I still like the look of the Form better if I could automatically configure
the space around the Form items.
Any guidance would be appreciated. Xcode 13.4, iOS 15.5
Form (and List) is not meant to be stacked inside other views like this, which is why it has such strange behavior.
Thankfully, it's fairly simple to recreate the stuff you do want using NavigationLink. Here’s a quick example of a couple custom views that do just that:
// drop-in NavigationLink replacement for Picker
struct NavigationButton<Content: View, SelectionValue: Hashable> : View {
#Binding var selection: SelectionValue
#ViewBuilder let content: () -> Content
#ViewBuilder let label: () -> Text
var body: some View {
NavigationLink {
PickerView(selection: $selection, content: content, label: label)
} label: {
HStack {
label()
Spacer()
Text(String(describing: selection))
.foregroundColor(.secondary)
}
.contentShape(Rectangle())
}
.buttonStyle(NavigationLinkButtonStyle())
}
}
// subview for the Picker page, which lets us use `dismiss()`
// to pop the subview when the user selects an option
struct PickerView<Content: View, SelectionValue: Hashable> : View {
#Binding var selection: SelectionValue
#ViewBuilder let content: () -> Content
#ViewBuilder let label: () -> Text
#Environment(\.dismiss) private var dismiss
var body: some View {
Form {
Picker(selection: $selection, content: content, label: label)
.pickerStyle(.inline)
.labelsHidden()
.onChange(of: selection) { _ in
dismiss()
}
}
.navigationTitle(label())
}
}
// recreate the appearance of a List row
struct NavigationLinkButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
HStack {
configuration.label
.frame(maxWidth: .infinity)
Image(systemName: "chevron.right")
.font(.footnote.bold())
.foregroundColor(Color(UIColor.tertiaryLabel))
}
.padding()
.background(
Rectangle()
.fill(configuration.isPressed ? Color(UIColor.quaternaryLabel) : Color(UIColor.systemBackground))
)
}
}
If you like the .insetGrouped style you got using Form, we can replicate that by putting NavigationButton inside a clipped VStack:
VStack(spacing: 0) {
NavigationButton(selection: $selectedNumber1) {
ForEach(0..<10) {
Text("\($0)")
}
} label: {
Text("A")
}
Divider()
NavigationButton(selection: $selectedNumber2) {
ForEach(0..<10) {
Text("\($0)")
}
} label: {
Text("B")
}
}
.clipShape(RoundedRectangle(cornerRadius: 11))
.padding()
.background(Color(UIColor.systemGroupedBackground))
And here’s a screenshot showing my custom views above your original Form.
(And if you like Picker as a popup menu, you could use Menu instead of NavigationLink)
I am trying to create below design using swiftUI but not able to find proper approach.
I tried but my image is not covering back button but coming below to back button
Expected design
VStack(spacing: 16) {
VStack {
ZStack(alignment: .topTrailing) {
Image("defaultImage")
.resizable()
.frame( height: 200)
Button("Cancel", action: {
print("cancel")
})
.padding(12)
}
}
}
My Design :(
You might want to do a lot of try in SwiftUI to get a custom design right. gave it a quick try for you and added comments on the code so you can understand most of what i did.
this is the quick result i got (with a random background i got on internet)
import SwiftUI
struct FirstView: View{
var body: some View{
NavigationView {
VStack{
NavigationLink(destination: BackgroundImageNav()){
Text("Go to the view")
.font(.title)
}
}
}
}
}
struct BackgroundImageNav: View {
#Environment(\.presentationMode) var presentationMode
// remplacing the back button action, (only problem is that this disable the swipe back)
var body: some View {
ZStack {
// ZStack help you having your image behind the other views
VStack {
Image("defaultImage")
.resizable()
.frame(height: 180)
.edgesIgnoringSafeArea(.all)
Spacer()
// having a spacer that push the image on the top and ignoring the safe area
}
VStack(alignment:.leading){
HStack{
Button(action:{
presentationMode.wrappedValue.dismiss()
// back button action
}){
Image(systemName:"chevron.left")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 30, height: 30)
.foregroundColor(.white)
}
Spacer()
Rectangle()
.fill(Color.white)
.frame(width: 200, height: 80, alignment: .center)
Spacer()
Button(action:{
// do something
}){
Image(systemName: "xmark")
.resizable()
.frame(width: 24, height: 24)
.foregroundColor(.white)
}
}.padding()
Text("Title")
.bold()
.font(.title)
.foregroundColor(.black)
.background(Color.white)
.padding(24)
Spacer()
}
}.navigationBarHidden(true)
// removing the bar to customize the back button
}
}
struct backgroundImage_Previews: PreviewProvider {
static var previews: some View {
FirstView()
}
}
In the native Settings app, there's a NavigationView with a TextField inside of it that nicely transitions as the user scrolls:
I was able to create something similar using:
struct HomeView: View {
#State var searchQuery: String = ""
var body: some View {
NavigationView {
List {
TextField("Search", text: $searchQuery).textFieldStyle(RoundedBorderTextFieldStyle())
}
.navigationBarTitle(Text("My App"))
}
}
}
which gave me this:
However, this doesn't really look or act the same as the native settings one, and I'm lost on how to even get the search icon in there. Thanks so much!
What youre trying to create in SwiftUI would be a UISearchBar in swift's UIKit.
So you need to stylize the textfield
TextField("Search ...", text: $text)
.padding(7)
.padding(.horizontal, 25)
.background(Color(.systemGray6))
.cornerRadius(8)
.padding(.horizontal, 10)
.onTapGesture {
self.isEditing = true
}
And in order to achieve the magnifying glass icon which is standard for a UISearchBar item. We need to add them manually with an overlay in SwiftUI
.overlay(
HStack {
Image(systemName: "magnifyingglass")
.foregroundColor(.gray)
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
.padding(.leading, 8)
if isEditing {
Button(action: {
self.text = ""
}) {
Image(systemName: "multiply.circle.fill")
.foregroundColor(.gray)
.padding(.trailing, 8)
}
}
}
)
you can reference this article for more https://www.appcoda.com/swiftui-search-bar/
I am trying to change background color main this view but unable to do it. I tried to put background(Color.green) at HStack, VSTack and even on ZStack but it did not work, not sure if i am putting at right place. By default it is taking phone or simulator color which is white but i want to apply custom background color
My Xcode version is 11.5
struct HomePageView: View {
#State var size = UIScreen.main.bounds.width / 1.6
var body: some View {
GeometryReader{_ in
VStack {
HStack {
ZStack{
// main home page components here....
NavigationView{
VStack {
AssignmentDaysView()
}.background(Color.lairBackgroundGray)
.frame(width: 100, height: 100, alignment: .top)
.navigationBarItems(leading: Button(action: {
self.size = 10
}, label: {
Image("menu")
.resizable()
.frame(width: 30, height: 30)
}).foregroundColor(.appHeadingColor), trailing:
Button(action: {
print("profile is pressed")
}) {
HStack {
NavigationLink(destination: ProfileView()) {
LinearGradient.lairHorizontalDark
.frame(width: 30, height: 30)
.mask(
Image(systemName: "person.crop.circle")
.resizable()
.scaledToFit()
)
}
}
}
).navigationBarTitle("Home", displayMode: .inline)
}
HStack{
menu(size: self.$size)
.cornerRadius(20)
.padding(.leading, -self.size)
.offset(x: -self.size)
Spacer()
}
Spacer()
}.animation(.spring()).background(Color.lairBackgroundGray)
Spacer()
}
}
}
}
}
struct HomePageView_Previews: PreviewProvider {
static var previews: some View {
HomePageView()
}
}
In your NavigationView you have a VStack. Instead you can use a ZStack and add a background below your VStack.
Try the following:
NavigationView {
ZStack {
Color.green // <- or any other Color/Gradient/View you want
.edgesIgnoringSafeArea(.all) // <- optionally, if you want to cover the whole screen
VStack {
Text("assignments")
}
.background(Color.gray)
.frame(width: 100, height: 100, alignment: .top)
}
}
Note: you use many stacks wrapped in a GeometryReader which you don't use. Consider simplifying your View by removing unnecessary stacks. Also you may not need a GeometryReader if you use UIScreen.main.bounds (however, GeometryReader is preferred in SwiftUI).
Try removing some layers: you can start with removing the top ones: GeometryReader, VStack, HStack...
Try the following:
Change the view background color especially safe area also
struct SignUpView: View {
var body: some View {
ZStack {
Color.blue //background color
}.edgesIgnoringSafeArea(.all)
I'm struggling to remove the background of a custom circular Button element in SwiftUI which is defined as follows:
struct NavButton: View {
var body: some View {
Button(action: {})
VStack {
Text("Button")
}
.padding(40)
.background(Color.red)
.font(.title)
.mask(Circle())
}
}
}
This results in a rectangular light gray background around the button, where I want it to not be shown:
I tried to append a "background" modifier to the button, and it demonstrates very strange behavior: if it's set to "Color.clear", there is no effect. But if I set it to "Color.green" it does change the background as expected.
Example of setting the "Background" modifier to "Color.green":
struct NavButton: View {
var body: some View {
Button(action: {})
VStack {
Text("Button")
}
.padding(40)
.background(Color.red)
.font(.title)
.mask(Circle())
}
.background(Color.green) // has no effect if set to "Color.clear"
}
}
I wonder if I'm missing something here?
PS: I'm using Xcode 11.1 (11A1027)
Try adding .buttonStyle(PlainButtonStyle()) on the button itself.
You would have something like this:
Button(action: {}){
VStack{
Text("Button")
}
.padding(40)
.background(Color.red)
.font(.headline)
.mask(Circle())
}
.buttonStyle(PlainButtonStyle())
Declare your own ButtonStyle:
struct RedRoundButton: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.padding(40)
.font(.title)
.background( Circle()
.fill(Color.red))
}
}
and then use it like this:
Button("Button") {}
.buttonStyle(RedRoundButton())
Try this:
struct ContentView: View {
var body: some View {
Button(action: {}) {
Text("Button")
.frame(width: 80, height: 80)
}
.background(Color.red)
.cornerRadius(40)
.frame(width: 80, height: 80)
}
}
Try this.
struct ContentView: View {
var body: some View {
VStack {
Button(action: {}){
Text("button")
.font(.system(size: 50))
.foregroundColor(.black)
.bold()
}
.padding(30)
.background(Color.yellow)
.font(.headline)
.mask(Circle())
.buttonStyle(PlainButtonStyle())
} // end Vstack
}// end body
}