How to create cover-flow with swiftui without using external api - swiftui

How I could create a Cover flow with SwiftUI TabView without using any external dependency.
Like this image
enter image description here
TabView(selection: self.$pg.index){
ForEach(0 ..< 5) {item in
FruitCardView(fruit: fruitsData[item])
}
}.tabViewStyle(PageTabViewStyle(indexDisplayMode: .always))
.edgesIgnoringSafeArea(.leading)
.padding(.vertical, 20)
How I want to display it :
enter image description here
Thanks in advance

You can use Tabview.
TabView {
ForEach(pages) { page in
Text(page.name)
}
.frame(width: 200, height: 200)
}
.tabViewStyle(PageTabViewStyle())
https://developer.apple.com/documentation/swiftui/tabview

Related

swiftui tabbar item image profile picture

I want to set the users Profile Picture as the item Image of the Tabbar.
What I tried so far is following:
ProfileView()
.tag(3)
.tabItem {
if selectedTab == 3 {
Image("1024")
.resizable()
.scaledToFit()
.frame(width: 20.0, height: 20.0)
} else {
Image(systemName: "bell")
}
}
It also shows the Image, but way to big - it doesn't resize to the 20x20...
Am I missing something? .renderingMode(.template) doesn't help as well

How to get a horizontal picker for Swift UI?

Is there an existing solution to get a horizontal picker in Swift UI?
Example for Swift: https://github.com/akkyie/AKPickerView-Swift
I ended up solving this using a horizontal scrollview, tap gestures, and state to track the selection.
#State private var index
var body: some View {
        return ScrollView(.horizontal, showsIndicators: false) {
            HStack {
                ForEach(0..<self.items.count, id: \.self) { i in
                    Text("\(i)")
                        .foregroundColor(self.index == i ? .red : .black)
                        .frame(width: 20, height: 20)
                        .gesture(TapGesture().onEnded({ self.index = i }))
                }
            }
        }
        .frame(width: self.width, alignment: .leading)
}
You can use the Rotation Effect on a Picker and on the Picker's content. Make sure to rotate the content 90 degrees opposite from the picker or else the content will be sideways. If the picker is too big, you can manually set a height of the picker by using frame(height: _). In my case, I used frame(maxHeight: _). You might need to adjust the row indicators by using clipped() after the resize to stop them from flowing out of the picker.
I'm using images as an example but it should work with most if not all basic views.
Code:
Picker(selection: $data, label: Text("Data")) {
ForEach(dataArray, id: \.self) { imageName in
Image(imageName)
.resizable()
.scaledToFit()
.rotationEffect(Angle(degrees: 90))
}
}
.labelsHidden()
.rotationEffect(Angle(degrees: -90))
.frame(maxHeight: 100)
.clipped()

Images now showing within NavigationView/NagivationLink

I was trying to show multiple clickable images within NavigationView/NagivationLink container(s).
var body: some View {
NavigationView {
VStack {
ForEach(self.sets) { set in
NavigationLink(destination: ExerciseVideoView(items: set.items )) {
Image("group-\(set.purpose)")
.resizable()
.frame(height: 300, alignment: .leading)
}
}
}
}
}
But the images are not shown.
When i remove NavigationView & NagivationLink lines - everything goes well, apart from making the images clickable of course. Here's how the screen looks like when images are shown:
and this is what happens when i uncomment NavigationView & NagivationLink lines:
Could you please explain me why are not they shown when i use NagivationLink?
Thanks!
The NavigationLink interprets images by default as template rendering mode, so you have to specify explicitly
NavigationLink(destination: ExerciseVideoView(items: set.items )) {
Image("group-\(set.purpose)")
.resizable()
.renderingMode(.original) // << here !!
.frame(height: 300, alignment: .leading)
}

How to save List state for View in TabView SwiftUI

I have a TabView in SwiftUI with tabs. When I scroll list from one FirstView and tap another tab, and switch back to FirstView, my List in FirstView automatically redraws and scrolls to top. How to fix that.
enter link description here
This is FirstView
var body: some View {
NavigationView {
List {
ForEach(feed) { game in
FeedCardItem(gameModel: game)
.frame(width: UIScreen.main.bounds.width - 30, height: 400)
}
}
.navigationBarTitle(Text("Новое сегодня"))
}
}
This is TabView implementation
TabView (selection: $currentTab) {
FeedView().tabItem {
Image(systemName: currentTab == 0 ? "house.fill" : "house")
.renderingMode(.original)
.imageScale(.large)
}.tag(0)
RecommendationsView().tabItem {
Image(systemName: currentTab == 1 ? "gamecontroller.fill" : "gamecontroller")
.renderingMode(.original)
.imageScale(.large)
}.tag(1)
SearchView().tabItem {
Image(systemName: currentTab == 2 ? "flame.fill" : "flame")
.renderingMode(.original)
.imageScale(.large)
}.tag(2)
NotificationsView().tabItem {
Image(systemName: currentTab == 3 ? "bell.fill" : "bell")
.renderingMode(.original)
.imageScale(.large)
}.tag(3)
ProfileView().tabItem {
Image(systemName: currentTab == 4 ? "person.fill" : "person")
.renderingMode(.original)
.imageScale(.large)
}.tag(4)
}.edgesIgnoringSafeArea(.top)
}
I don't think it is possible via SwiftUI. The alternate to do this is to create the tabview in UIKit and use it in SwiftUI.
I have created a quick sample of how this can be achieved and how it solves your issue. Let me know if you have any other questions.
I have uploaded the code to GitHub.
https://github.com/subhan5/TabTest
In the uploaded code, the folder UITab contains the tabview created via UIKit.
In ContentView, I convert the same as UIViewControllerRepresentable and use it.
I have the same problem, and found this solution: https://kavsoft.dev/SwiftUI_2.0/Tab_Bar
Basically, you could just hide the content of one tab instead of replace it with another content view. I thought this solution is a little tricky but works.
it is possible with the UITableViewConfigurator which is described here: Scroll SwiftUI List to new selection
But of course...this uses UIViewControllerRepresentable....

Detailed list view - top alignment question

Added on the 24th of July:
This line of code fixes the space in the detail view. However... in the list view the title has become a lot smaller too.
.navigationBarTitle(Text("Egg management"), displayMode: .inline)
Added on the 23th of July:
Thanks to the tips I made a lot of progress. Especially the tip to add borders does wonders. You see exactly what happens!
However, there seems to be a difference between the Xcode Preview canvas, the simulator and the physical device. Is this a bug because -after all- it is still beta? Or is there anything I can do?
As you can see in the images... only in the Xcode Preview canvas the view connects to the top of the screen.
I believe it has something to do with the tabbar. Since when I look at the Xcode Preview canvas with the tabbar... that space above is also there. Any idea how to get rid of that?
Original postings:
This is my code for a detailed list view:
import SwiftUI
struct ContentDetail : View {
#State var photo = true
var text = "Een kip ..."
var imageList = "Dag-3"
var day = "3.circle"
var date = "9 augustus 2019"
var imageDetail = "Day-3"
var weight = "35.48"
var body: some View {
VStack (alignment: .center, spacing: 10) {
Text(date)
.font(.title)
.fontWeight(.medium)
ZStack (alignment: .topLeading){
Image(photo ? imageDetail : imageList)
.resizable()
.aspectRatio(contentMode: .fit)
.background(Color.black)
.padding(.trailing, 0)
.tapAction {
self.photo.toggle() }
HStack {
Image(systemName: day)
.resizable()
.padding(.leading, 10)
.padding(.top, 10)
.frame(width: 40, height: 32)
.foregroundColor(.white)
Spacer()
Image(systemName: photo ? "photo" : "pencil.circle")
.resizable()
.padding(.trailing, 10)
.padding(.top, 10)
.frame(width: 32, height: 32)
.foregroundColor(.white)
}
}
Text(text)
.lineLimit(6)
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
.padding(.leading, 6)
} .padding(20)
}
}
#if DEBUG
struct ContentDetail_Previews : PreviewProvider {
static var previews: some View {
ContentDetail()
}
}
#endif
Also included is the preview canvas. What I don't get is how I can make sure the text and photo are aligned to the top (instead of the middle). I tried with Spacers, padding etc.
I must be overseeing something small I guess... but. Can somebody point me in the right direction? Thanks.
Added:
After both answers I added a Spacer() after the last text. In Xcode in the preview canvas everything looks okay now. But on my connected iPhone 7 Plus there are some problems: the view is not aligned to the top, and the image is cropped (icon on the right is gone; white banding to the right).
Adding a Spacer() after the last text shifts everything to the top. Tested on iPhone Xr simulator (not preview).
...
Text(text)
.lineLimit(6)
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
.padding(.leading, 6)
Spacer()
}
To remove the space at the top:
VStack {
...
}
.padding(20)
.navigationBarTitle("TITLE", displayMode: .inline)
Think in terms of what a Spacer() does. It "moves" the views as far apart as it can - at least, without a specific space.
So you have this:
VStack {
Text
ZStack {
Image
HStack {
Image
Spacer()
Image
}
}
Text
}
All told, going from inner to outer, you have a horizontal stack of two images placed as far apart (the spacer is between them) inside of a "Z axis" stack that places an image on top of them, inside of a vertical stack that has some text above it.
So if you want to move everything in that vertical stack to the top, you simply need to add one last spacer:
VStack {
Text
ZStack {
Image
HStack {
Image
Spacer()
Image
}
}
Text
Spacer() // <-- ADD THIS
}
Last note: Don't be afraid to adding additional "stacks" to your view. In terms of memory footprint, it's really just a single view with no performance hit.
EDIT: I took your original view and changed everything to placeholders...
var body: some View {
VStack (alignment: .center, spacing: 10) {
Text("Text #1")
.font(.title)
.fontWeight(.medium)
ZStack (alignment: .topLeading) {
Text( "Image #1")
HStack {
Text("Image #2")
Spacer()
Text("Image #3")
}
}
Text("Text #2")
.lineLimit(6)
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
.padding(.leading, 6)
} .padding(20)
}
As expected, everything is vertically centered. Adding a Spacer() below "Text #2" throws everything to the top. A couple of thoughts:
Starting there, and add in your Image views one by one. Add in the modifiers like that also.
I don't have the specific images you are rendering, so maybe put a noticeable background color on various things (orange is my personal favorite) and see if the top Image is actually on top but the image makes it appear as though it isn't. A border would work pretty well too.