Swiftui - How to Change Text Alignment of Label in Toggle

SwiftUI - how to change text alignment of label in Toggle?

Here it is

demo

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:

Toggle Example with no Label

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):

Sample Image

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



Leave a reply



Submit