I want to use scaleEffect to scale a TextEditor contained in a VStack. When not scaled the text editor is very normal. But After scaling the editor can not be edited normally as the cursor can not be placed in the right place. Here is the code:
import SwiftUI
struct DemoTextView: View {
#State var text: String = ""
#State var scale: Double = 1
var body: some View {
VStack {
Spacer()
VStack {
TextEditor(text: $text)
.frame(width: 100, height: 100, alignment: .top)
.border(Color.red)
}
.scaleEffect(scale)
Spacer()
HStack {
Slider(value: $scale, in: 0.25...4)
Text("\(scale)")
}
.padding()
}
.frame(width: 500, height: 500, alignment: .center)
}
}
struct DemoTextView_Previews: PreviewProvider {
static var previews: some View {
DemoTextView()
}
}
And the screenshot of the wired behavior:
Anyone knows how to make the scaling of TextEditor works?
Related
I want to have the TextEditor1 to be on the bottom of the app, then when user taps on the TextEditor1 to type the message, the TextEditor1 should attached to the keyboard and move up with it. I used the following code, it attaches to it through the .toolbar, but don't know how to make TextEditor1 stay in the bottom of the app etc and then move up with the keyboard. Image is attached for further clarification.
import SwiftUI
struct ContentView: View {
#State var textTyped: String = "this is textttt"
var body: some View {
TextEditor (text: $textTyped)
.toolbar {
ToolbarItemGroup(placement: .keyboard) {
TextEditor1()
}
}
.frame(height: 200, alignment: .leading)
.padding(.horizontal, 10)
}
}
struct TextEditor1: View {
#State var textTyped: String = "this is textttt"
var body: some View {
TextEditor (text: $textTyped)
.frame(height: 200, alignment: .leading)
.padding(.horizontal, 10)
}
}
Is this what you want? I also put a colored .background() on to see the outlines of the TextEditor. I find it helps to be able to visualize the extent of the views.
struct ContentView: View {
#State var textTyped: String = "this is textttt"
var body: some View {
VStack {
Spacer()
TextEditor (text: $textTyped)
.frame(height: 200, alignment: .leading)
// .padding(.horizontal, 10)
.padding()
.background(Color.yellow.opacity(0.2))
}
}
}
The default button style of ColorPicker is a circle as bellow.
I want to change the style of the circle button to Rectangle. But seems no API can change it style. So I put a Rectangle over it , and set it allowsHitTesting to false to transport click event to ColorPicker.
struct ColorPickerView: View {
#State private var colorValue = Color.orange
var body: some View {
ZStack() {
ColorPicker("", selection: $colorValue)
.labelsHidden()
Rectangle()
.foregroundColor(.blue)
.frame(width: 40, height: 40, alignment: .center)
.allowsHitTesting(false)
}
}
}
But the ColorPicker did not present after click.
I put a circle bellow the Rectangle to test whether allowsHitTesting is useful. It can work properly responding to tap gesture to print "Circle tapped!".
struct ColorPickerView: View {
#State private var colorValue = Color.orange
var body: some View {
ZStack() {
ColorPicker("", selection: $colorValue)
.labelsHidden()
Rectangle()
.foregroundColor(.blue)
.frame(width: 40, height: 40, alignment: .center)
.onTapGesture {
print("Circle tapped!")
}
Rectangle()
.foregroundColor(.blue)
.frame(width: 40, height: 40, alignment: .center)
.allowsHitTesting(false)
}
}
}
Why the ColorPicker can not responding to tap gesture? Or Is there a way to customize the ColorPicker button?
Simply use opacity, and send the ColorPicker to overlay, like in the code:
struct SquareColorPickerView: View {
#Binding var colorValue: Color
var body: some View {
colorValue
.frame(width: 40, height: 40, alignment: .center)
.cornerRadius(10.0)
.overlay(RoundedRectangle(cornerRadius: 10.0).stroke(Color.white, style: StrokeStyle(lineWidth: 5)))
.padding(10)
.background(AngularGradient(gradient: Gradient(colors: [.red,.yellow,.green,.blue,.purple,.pink]), center:.center).cornerRadius(20.0))
.overlay(ColorPicker("", selection: $colorValue).labelsHidden().opacity(0.015))
.shadow(radius: 5.0)
}
}
Use case:
struct ContentView: View {
#State private var colorValue = Color.orange
var body: some View {
SquareColorPickerView(colorValue: $colorValue)
}
}
Here I got 2 shapes, one Rectangle and one Circle, which with action of a Button only one of them became visible to user, I tried to use #Namespace for this transform, but did not panned out!
MY Goal: Having a nice and smooth transform animation from one Shape to other.
struct ContentView: View {
#State var action: Bool = false
#Namespace var sameShape
var body: some View {
ZStack
{
Group
{
if action
{
Circle()
.fill(Color.blue).frame(width: 150, height: 150, alignment: .center)
.matchedGeometryEffect(id: "Dakota148Zero", in: sameShape)
}
else
{
Rectangle()
.fill(Color.red).frame(width: 150, height: 150, alignment: .center)
.matchedGeometryEffect(id: "Dakota148Zero", in: sameShape)
}
}
.animation(.easeInOut)
VStack
{
Spacer()
Button("transform") { action.toggle() }.font(Font.largeTitle).padding()
}
}
}
}
Here is way to do it by representing the circle and square as a RoundedRectangle with different cornerRadius values:
struct ContentView: View {
#State var action = false
var body: some View {
ZStack
{
RoundedRectangle(cornerRadius: action ? 0 : 75)
.fill(action ? Color.red : .blue)
.frame(width: 150, height: 150, alignment: .center)
.animation(.easeInOut)
VStack
{
Spacer()
Button("transform") {
action.toggle()
}
.font(Font.largeTitle)
.padding()
}
}
}
}
Group is not real container, so don't store animation. Replace Group with some stack, like
VStack
{
if action
// ... other code no change
With iOS14 out, you can use matchedGeometryEffect(). If you are using iOS14, I would recommend this approach.
https://www.hackingwithswift.com/quick-start/swiftui/how-to-synchronize-animations-from-one-view-to-another-with-matchedgeometryeffect
https://developer.apple.com/documentation/swiftui/view/matchedgeometryeffect(id:in:properties:anchor:issource:)
So in your solution, if you replace action.toggle() with withAnimation{self.action.toggle()} in your button code, it will animate.
Button("transform") {
withAnimation{self.action.toggle()}
}
.font(Font.largeTitle).padding()
This solution works on the simulator for me (Xcode 12.1, iPhone 11 iOS 14.1):
import SwiftUI
struct ContentView: View {
#State var action: Bool = false
#Namespace var transition
var body: some View {
ZStack {
Group {
if action {
Circle()
.fill(Color.blue).frame(width: 150, height: 150, alignment: .center)
.matchedGeometryEffect(id: "shape", in: transition)
} else {
Rectangle()
.fill(Color.red).frame(width: 150, height: 150, alignment: .center)
.matchedGeometryEffect(id: "shape", in: transition)
}
}
.animation(.easeInOut)
VStack {
Spacer()
Button("transform") { withAnimation{self.action.toggle()} }.font(Font.largeTitle).padding()
}
}
}
}
The matchedGeometryEffect() doesn't want to animate different shapes (including cornerRadius) or colors that nicely, not sure if this is a bug that will get fixed in future patches or just a feature that needs to be worked around by regular animations. With me playing around with matchedGeometryEffect(), it seems to do great with sizing things up and down, like shown with this code:
import SwiftUI
struct ContentView: View {
#State private var animate: Bool = false
#Namespace private var transition
var body: some View {
VStack {
if animate {
RoundedRectangle(cornerRadius: 75.0)
.matchedGeometryEffect(id: "shape", in: transition)
.frame(width: 250, height: 250, alignment: .center)
.foregroundColor(Color.blue)
.animation(.easeInOut)
.onTapGesture {
animate.toggle()
}
} else {
// Circle
RoundedRectangle(cornerRadius: 75.0)
.matchedGeometryEffect(id: "shape", in: transition)
.frame(width: 150, height: 150, alignment: .center)
.foregroundColor(Color.red)
.animation(.easeInOut)
.onTapGesture {
animate.toggle()
}
}
}
}
}
I try to make a smooth animation when the NetStatus change but it's not working like i want.
I want to get the same effect as when i press the button with the toggle animation. The commented button animation is working great and i try to replicate it with the scaling of the height of the text frame.
The commented button code is just for a working example of the animation effect that i want (expand and close gracefully), i don't need this code.
How can i do that?
import SwiftUI
struct NoNetwork: View {
let screenSize: CGRect = UIScreen.main.bounds
#ObservedObject var online = NetStatus()
var body: some View {
VStack{
Text("NoNetworkTitle")
.fontWeight(.bold)
.foregroundColor(Color.white)
.frame(width: screenSize.width, height: self.online.connected ? 0 : 40, alignment: .center)
// .animation(.easeIn(duration: 5))
.background(Color.red)
// Button(action: {
// withAnimation {
// self.online.connected.toggle()
// }
// }, label: {
// Text("Animate")
// })
}
}
}
struct NoNetwork_Previews: PreviewProvider {
static var previews: some View {
NoNetwork()
}
}
To animate when online.connected changes, put the .animation modifier on the VStack:
VStack{
Text("NoNetworkTitle")
.fontWeight(.bold)
.foregroundColor(Color.white)
.frame(width: screenSize.width, height: self.online.connected ? 0 : 40, alignment: .center)
.background(Color.red)
Button(action: {
self.online.connected.toggle()
}, label: {
Text("Animate")
})
}
.animation(.easeInOut(duration: 0.5))
This will animate the other views in the VStack as the Text appears and disappears.
`import SwiftUI
struct Test2: View {
var body: some View {
ZStack {
Rectangle()
.fill(Color.green)
.frame(height:200)
.offset(y: 100)
VStack{
Image("star2")
.resizable()
.frame(width: 50, height: 50)
Text("So even if the text is suepr long, text height expend to bottom. not top and bottom")
.font(.system(size: 30))
.frame(width:300)
.padding()
}
}
}
}`
[
When the text is too long, SwiftUI Text() height changes. But it increases toward top and bottom.
it pushes out my other views.
How can I change Text() to increase height only to down side??
fix the space above the star!
import SwiftUI
struct ContentView: View {
#State var flag = false
let text = ["Hello World", """
So even if the text is suepr long, text height expend to bottom. not top and bottom
"""]
var body: some View {
GeometryReader { proxy in
ZStack {
Rectangle()
.fill(Color.green)
.frame(height:200)
.offset(y: 100)
VStack{
Color.clear.frame(height: proxy.size.height / 3)
Image(systemName: "star")
.resizable()
.frame(width: 50, height: 50).onTapGesture {
self.flag.toggle()
}
Text(self.text[self.flag ? 0 : 1])
.font(.system(size: 30))
.padding()
Spacer()
//Color.yellow
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}