SwiftUI - how to change text alignment of label in Toggle?
Here it is
Toggle(isOn: $vibrateOnRing) {
Text("Vibrate on Ring")
.frame(maxWidth: .infinity, alignment: .trailing)
}
Change text based on toggle values in SwiftUI
You are instantiating Settings separately in each view. Both views need to be seeing the same Settings object:
Change the following:
NavigationButton(destination: ToggleBluetoothView(bluetooth: bluetooth)) { ... }
and remove the initial value in ToggleBluetoothView:
struct ToggleBluetoothView: View {
@ObjectBinding var bluetooth: Settings
var body: some View {
Form {
Section(header: Text("ENABLE TO CONNECT WITH NEARBY DEVICES")) {
Toggle(isOn: $bluetooth.isBluetoothOn) {
Text("Bluetooth")
}
}
}
}
}
How to remove or hide the label of a Toggle in SwiftUI
SwiftUI 1.0
Hide the label/title with the labelsHidden Modifier
This is how it should be done.
Toggle("Turn alarm on", isOn: $isToggleOn)
.labelsHidden() // Hides the label/title
Note: Even though the label is hidden, you should still add one for accessibility purposes.
Example:
SwiftUI Toggle in a VStack is misaligned
this should work
import SwiftUI
struct ContentView: View {
@State var showDetails = false
@State var firstToggle = false
@State var secondToggle = false
var body: some View {
NavigationView {
Form {
ToggleSubtitleRow(title: "Show Advanced",
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, se",
isOn: $showDetails)
if showDetails {
ToggleSubtitleRow(title: "Lorem ipsum dolor sit amet",
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam",
isOn: $firstToggle).id(UUID())
ToggleSubtitleRow(title: "Lorem ipsum dolor sit amet",
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam",
isOn: $secondToggle)
}
}
.listStyle(GroupedListStyle())
.navigationBarTitle("Settings", displayMode: .inline)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
public struct ToggleSubtitleRow: View {
let title: String
let text: String
@Binding var isOn: Bool
public var body: some View {
VStack(alignment: .leading) {
Toggle(isOn: $isOn) {
Text(title)
}
Text(text)
.fixedSize(horizontal: false, vertical: true)
.foregroundColor(Color(.secondaryLabel))
.frame(alignment: .leading)
}
.foregroundColor(Color(.label))
}
}
I put it here to show, that the whole conditional part is recreated if at least one of its element need to be recreated.
For explanation, change the code a little bit (without any .id modifier)
if showDetails {
Text("\(showDetails.description)")
ToggleSubtitleRow(title: "Lorem ipsum dolor sit amet",
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam",
isOn: $firstToggle)
ToggleSubtitleRow(title: "Lorem ipsum dolor sit amet",
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam",
isOn: $secondToggle)
}
It works, "as expected", because in the conditional part SwiftUI recognized "something" was changed.
Text("\(showDetails.description)")
has the same effect.
What about .id modifier? Why it works?
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
extension View {
/// Returns a view whose identity is explicitly bound to the proxy
/// value `id`. When `id` changes the identity of the view (for
/// example, its state) is reset.
@inlinable public func id<ID>(_ id: ID) -> some View where ID : Hashable
}
Based on written
ToggleSubtitleRow(title: "Lorem ipsum dolor sit amet",
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam",
isOn: $firstToggle).id(showDetails)
works as well!
Lets rearrange the code this way
struct ContentView: View {
@State var showDetails = false
@State var firstToggle = false
@State var secondToggle = false
var body: some View {
let g = Group {
if showDetails {
ToggleSubtitleRow(title: "Lorem ipsum dolor sit amet",
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam",
isOn: $firstToggle).id(UUID())
ToggleSubtitleRow(title: "Lorem ipsum dolor sit amet",
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam",
isOn: $secondToggle)
}
}
let f = Form {
ToggleSubtitleRow(title: "Show Advanced",
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, se",
isOn: $showDetails)
g
}
.listStyle(GroupedListStyle())
.navigationBarTitle("Settings", displayMode: .inline)
let v = NavigationView {
f
}
return v
}
}
and check the type of g
let g: Group<TupleView<(some View, ToggleSubtitleRow)>?>
we can see how SwiftUI deal with our "conditional". It is in fact
TupleView<(some View, ToggleSubtitleRow)>?
UPDATE based on discussion, applying .id modifier on more than one ToggleSubtitleRow simply doesn't work
The best option, how to solve this bug is redefine
public struct ToggleSubtitleRow: View {
let title: String
let text: String
@Binding var isOn: Bool
public var body: some View {
VStack(alignment: .leading) {
Toggle(isOn: $isOn) {
Text(title)
}.id(UUID())
Text(text)
.fixedSize(horizontal: false, vertical: true)
.foregroundColor(Color(.secondaryLabel))
.frame(alignment: .leading)
}
.foregroundColor(Color(.label))
}
}
by not modifying anything in you ContentView but directly Toggle self in ToggleSubtitleRow
Aligning text + button Terms of Use - SwiftUI
Ok this is how I solved it (and actually like the design better):
VStack {
HStack {
Text("By continuing, you agree to our ")
.font(.system(size: 10))
Button(action: {
showTermsOfUse.toggle()
}) {
Text("Terms of Use (EULA)")
.font(.system(size: 10))
}
.fullScreenCover(isPresented: $showTermsOfUse, content: {
SFSafariViewWrapper(url: URL(string: "https:...")!)
})
}
HStack {
Text(" and acknowledge that you have read our")
.font(.system(size: 10))
Button(action: {
showPrivacyPolicy.toggle()
}) {
Text("Privacy Policy.")
.font(.system(size: 10))
}
.fullScreenCover(isPresented: $showPrivacyPolicy, content: {
SFSafariViewWrapper(url: URL(string: "https:/...")!)
})
}
}
How to change the label of a button by using an if statement in SwiftUI
You're very close, but you have to have the same instance of the WelcomeButton ObservableObject shared between the two. Right now, they're two separate instances, so when you update hasBeenPressed
on one, the other one doesn't know to change its state.
struct WelcomeScreenButton: View {
@ObservedObject var welcomeButton : WelcomeButton //<-- here
var body: some View {
ZStack {
if welcomeButton.hasBeenPressed {
Circle()
.fill(Color(.white))
}
else {
Circle()
.fill(Color(.black))
}
}
}
}
struct ContentView: View {
@ObservedObject var welcomeButton = WelcomeButton()
var body: some View {
VStack {
Button(action: {welcomeButton.hasBeenPressed.toggle()})
{
WelcomeScreenButton(welcomeButton: welcomeButton) //<-- here
}
.frame(width: 375, height: 375, alignment: .center)
}
}
}
PS -- just as a general practice, it might be good to make the naming a little different just to keep things straight. WelcomeButton
sounds like it's going to be a button. Naming it WelcomeButtonViewModel
instead would make its intention more clear, although it wouldn't change the functionality at all.
How to change Button Title Alignment in Swift?
Use contentHorizontalAlignment
.You have to use UIControlContentHorizontalAlignment.Left
.You need to usehorizontal
not vertical
.
btn.contentHorizontalAlignment = UIControlContentHorizontalAlignment.Left
Swift 3.x
btn.contentHorizontalAlignment = .left
SwiftUI display different images/text on toggle/true or false
In lieu of more details, generally the best way to adjust your view in the result of an object's property is to make the smallest adjustment necessary. In this case, you can limit the change to the systemName
of the image:
Button {
taskViewModel.completeTask(id: task.id)
} label: {
Image(systemName: task.taskCompleted ? "checkmark.square" : "square")
.foregroundStyle(.black)
.padding(10)
.background(Color(.white), in: RoundedRectangle(cornerRadius: 10))
}
What is more likely happening is that task
isn't signalling its change to the SwiftUI rendering system, so after completeTask
has run there's no indication that the view needs to be re-evaluated.
Related Topics
Access Flutter Sharedpreferences in Swift
Differencebetween Date.Addingtimeinterval(_:) and Date.Advanced(By:)
Openinmapswithlaunchoptions Not Working
How to Add a Left Bar Button Without Overriding the Natural Back Button
How to Display Current Time (Realtime) in iOS 14 Home Widget
JSONencoder and Propertylistencoder Don't Conform to Encoder
Apple Push Notifications Without Developer Account
Swiftui Nested Foreach Causes Unexpected Ordering
For-In Loops Multiple Conditions
Opening Import File for Module 'Swift': Not a Directory
Swiftui - How to Change Text Alignment of Label in Toggle
How to Scale/Position Nodes Swift Spritekit? Custom View
Uiimagepickercontroller Navigation Bar Tint Color Not Working with iOS 13
Swift Throws Python Errors from Terminal
Exc_Bad_Instruction Happens When Using Dispatch_Get_Global_Queue on iOS 7(Swift)
Convert [(Key: String, Value: String)] in [String:String]