The text inside my chatbubbles won't break in new line.
Here's the "chatbubble" extracted in an own view
struct chatPartnerBubble: View {
var textMsg: String
var body: some View {
VStack(alignment: .leading) {
HStack {
HStack {
Text(textMsg)
.foregroundColor(Color.white)
.padding(10)
.lineLimit(nil)
}
.background(Color.blue)
.cornerRadius(12)
Spacer()
}.padding(.leading)
}
}
}
and here is the ChatView
ScrollView {
VStack {
chatPartnerBubble(textMsg: "text")
chatPartnerBubble(textMsg: "text")
chatPartnerBubble(textMsg: "text")
chatPartnerBubble(textMsg: "text")
chatPartnerBubble(textMsg: "text")
chatPartnerBubble(textMsg: "text")
}
}
But if the textMsg is longer, it just dots..., and does not break into new line
You can achieve the desired functionality by choosing List over Scrollview. If we consider scalability factor in our chatting app then List is far better than Scrollview. Because views can be easily reusable in List.
struct chatPartnerBubble: View {
var textMsg: String
var body: some View {
VStack{
Text(textMsg)
.foregroundColor(Color.white)
.padding(10)
.lineLimit(nil)
}
.background(Color.blue)
.cornerRadius(12)
}
}
struct ContentView: View {
var body: some View {
List {
chatPartnerBubble(textMsg: "text1 111111111 1 11111111 1 1 1 1 1 1 1 1 111111111111")
chatPartnerBubble(textMsg: "text2 22222 222222222 2222222222222 222 2 2 2 22 2 222222")
chatPartnerBubble(textMsg: "text3 333333 3 333 333 3 3 3 3 33333333 3 33333333 3333333")
}
.padding(.top)
.onAppear {
UITableView.appearance().separatorColor = .clear
}
.onDisappear {
UITableView.appearance().separatorColor = .gray
}
}
}
In case we have more than one table view in our app, so OnAppear and onDisappear blocks are used to hide/show seperator only for above message table view.
I seems to work fine for me, I'm using Xcode 11.2 Beta 2, so the Xcode version might be the problem. I remember I had a similar problem before and the solution was VStack(alignment: .center, spacing: 0) maybe it helps
Related
I want to recreate the animated buttons found in the Photos app and shown below. My goal is to use this type of buttons in a TabView(or something similar) instead of the default ones. Does these type of buttons exist in swiftUI? Or what is a good way to create these buttons?
I have written some stupid code to illustrate the problem, but it feels like the wrong approach.
struct ContentView: View {
#State private var selection = 0
var body: some View {
ZStack(alignment: .leading) {
RoundedRectangle(cornerRadius: 10)
.frame(width: 100, height: 50)
.offset(x: CGFloat(selection * 100), y: 0)
HStack {
Button("Tap Me") {
withAnimation {
selection = 0
}
}
Spacer()
Button("Tap Me") {
withAnimation {
selection = 1
}
}
Spacer()
Button("Tap Me") {
withAnimation {
selection = 2
}
}
}
.frame(width: 300)
}
.padding()
.background(.green)
}
}
Output:
In my example code below, I have two tabs and within the main tab (Tab A) there are two "buttons" on the front page to allow the user to navigate to two views (View 1 or View 2) using navigationlinks. Within each of view 1 and view 2 there are further navigation links so my code (purposefully) resets the navigation stack for each view when you switch tabs and then return to the tab. Also, if you navigate to view 1 or view 2 (while still on the main tab (tab A)), tapping the main tab button (tab A) again brings you back to the front page (which presents the two buttons). This behaviour is what I need. The problem I now have is that the navigation links (to view 1 and view 2) don't work as intended. Sometimes clicking the view 1 button takes you to view 2 and sometimes it takes you to view 1. The same happens with the view 2 button. This must have something to do with how I reset the navigation stack for my other needs, but I'm not sure how to solve this. I include some minimal code to show this. Does anyone have an idea how to solve this? Thanks
struct ContentView: View {
#State var activeView: Int = 0
#State var showNavigation: Bool = false
let items = ["View1", "View2"]
var body: some View {
TabView(selection: Binding<Int> (
get: {
activeView
}, set: {
activeView = $0
showNavigation = false
}))
{
NavigationView {
HStack {
VStack {
NavigationLink(
destination: View1(), isActive: $showNavigation, label: {
Rectangle()
.fill(Color.red)
.cornerRadius(12)
.frame(width: 70, height: 70)
}).isDetailLink(false)
Text(items[0])
}
VStack{
NavigationLink(
destination: View2(), isActive: $showNavigation, label: {
Rectangle()
.fill(Color.red)
.cornerRadius(12)
.frame(width: 70, height: 70)
}).isDetailLink(false)
Text(items[1])
}
}.navigationTitle("")
.navigationBarHidden(true)
}
.tabItem {
Image(systemName: "a.circle")
Text("Main")
}
.tag(0)
View3()
.padding()
.tabItem {
Image(systemName: "b.circle")
Text("View 3")
}
.tag(1)
}
}
}
The problem seems to be that you're using the same showNavigation variable for both NavigationLinks.
I've changed the variable around a bit to hold an id and added a custom Binding to keep track of which NavigationLink should be active:
struct ContentView: View {
#State var activeView: Int = 0
#State var activeNavigationLink: Int = 0 //<-- Here
let items = ["View1", "View2"]
func navigationLinkBinding(id: Int) -> Binding<Bool> { //<-- Here
.init { () -> Bool in
activeNavigationLink == id
} set: { (newValue) in
if newValue {
activeNavigationLink = id
} else {
activeNavigationLink = 0
}
}
}
var body: some View {
TabView(selection: Binding<Int> (
get: {
activeView
}, set: {
activeView = $0
activeNavigationLink = 0 //<-- Here
}))
{
NavigationView {
HStack {
VStack {
NavigationLink(
destination: Text("View 1"), isActive: navigationLinkBinding(id: 1), label: { //<-- Here
Rectangle()
.fill(Color.red)
.cornerRadius(12)
.frame(width: 70, height: 70)
}).isDetailLink(false)
Text(items[0])
}
VStack{
NavigationLink(
destination: Text("View 2"), isActive: navigationLinkBinding(id: 2), label: { //<-- Here
Rectangle()
.fill(Color.red)
.cornerRadius(12)
.frame(width: 70, height: 70)
}).isDetailLink(false)
Text(items[1])
}
}.navigationTitle("")
.navigationBarHidden(true)
}
.tabItem {
Image(systemName: "a.circle")
Text("Main")
}
.tag(0)
Text("View 3")
.padding()
.tabItem {
Image(systemName: "b.circle")
Text("View 3")
}
.tag(1)
}
}
}
I am working on an app that requires 6 items in a PageView, xcode was acting up so i came on Stack Overflow and found pawello2222's way, found it really helpful but I still need to connect it to the horizontal links on top. here is the code, thanks a million.
Original solution: How can I implement PageView in SwiftUI?
Below is my code and what I want to achieve, swiping left or right works, but clicking on the links does not change the view
struct TestingView: View {
#State var selection = 0
var body: some View {
VStack {
HStack(spacing: 10) {
VStack {
Text("Link 1")
.foregroundColor(self.selection == 0 ? Color.blue : Color("Silver").opacity(0.7))
.font(.caption)
.fontWeight(.bold)
.clipShape(Rectangle())
.onTapGesture {
withAnimation(.default) {
self.selection = 0
}
}
}
Spacer(minLength: 0)
VStack {
Text("Link 2")
.foregroundColor(self.selection == 1 ? Color.blue : Color("Silver").opacity(0.7))
.font(.caption)
.fontWeight(.bold)
.clipShape(Rectangle())
.onTapGesture {
withAnimation(.default) {
self.selection = 1
}
}
}
Spacer(minLength: 0)
VStack {
Text("Link 3")
.foregroundColor(self.selection == 2 ? Color.blue : Color("Silver").opacity(0.7))
.font(.caption)
.fontWeight(.bold)
.clipShape(Rectangle())
.onTapGesture {
withAnimation(.default) {
self.selection = 2
}
}
}
}
PageView(selection: $selection, indexDisplayMode: .never, indexBackgroundDisplayMode: .never) {
VStack {
FirstView()
}
.tag(0)
VStack {
SecondView()
}
.tag(1)
VStack {
ThirdView()
}
.tag(2)
}
}
}
}
I tried to do a app that pop out a temporary alert that only appear for 1 or 2 seconds. It’s something like App Store rating.
But I don’t know what this called in swiftui. Can anyone answer me?
That is just a view that is shown or hidden conditionally. Here is a complete example that uses a ZStack to place the thank you view over the other view content. The thank you view is either present or not based upon the #State variable showThankYou. DispatchQueue.main.asyncAfter is used to remove the view after 3 seconds.
struct ContentView: View {
#State private var showThankYou = false
var body: some View {
ZStack {
VStack {
Spacer()
Text("Stuff in the view")
Spacer()
Button("submit") {
showThankYou = true
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
self.showThankYou = false
}
}
Spacer()
Text("More stuff in the View")
Spacer()
}
if showThankYou {
RoundedRectangle(cornerRadius: 16)
.foregroundColor(Color.gray)
.frame(width: 250, height: 250)
.overlay(
VStack {
Text("Submitted").font(.largeTitle)
Text("Thanks for your feedback").font(.body)
}
)
}
}
}
}
I know this has been solved in iOS 14 but my current project is in iOS 13 and we have to release it fast. I tried multiple approach from stack but no luck. I just want to click a button and scroll to the bottom of the ScrollView, thats it. I was surprised there is not built in function in SwiftUI for this !!!
struct ContentView: View {
var items = [Color.red, Color.orange, Color.yellow, Color.green,Color.blue, Color.purple, Color.red, Color.orange, Color.yellow, Color.green,Color.blue, Color.purple]
var body: some View {
ZStack {
ScrollView(Axis.Set.vertical, showsIndicators: false) {
VStack {
ForEach(self.items, id: \.self) { item in
// 3.
Circle()
.fill(item)
.frame(width: 100, height: 100)
}
}
}
VStack {
Spacer()
HStack {
Spacer()
Button(action: {
// scroll to bottom
}) {
Text("Button")
}
}
.padding(.trailing, 20)
.padding(.bottom, 20)
}
}
}
}
If anybody could help
After a few hours search i found this amazing library that does exactly as you want
ScrollView{ proxy in
Button("click"){
proxy.scrollTo(200)
}.foregroundColor(.red)
ForEach(0..<1000){ index in
Text("\(index)")
.scrollId(index)
}
}