nachonavarro / pages Goto Github PK
View Code? Open in Web Editor NEW📖 A lightweight, paging view solution for SwiftUI
License: MIT License
📖 A lightweight, paging view solution for SwiftUI
License: MIT License
I'm having an issue with the library, where any time any of my other state variables change on page, the animation triggers.
If I've got a Page 0, and a Page 1, the "moving back to 0" animation triggers anytime a variable changes on page 0 (UX element, etc).
Is there any way to prevent this from happening?
is there a way to hide the navigation bar in a ModelPages view? The navigationBarHidden modifier doesn't seem to work
The adaptation to SwiftUI works great thanks.
I needed this for pageCurl transition and not the scroll transition. However, the transition animation does not work properly. The top page curls up nicely and the next page is visible behind it. However, when the animation is complete the second page curls away too leaving a blank white page. There is an error message shown "Unbalanced calls to begin/end appearance transitions" .
Two things - (1) this problem does not occur when the transition type is scroll -only there for pageCurl type. (2). if I comment out the UIPageViewControllerDelegate method didFinishAnimating finished the problem goes away - the transition works nicely.
I am not sure that the problem is your code, because I get the same problem just using the code in the tutorial from Apple ( https://developer.apple.com/tutorials/swiftui/interfacing-with-uikit ) .
I can send you the complete example if needed. I am hoping that you can figure out a solution.
I have an animated view that starts on .onAppear.
By itself, it works fine, but in a Pages() view, it keeps loading the page over and over again...
For example, we open a book, stopped reading at page number 33. The book resumes at page 1 and we have to flip page by page until page number 33. If the book resumes at page 33, it would be great.
Pages(currentPage: self.$currentPage, bounce: true, hasControl: false) {
Text("A")
Text("B")
Text("C")
}
If another view updates self.currentPage
, the page surely updates, but it just snaps there. NO animation. Is there a way to make it animate to the next page?
Thanks!
Hello!
if dynamic header title, page scroll not work
How fix this?
There is examle:
struct TestView: View {
var body: some View {
NavigationView {
VStack {
List {
NavigationLink(destination: GalleryView()) {
Text("Gallery View")
}
}
}
}
.navigationBarTitle(Text(""), displayMode: .inline)
}
}
struct GalleryView: View {
@State var index: Int = 0
func setupTitle(forPage page: Int) -> String {
switch page {
case 0: return "Extended"
case 1: return "PrePay"
case 2: return "Disabled"
default: return "Extended \(page)"
}
}
var body: some View {
VStack(alignment: .leading, spacing: 8) {
Text("My Art Collection")
.font(.system(size: 40, weight: .bold))
.padding([.horizontal, .top])
ModelPages(paintings, currentPage: $index, hasControl: false) { i, painting in
PaintingView(painting: painting)
}
Spacer()
}
.navigationBarTitle(Text(setupTitle(forPage: index)), displayMode: .inline)
}
}
private struct PaintingView: View {
var painting: Painting
@State var list = ["One", "Two", "Three", "Four", "Five", "Six", "Seven"]
var body: some View {
VStack {
Image(painting.image)
.resizable()
.scaledToFit()
VStack(alignment: .leading) {
Text(painting.title)
.font(.system(size: 30, weight: .bold))
Text(painting.author)
.foregroundColor(.secondary)
}
List {
ForEach(list, id: \.self) {
Text($0)
}
.onMove { self.list.move(fromOffsets: $0, toOffset: $1) }
}
Button(action: {}) {
HStack {
Spacer()
Text("Buy for $\(painting.price)")
.fontWeight(.semibold)
.foregroundColor(.white)
.padding(.vertical)
Spacer()
}
.background(Color.blue)
.cornerRadius(10)
}
.padding(.top, 30)
Spacer()
}
.padding(.horizontal)
.environment(\.editMode, .constant(.active))
}
}
I would be very interested in being able to dynamically remove a page by, say, clicking on a button on said page. Currently, this is not supported and if the data element is removed, PageViewController crashes with index out of range.
How do we integrate navigation link with pages? I have tried the code below. The view shows it was clicked (visually), however no desination is actually navigated to.
var body: some View {
ModelPages(cars) { index, car in
NavigationLink(destination: DestinationView(car: car)) {
Text("The \(index) car is a \(car.model)")
.padding(50)
.foregroundColor(.white)
.background(Color.blue)
.cornerRadius(10)
}
}
}
Hi, background colors of the ViewController's.view should be .clear.
PageViewController.swift:52
Pages.swift:105
ModelPages:115
I somehow cannot create a brach....
Animation is coming twice and also it ends with a white screen.
i don't want those pagination dots that controlAlignment brings. How can I disable them?
Hello! thank you for your solution, but I cannot use it with dinamic array.
My code
`
import SwiftUI
import Pages
struct Car {
var model: String
}
struct CarsView: View {
@State var cars = [Car(model: "Ford"), Car(model: "Ferrari")]
@State var index: Int = 0
var body: some View {
VStack {
GeometryReader { g in
ModelPages(self.cars, currentPage: self.$index) {index, car in
VStack(alignment: .leading) {
Text(car.model).font(.title)
Button(action: {
self.cars.append(Car(model: "BMW"))
}) {
Text("Add").font(.title)
}
}
}
}
}
}
}
`
When I added element it stop work and element doesn't add.
Thanks for a great library!
I am facing a problem where scrolling stops working when the view hierarchy changes. At first, everything works great. However, if I modify the view hierarchy in any way (e.g. by setting a state property that causes a label to change), the page view's scroll just starts bouncing back. The problem appears in both Pages
and ModelPages
.
Do you have any idea what may be causing this?
UPDATE The problem exists in 0.1.3
, but is solved in master
. Can you consider making a 0.1.4
version of master?
Hi, this is an amazing package, thanks! Is there a way to modify the code to only allow page turning when swiping? I have views with .onTapGesture{} placed near the edge and it's causing the page to turn instead of performing the function I'm calling. I was looking at the files in this package but can't seem to figure out if this an be done.
When i want to show current index, rightToLeft swipe is not working. If i enter to some text (like Text("Test header"), it's working. Really interesting.
`import Pages
struct WelcomeView: View {
@State var index: Int = 0
var body: some View {
VStack {
Text("\(index)")
Spacer()
Pages(currentPage: $index) {
Text("Welcome! This is Page 1")
Text("This is Page 2")
Text("...and this is Page 3")
Circle() // The 4th page is a Circle
}
}
}
}`
Hello, I am trying to make a UI like TikTok but the images are behaving weirdly. It works fine on my 11 pro max but not on a screen size smaller, it sort of jumps around. Screenshot
Pages image issue (clipping)
<script async src="//s.imgur.com/min/embed.js" charset="utf-8"></script>Hello, I am trying to make a TikTok style UI.
I have tried this:
struct ContentView: View {
@State var index: Int = 0
var body: some View {
Pages(currentPage: $index, navigationOrientation: .vertical) {
Image("ModelX")
}
}
}
However I get this error: Cannot convert value of type 'Image' to closure result type '[AnyView]'
I have also tried doing this:
struct ContentView: View {
@State var index: Int = 0
var body: some View {
Pages(currentPage: $index, navigationOrientation: .vertical) {
NewsView()
}
}
}
struct NewsView: View{
var body: some View {
Image("modelX")
}
}
However I get the same error but lightly different: Cannot convert value of type 'NewsView' to closure result type '[AnyView]'
Anyhelp is appreciated, I am not a noob but I am new to swiftUI
Hi,
When I change the page programmatically, it is animated once. If I swipe to the next page, I get it animated twice, i.e., once with my swipe and again (to the same page) upon release. This ONLY happens if i change the color of the buttons' texts according to the index. If i leave the color as is, it works fine.
Used your demo "OnboardingView" for this.
`struct OnboardingView: View {
@State var index: Int = 0
var body: some View {
VStack {
HStack {
Button(action: {
self.index = 0
}) {
Text("page 1")
.foregroundColor(self.index == 0 ? Color.red : Color.black)
}
Button(action: {
self.index = 1
}) {
Text("page 2")
.foregroundColor(self.index == 1 ? Color.red : Color.black)
}
Button(action: {
self.index = 2
}) {
Text("page 3")
.foregroundColor(self.index == 2 ? Color.red : Color.black)
}
Button(action: {
self.index = 3
}) {
Text("page 4")
.foregroundColor(self.index == 3 ? Color.red : Color.black)
}
}
Pages(currentPage: $index, wrap: false) {
WelcomePage(background: "avenue",
title: "Ready. Set. Apple.",
subtitle: "Insert witty remark about your app that will catch potential users.")
WelcomePage(background: "elephant",
title: "Wow. An elephant.",
subtitle: "Did you know these magnificent mammals spend between 12 to 18 hours eating grass, plants and fruit every single day?")
WelcomePage(background: "nature",
title: "Nature.",
subtitle: "I'm running out of subtitles.")
WelcomePage(background: "landscape",
title: "Ah yes, Scotland.",
subtitle: "They may take our lives, but they'll never take our freedom!")
}.padding()
}
}
}`
Same issue with wrap: true
.
Printout (e.g., Current page is 1, going to 0
) is done once, when the page is changed twice.
Afraid that I have no idea how to fix this...
非常感谢有这么好的开源组件,在使用的过程中遇到一些小的问题。
给Page添加Onchange事件以后会触发页面滑动两次的问题。
希望能给作者解决BUG提供一些思路。
Hello again :)
I want to load each news inside of pages, I am loading Html content in wkwebview and I added it to the inside of pages. When I move to the next page webview height is the same as the previous one, does not load with new height.
What do you recommend to solve this issue ? Thanks in advance :)
WebTest View
import SwiftUI
import Pages
struct WebTest: View {
@ObservedObject var viewModel = NewsVM()
@State var index: Int = 0
@State var newID: String = ""
let screen = UIScreen.main.bounds
let formatString = "<html><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=0\"><script type=\"text/javascript\" src=\"https://platform.twitter.com/widgets.js\"></script><style>@media (prefers-color-scheme: dark) { body { background-color: #1c1c1e; color: white; }} img,iframe,blockquote {\n\t\t\tmax-width: \(UIScreen.main.bounds.width - 24);\n\t\t\theight: auto\n\t\t}\n\t\t</style></head><body><span style=\"font-family: '-apple-system', 'HelveticaNeue'; font-size:17\">%@</span></body></html>"
@State private var webViewHeight: CGFloat = .zero
init(id:String) {
viewModel.fetchNews(id: id)
self.newID = id
}
var body: some View {
Group{
if self.viewModel.news.count > 0 {
ModelPages(viewModel.news, currentPage: $index, wrap: false, hasControl: false) { pageIndex, new in
ScrollView(.vertical, showsIndicators: false){
Text(new.title)
.font(.title).fontWeight(.bold)
.padding(.horizontal)
.fixedSize(horizontal: false, vertical: true)
Text("Height: \(self.webViewHeight)").padding()
WebView(htmlString: String(format: self.formatString, new.content), dynamicHeight: self.$webViewHeight)
.frame(width: self.screen.width - 16, height: self.webViewHeight)
.padding(.horizontal, 8)
}
}
}else{
Group{
if self.viewModel.error == true{
ConnectionError()
}else{
LoadingView()
}
}
}
}
}
}
WebView
import SwiftUI
import Webkit
struct WebView: UIViewRepresentable {
var htmlString: String
@Binding var dynamicHeight: CGFloat
var webView: WKWebView = WKWebView()
func makeUIView(context: Context) -> WKWebView {
webView.navigationDelegate = context.coordinator
webView.scrollView.bounces = false
webView.backgroundColor = .clear
if htmlString != context.coordinator.content {
context.coordinator.content = htmlString
webView.loadHTMLString(htmlString, baseURL: Bundle.main.bundleURL)
}
return webView
}
func updateUIView(_ uiView: WKWebView, context: Context) {
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, WKNavigationDelegate {
var parent: WebView
var content = ""
init(_ parent: WebView) {
self.parent = parent
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
webView.evaluateJavaScript("document.readyState", completionHandler: { (complete, error) in
if complete != nil {
webView.evaluateJavaScript("document.documentElement.scrollHeight", completionHandler: { (height, error) in
DispatchQueue.main.async{
self.parent.dynamicHeight = height as? CGFloat ?? 0
}
})
}
})
}
}
}
First content height is true, but the second view still using same height
I have a menu that changes the content shown on the screen. In two of the different views I used Pages. Showing the first instance of Pages works fine, but when I go to the other view with an instance of Pages, the Pages view flashes and then disappears. Then if I try to go back the other one disappears as well. If I remove one instance of Pages it works fine.
I have follow situation.
struct HomeView { ... Pages(currentPage: self.$currentPage) { ChannelsView() PublicationsView() MarkedView() } ...
The problem is coming from that in PublicationsView, Im realoading some data and view should be rendered again. Then "controllers" array is updated and refill with newest views.
But in the Coordinator the parent reference keep the first "controllers" array. That follow to a bug:
in "viewControllerBefore" and "viewControllerAfter" -> "parent.controllers.firstIndex(of: viewController)" is returning nil and the pages cannot be changed.
I cannot find a easy solution. Could you help me?
I know this has been added recently (#8, 9642f78), but for my use case it works best when animations are disabled.
For some context I‘m changing page contents and page index on swiping, effectively creating an possibly infinite number of pages. Currently, the animation of the real swipe and the implicit one by changing the page index causes a slight flickering.
It would be great to have both possibilities and even better a dynamic way of switching this programmatically.
Hi, firstly I wanna say thanks for this package.
I tried to use dynamic page with my ViewModel data but when I tried to run the app, I got to crash with an index out of range error.
Fatal error: Index out of range
View:
struct SliderNewsList: View {
@ObservedObject var viewModel = SliderNewsVM()
@State var index: Int = 0
var body: some View {
ModelPages(viewModel.news, currentPage: $index) { pageIndex, new in
Text(new.title)
}
}
}
ViewModel:
class SliderNewsVM: ObservableObject {
@Published var news = [SliderNews]()
init() {
fetchSliderNews()
}
}
extension SliderNewsVM {
func fetchSliderNews() {
ApiManager.shared.fetchSliderNews { [weak self] result in
guard let self = self else { return }
switch result {
case .success(let result):
self.news = result
case .failure(_):
print("error")
}
}
}
}
This is a good lib, but looks like it's not dealing with rotation at all.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.