SwiftUI Stack Layout - text

I need to implement view with two texts, and first text alignment need to be trailing, and second text alignment leading, but I have this..
please help me to build correct layout.
i tried to put another VStack inside the HStack and assign the trailing orientation to the first and the leading to the second
this is my code example:
var body: some View {
VStack {
HStack(spacing: 10) {
Text("test1")
.font(.system(size: 12))
.fontWeight(.bold)
// .padding(EdgeInsets(top: 0, leading: 12, bottom: 0, trailing: 10))
Text("testtest1")
.padding()
.font(.system(size: 14))
.foregroundColor(.black)
.multilineTextAlignment(.center)
.overlay(
RoundedRectangle(cornerRadius: 20)
.stroke(Color.red, lineWidth: 1)
)
Spacer()
}
.frame(width: UIScreen.screenWidth)
.padding(EdgeInsets(top: 0, leading: 40, bottom: 12, trailing: 0))
HStack(spacing: 10) {
Text("test23")
.font(.system(size: 12))
.fontWeight(.bold)
// .padding(EdgeInsets(top: 0, leading: 12, bottom: 0, trailing: 10))
Text(String("testtest12"))
.padding()
.font(.system(size: 14))
.foregroundColor(.black)
.multilineTextAlignment(.center)
.overlay(
RoundedRectangle(cornerRadius: 20)
.stroke(Color.red, lineWidth: 1)
)
Spacer()
}
.frame(width: UIScreen.screenWidth)
.padding(EdgeInsets(top: 0, leading: 40, bottom: 12, trailing: 0))
HStack(spacing: 10) {
Text("test345")
.font(.system(size: 12))
.fontWeight(.bold)
.frame(alignment: .trailing)
// .padding(EdgeInsets(top: 0, leading: 12, bottom: 0, trailing: 10))
Text("testtest1234")
.padding()
.font(.system(size: 14))
.foregroundColor(.black)
.multilineTextAlignment(.center)
.overlay(
RoundedRectangle(cornerRadius: 20)
.stroke(Color.red, lineWidth: 1)
)
Spacer()
}
.frame(width: UIScreen.screenWidth)
.padding(EdgeInsets(top: 0, leading: 40, bottom: 12, trailing: 0))
HStack {
Text("test6789")
.font(.system(size: 12))
.fontWeight(.bold)
// .padding(EdgeInsets(top: 0, leading: 12, bottom: 0, trailing: 10))
Text("testtest123456")
.padding()
.font(.system(size: 14))
.foregroundColor(.black)
.multilineTextAlignment(.center)
.overlay(
RoundedRectangle(cornerRadius: 20)
.stroke(Color.red, lineWidth: 1)
)
Spacer()
}
.frame(width: UIScreen.screenWidth)
.padding(EdgeInsets(top: 0, leading: 40, bottom: 12, trailing: 0))
HStack {
Text("test01234")
.font(.system(size: 12))
.fontWeight(.bold)
// .padding(EdgeInsets(top: 0, leading: 12, bottom: 0, trailing: 10))
Text("testtest56")
.padding()
.font(.system(size: 14))
.foregroundColor(.black)
.multilineTextAlignment(.center)
.overlay(
RoundedRectangle(cornerRadius: 20)
.stroke(Color.red, lineWidth: 1)
)
Spacer()
}
.frame(width: UIScreen.screenWidth)
.padding(EdgeInsets(top: 0, leading: 40, bottom: 12, trailing: 0))
HStack {
Text("test5")
.font(.system(size: 12))
.fontWeight(.bold)
// .padding(EdgeInsets(top: 0, leading: 12, bottom: 0, trailing: 10))
Text("testtes78")
.padding()
.font(.system(size: 14))
.foregroundColor(.black)
.multilineTextAlignment(.center)
.overlay(
RoundedRectangle(cornerRadius: 20)
.stroke(Color.red, lineWidth: 1)
)
Spacer()
}
.frame(width: UIScreen.screenWidth)
.padding(EdgeInsets(top: 0, leading: 40, bottom: 12, trailing: 0))
}
}
But I want to make something like this:

Give the texts on the left fixed width and add the multiLineAlignment(.traling) to all.
Edit:
var body: some View {
VStack(spacing: 0) {
ForEach(0..<5) { i in
HStack(spacing: 0) {
Text("Left Text \(String(repeating: "XX", count: i))")
.font(.system(size: 12).bold())
.frame(width: 150, alignment: .trailing)
.padding(.trailing, 15)
Text("Right Text \(i)")
.font(.system(size: 12))
.padding()
.overlay(
RoundedRectangle(cornerRadius: 20, style: .continuous)
.stroke(.red)
)
Spacer()
}
.padding(.bottom, 15)
.frame(maxWidth: .infinity)
}
Spacer()
}
.padding()
.frame(maxWidth: .infinity)
}

Related

UIView Top Point is Lower Then Expected

I have a format problem. How I want is the 2nd picture but for some reason, my view starts a little bit lower. You can see the gap between the pictures. I want to solve this problem without offset. Might be because of .navigationBarHidden(true) but I do not want navigation bar.
I added NavigationView to my code because I have a button down-right to add a new task.
Plus for some reason, this button is not clickable. Would be good if you give a hand to that problem.
import SwiftUI
struct TaskListView: View {
#State private(set) var data = ""
#State var isSettings: Bool = false
#State var isSaved: Bool = false
var body: some View {
NavigationView {
ZStack {
Color(#colorLiteral(red: 0.9333333333, green: 0.9450980392, blue: 0.9882352941, alpha: 1)).edgesIgnoringSafeArea(.all)
VStack {
TopBar()
HStack {
CustomTextField(data: $data, tFtext: "Find task", tFImage: "magnifyingglass")
Button(action: {
self.isSettings.toggle()
}, label: {
ZStack {
RoundedRectangle(cornerRadius: 15)
.frame(width: 50, height: 50, alignment: .center)
.foregroundColor(Color(#colorLiteral(red: 0.4274509804, green: 0.2196078431, blue: 1, alpha: 1)))
Image("buttonImage")
.resizable()
.frame(width: 30, height: 30, alignment: .center)
}
.padding(.horizontal, 15)
})
}
CustomSegmentedView()
ZStack {
TaskFrameView()
Button( action: {
self.isSaved.toggle()
}, label: {
ZStack {
RoundedRectangle(cornerRadius: 20)
.foregroundColor(Color(#colorLiteral(red: 1, green: 0.7137254902, blue: 0.2196078431, alpha: 1)))
Text("+")
.foregroundColor(.white)
.font(.title)
.fontWeight(.bold)
}
.frame(width: 40, height: 40)
.offset(x: 150, y: 220)
})
NavigationLink(
destination: NewTaskView(),
isActive: $isSaved,
label: {
Text("")
})
}
}
}
Spacer()
}
.navigationBarHidden(true)
}
}
struct TopBar: View {
var body: some View {
HStack {
Image("avatar")
.resizable()
.frame(width: 100, height: 100)
VStack(alignment: .leading){
DateView()
.font(Font.custom("SFCompactDisplay", size: 20))
.foregroundColor(.gray)
.padding(.vertical, 5)
Text("Hi, Random")
.font(Font.custom("SFCompactDisplay", size: 20))
}
Image(systemName: "ellipsis")
}
}
}
It is navigation view bar. The navigationBarHidden modifier should be inside NavigationView, like
}
.navigationBarHidden(true) // << here !!
Spacer()
} // end of NavigationView

How to dynamically extend the CARD widget height size based on the text in the card?

So if I put a lot of text in a widget card the text will exceed the card widget and I can t see anymore the rest of it.
Only if I manually the size of each card it will show all the text.
Is it possible to dynamically extend the CARD widget height size based on the text in the card?
For example, no matter how much text I put there the height of the card it will extend in order to show all the text in it.
The code:
Widget _card(
{Color primary = Colors.redAccent,
String imgPath,
String chipText1 = '',
String chipText2 = '',
Widget backWidget,
Color chipColor = LightColor.orange,
bool isPrimaryCard = false}) {
return Container(
height: isPrimaryCard ? 500 : 500,
width: isPrimaryCard ? width * .90 : width * .90,
margin: EdgeInsets.symmetric(horizontal: 10, vertical: 20),
decoration: BoxDecoration(
color: primary.withAlpha(200),
borderRadius: BorderRadius.all(Radius.circular(20)),
boxShadow: <BoxShadow>[
BoxShadow(
offset: Offset(0, 5),
blurRadius:
10,
color: LightColor.lightpurple.withAlpha(20))
]),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(20)),
child: Container(
child: Stack(
children: <Widget>[
backWidget,
Positioned(
top: 20,
left: 10,
child: CircleAvatar(
backgroundColor: Colors.transparent,
backgroundImage: NetworkImage(imgPath),
)),
Positioned(
top: 30,
left: 20,
child: _cardInfo(chipText1, chipText2,
LightColor.titleTextColor, chipColor,
isPrimaryCard: isPrimaryCard),
)
],
),
),
));
}
You might want to use a ConstrainedBox. It allows you to set a minimum height, but can expand if needed :
Card(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: 100,
),
child: Text("")
)
)

The keyboard of a TextField doesn't show when I tap it in SwiftUI

The keyboard of a TextField doesn't show when I tap it on a physical device and I don't know why, here is my code:
VStack {
HStack {
Image(colorScheme == .light ? "user" : "userDark")
.resizable()
.frame(width: 30, height: 30)
Text(localName)
.font(.system(size: 20))
Spacer()
}.padding(.horizontal)
ZStack {
HStack {
TextField("Change name", text: $name)
.textFieldStyle(PlainTextFieldStyle())
.padding(.leading, 5)
.font(.system(size: 20))
.autocapitalization(.none)
.disableAutocorrection(true)
.zIndex(1)
if self.name != "" {
Spacer()
Button(action: {
// update name
})
{
Text("Update")
.padding()
}.padding()
}
}.padding(.horizontal)
}
}
Thank you in advance!

SwiftUI - Text minimumScaleFactor not scaling only when needed

I have a Text that I want to modify with a .minimumScaleFactor(0.1) when the length of its string extends outside the view. However, the scaling applies every time, even when the original font size would be perfectly fine.
My view is structured thusly:
VStack(alignment: .center, spacing: 0) {
HStack {
Image("medal \(place)").resizable()
.foregroundColor(color)
.frame(width: 40, height: 40)
Spacer()
Text(username)
.font(.bold(16))
.lineLimit(1)
.minimumScaleFactor(0.1)
.frame(alignment: .trailing)
.foregroundColor(Color("mediumTextColor"))
}
Spacer()
Text(score)
.font(.extraBold(60))
.foregroundColor(color)
.lineLimit(1)
.minimumScaleFactor(0.7)
Spacer()
}
.frame(height: 96)
.padding(10)
.cornerRadius(16)
.overlay(RoundedRectangle(cornerRadius: 16)
.stroke(color, lineWidth: 2))
A continuation of answer above.
What is important is the order in which the modifiers are applied:
Text("This is a really long sentence.")
.minimumScaleFactor(0.5)
.font(.custom("OpenSans", size: 15))
.lineLimit(1)
.layoutPriority(1)
There isn't a need for the GeometryReader unless you need it for something else
Adding .lineLimit(1) to the Text will work well.
Xcode: 11.3.1
Important for that minimumScaleFactor() only does its job when it is needed, is the combination of .minimumScaleFactor AND .lineLimit(1); otherwise it will not work. layoutPriority(1) is not the key here.
Example - this works; Scale is only applied when needed:
Text("Something").minimumScaleFactor(0.5).lineLimit(1)
Adding a GeometryReader around the VStack that my two Text views were in solved this. As requested by #gohnjanotis:
GeometryReader { proxy in
VStack(alignment: .center, spacing: 0) {
HStack {
Image("medal \(self.place)").resizable()
.foregroundColor(self.color)
.frame(width: 40, height: 40)
Spacer()
Text(self.username)
.minimumScaleFactor(0.1)
.font(.bold(16))
.lineLimit(1)
.frame(alignment: .trailing)
.foregroundColor(Color("mediumTextColor"))
.layoutPriority(1)
}
.padding(.top, 10)
.padding(.horizontal, 10)
Spacer()
Text(self.score)
.font(.extraBold(60))
.foregroundColor(self.color)
.lineLimit(1)
.minimumScaleFactor(0.1)
.layoutPriority(1)
.padding(.horizontal, 10)
.padding(.bottom, 10)
.offset(y: -10)
}
.frame(width: proxy.size.width, height: proxy.size.height, alignment: .top)
}
.frame(maxHeight: 130)
Add .layoutPriority(1) modifier to your Text to make sure it takes the space if there is any.
After trying to figuring this out for a long while... playing with minimumScaleFactor, LineLimit, layoutPriority... I found out that using .frame() helps solve my problem.
My problem is that minimumScaleFactor applies to Text even if it is not needed.
Applying .frame() ad the last line solve my problem.
Something like this...
GeometryReader { geometry in
VStack{
Text("Hello")
.foregroundColor(Color.Black)
.font(.system(size: 50))
.minimumScaleFactor(0.1)
.lineLimit(1)
.frame(height: geometry.size.height)
}
}

How to add a neon glow effect to an widget border / shadow?

Is there any way to create effects like these using flutter (a CustomPaint with a special shadder or something like this)?
For example. I have this container and I drew some lines on it using a CustomPainter. Could I draw these lines using a neon effect just like the pictures? The Paint class has a shader property that I thought I could set up to achieve this goal, but I don't realize how.
Container(
color: Colors.white,
width: 300,
height: 300,
child: CustomPaint(
painter: NeonPainter(),
),
),
class NeonPainter extends CustomPainter {
Paint neonPaint = Paint();
NeonPainter() {
neonPaint.color = const Color(0xFF3F5BFA);
neonPaint.strokeWidth = 2.5;
neonPaint.shader = /// how to create a shader or something for that?
neonPaint.someOtherProperty///
}
#override
void paint(Canvas canvas, Size size) {
drawLine(canvas, size.width / 2 - 50, size.height / 2, size.width / 2 + 50,
size.height / 2);
drawLine(canvas, size.width / 2 + 50, size.height / 2, size.width / 2 + 100,
size.height / 2 + 50);
drawLine(canvas, size.width / 2 + 100, size.height / 2 + 50,
size.width / 2 - 100, size.height / 2 + 50);
drawLine(
canvas, size.width / 2 - 100, size.height / 2 + 50, size.width / 2 - 50,
size.height / 2);
}
void drawLine(canvas, double x1, double y1, double x2, double y2) {
canvas.drawLine(Offset(x1, y1), Offset(x2, y2), neonPaint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
You can use BoxShadow widget.. You can set color, blurRadius, SpreadRadius and offset to achieve what you want..
Note in example I have used it to get a drop shadow.. But you can get a glow if you set the properties correctly..
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(50),
boxShadow: [
BoxShadow(
color: Color(0xFF000000).withAlpha(60),
blurRadius: 6.0,
spreadRadius: 0.0,
offset: Offset(
0.0,
3.0,
),
),
]),
use boxShadow property twice inside Container widget decoration. for outer glow use spreadRadius positive value and for inner glow use negetive value.
sample code is given below..
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(18.0),
),
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.pink,
spreadRadius: 4,
blurRadius: 10,
),
BoxShadow(
color: Colors.pink,
spreadRadius: -4,
blurRadius: 5,
)
]),
child: FlatButton(
onPressed:(){},
child: Text("submit"),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
),
),
),

Resources