Giter Club home page Giter Club logo

waterfallgrid's People

Contributors

paololeonardi avatar tatsuz0u avatar toshi0383 avatar youjinp avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

waterfallgrid's Issues

right to left grid

I need it to be right to left grid. is there any possibility to do that?

Cannot find 'WaterfallGrid' in scope

Hi, I am new to SwiftUI and I am a little lost on how to actually incorporate WaterfallGrid into my app / UI. I tried creating a WaterfallGrid as such:

WaterfallGrid(listsViewModel) { listViewModel in
    NavigationLink(destination: ItemListView(list: listViewModel.list)) {
        CardView(listViewModel: listViewModel)
    }
}

But i get the error: Cannot find 'WaterfallGrid' in scope

Nondeterministic layout bug

Hi,
I am using the WaterfallGrid to layout thumbnails of different aspect ratios. The data (including the JPEG data for the thumbnail images) comes from a local database (using GRDB). But it is read synchronously on the main thread, and the order (and content) of the displayed items does not change.
However the layout does. Sometimes it displays correctly, sometimes it does not (thumbnails overlap). See attached video where I switch back and forth between tabs of the app (not an actual TabView, the tab content is recreated from scratch each time).

The following error/warning shows up in the Xcode console when the thumbnails end up overlapping, but not when the layout works correctly:

Bound preference ElementPreferenceKey tried to update multiple times per frame.

Any idea what is causing this, and how I could fix it?

Btw, as you can see in the video, the layout always animates on initial display. Is that by design? And can that be disabled, ideally without disabling animations during changes?

layout_bug.mov

If there are less than two images to be displayed, nothing will be displayed.

Hi all, I have found a bug.

When using WaterdallGrid, if there are less than 2 data to display, nothing will be displayed.

Here is a piece of source code that reproduces the bug at my end

ScrollView {
                        WaterfallGrid(dataArray, id: \.self) { file in
                            VStack {
                                if let post = viewModel.posts.first(where: { $0.fileIds.contains(file.id) }) {
                                    NavigationLink(destination: ImageDetailView(item: post, file: file)) {
                                        // View to display images.
                                        ImageGridItem(url: file.url!)
                                    }
                                }
                            }
                        }
                    }
import SwiftUI
import Kingfisher

// View to display images.
struct ImageGridItem: View {
    
    private var url: String
    
    init(url: String) {
        self.url = url
    }
    
    var body: some View {
        KFImage.url(URL(string: url))
            .resizable()
            .placeholder{
                RoundedRectangle(cornerRadius: 30)
                    .fill(Color(0xe6e6e6))
            }
            .scaledToFit()
            .clipped()
            .cornerRadius(5)
            .aspectRatio(contentMode: .fit)
    }
}
3 or more less than two data

Please some advice or fix

Getting Cannot convert value of type 'some View' to closure result type '_'

struct WaterfallGallery: View {
    @ObservedObject var loader: ImagesLoader
    @State var urlPaths: [String]
    
    init(urlPaths: [String]) {
        var URLs = [URL]()
        for urlPath in urlPaths {
            //TODO: provide defualt error image
            URLs.append(URL(string: urlPath)!)
        }
        self._urlPaths = State(initialValue: urlPaths)
        self.loader = ImagesLoader(urls: URLs)
    }
    
    var body: some View {
        Group {
            if self.loader.isLoading {
                placeHolder
            } else {
                gallery
            }
        }
            .onAppear(perform: loader.load)
            .onDisappear(perform: loader.cancel)
    }
    
    private var gallery: some View {
            WaterfallGrid(self.loader.$images) { uiImage in
                Image(uiImage: uiImage).resizable().aspectRatio(contentMode: .fit).cornerRadius(10)
            }
           .gridStyle(columns: 2)
    }
    
    private var placeHolder: some View {
         Text("Loading")
    }
}

I followed the example to use WaterfallGrid but keep getting Cannot convert value of type 'some View' to closure result type '_' on line:

Image(uiImage: uiImage).resizable().aspectRatio(contentMode: .fit).cornerRadius(10)

Support for async images with placeholder?

I have an AsyncImage class that displays a placeholder when the image is fetching. I tried to use this library with my AsyncImage but it just gets stuck with showing the placeholder. My guess is the WaterFallGrid isn't updating when the AsyncImages changed? Is there any way to handle url images besides pre-loading them into an array of UIImages?

Can't see on Canvas, on in Preview Mode

If I include within one of my own views, I can't see it on the canvas in Xcode. However I can see it in Preview mode.

My code is fairly simple:

WaterfallGrid(allTopics, id: \.id) { topic in TopicCapsule(topic: topic) }

Screen Shot 2020-12-03 at 11 39 27 AM

Screen Shot 2020-12-03 at 11 39 36 AM

LongPressGesture Gestures conflict

WaterfallGrid((0..<30), id: .self) { index in
CategoryBook().gesture(LongPressGesture(minimumDuration: 0.5, maximumDistance: 1).onEnded{ v in
self.previewShow = true
})
}

use LongPressGesture can't scroll

Images not loading in two columns

I am having an issue where when I first come to the screen the images don't go into two columns like they should. After I navigate into one of the image items and return to the initial screen the images go into two columns.

Initial view of screen:
IMG_0924

Navigate away from screen:
IMG_0925

Navigate back to screen, images waterfall as they should:
IMG_0926

My code:

`
struct FavoritesView: View {

@EnvironmentObject var viewRouter: ViewRouter
@ObservedObject var favoriteItems = FavoriteItemModel()

var body: some View {
    
    HStack {
        WaterfallGrid(favoriteItems.favorites, id: \.self) { item in
            FavoriteItemView(favoriteitem: item)

        } // Waterfall
        .gridStyle(
            columnsInPortrait: 2,
            columnsInLandscape: 3,
            spacing: 8,
            padding: EdgeInsets(top: 16, leading: 8, bottom: 16, trailing: 8),
            animation: .easeInOut(duration: 0.5)
        )
        .navigationBarTitle("Favorites", displayMode: .inline)
        .onAppear(perform: getFavorites)
    } // HStack
    
}

func getFavorites() {
    favoriteItems.loadFavorites()
}

}
`

`
struct FavoriteItemView: View {

let favoriteitem: FavoriteItem
@EnvironmentObject var shareableItemVM: ShareableItemViewModel
@State private var showShareableModal: Bool = false

var body: some View {
    HStack{
        NavigationLink(destination: ShareableDetailView(shareableId: self.favoriteitem.id, categoryId: 0, categoryType: "", shareItemType: favoriteitem.itemType, showShareableModal: self.$showShareableModal)) {
                WebImage(url: URL(string: self.favoriteitem.itemImage))
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .cornerRadius(10)
        }
        .environmentObject(self.shareableItemVM)
        .buttonStyle(PlainButtonStyle())
    }
}

}
`

I am using similar code with the WaterfallGrid in a couple other views, and I do not have this issue. The only thing I can think of is because these images are at different heights.

Any thoughts?

Invalid frame dimension (negative or non-finite)

I am getting this warning when I run my app and go to the view that is using the WaterfallGrid.

Screen Shot 2021-02-09 at 8 21 31 AM

I think it's causing what than displays to disappear when I scroll up on the page. I'm not sure.

`///:  FAVORITE ITEMS GRID
     WaterfallGrid(favoriteItems.favorites, id: \.self) { item in
        ZStack(alignment: .topTrailing) {
            FavoriteItemView(favoriteItem: item)
         } ///: ZSTACK
       } //: WATERFALL
          .gridStyle(
             columnsInPortrait: 2,
             columnsInLandscape: 3,
             spacing: 10,
             animation: .easeInOut(duration: 0.5)
          )
          .padding(EdgeInsets(top: 0, leading: 8, bottom: 15, trailing: 8))
                .scrollOptions(direction: .vertical)
                .onAppear(perform: loadFavorites)`

I am pulling the items that display from Cloud Firestore.

`func loadFavorites() {
    
    db.collection("favorites").getDocuments() { (querySnapshot, err) in
        if let err = err {
            print("Error getting documents: \(err)")
        } else {
            for document in querySnapshot!.documents {

                let docId = document.documentID
                let itemInfo = document.data()
                let itemType = itemInfo["itemType"] as? String ?? "shareable"
                let itemTitle = itemInfo["itemTitle"] as? String ?? "DaySpring"
                let itemImage = itemInfo["itemImage"] as? String ?? "No Photo"
                let itemAuthor = itemInfo["itemAuthor"] as? String ?? "DaySpring"
             
                db.collection("users").document(userId!).addSnapshotListener { documentSnapshot, error in
                    guard let userFavs = documentSnapshot else {
                        print("Error fetching document: \(error!)")
                        return
                    }
                    guard let data = userFavs.data() else {
                        print("Document data was empty.")
                        return
                    }
                    if let favorites = data["favorites"] as? [String: Any] {
                        if let favItem = favorites[docId] as? [String: Any] {
                            if let fav = favItem["itemActive"] as? Bool {
                                if fav {
                                    if let itemDate = favItem["itemAdded"] as? Timestamp {
                                        let thisDate = itemDate.dateValue()
                                        self.favorites.append(FavoriteItem(id: docId, itemType: itemType, itemImage: itemImage, itemTitle: itemTitle, itemAuthor: itemAuthor, itemDate: thisDate))
                                        DispatchQueue.main.async {
                                            self.favorites.sort(by: { $0.itemDate > $1.itemDate })
                                        }
                                    }

                                }
                            }
                        }
                    }
                }
                
            }
        }
    }
    
}`

maxHeight not supported

Hi, I've tried to set a maxHeight for each item like this:

KFImage(imgUrl)
            .resizable()
            .aspectRatio(contentMode: .fit).frame(minHeight: 0, maxHeight: 400).border(Color.red)

But finally each item becomes the same height 400. How could I get maxHeight worked?

Grid that fits contents?

I want to use WaterfallGrid to contain some buttons which are laid out in a grid depending on the size available. WaterfallGrid is in a VStack with a List and some other views. I want the grid to just fit the buttons, so to fit the content as tightly as possible, and disable scrolling. Is this possible?
Screenshot 2020-01-27 at 09 48 53

Lazy loading

Does this library support lazy loading where it doesn't load everything upfront but instead loads just visible elements?

Thank you!

Span over columns

Hi, is there a way to span a cell over multiple columns?
For example, I want 2 cells, and then 1 cell that spans over all columns…

1 2
-3-
4 5

thx

Layout issue in simulators

Hi just wanted to mention that there is a layout issue on simulators (iPhone 11 Pro). Awesome grid btw.
Simulator Screen Shot - iPhone 11 Pro - 2019-11-06 at 12 19 06

How to disable scrolling?

Hi there!

I was wondering if there is any way to disable the scrolling option and just have the stack show up? I'm trying to create a 2 by 2 grid.

WaterfallGrid((0..<4), id: .self) { index in
Rectangle()
.foregroundColor(Color("primary"))
.cornerRadius(8)
.frame(height: 125)
}
.gridStyle(
columns: 2,
spacing: 24,
padding: EdgeInsets(top: 20, leading: 30, bottom: 30, trailing: 30)
)

Thank you!

Self-adopting to different devices?

I'm using the WaterfallGrid in my own application. Although it's a great help, it seems that it does not adopt itself to the device.

This is how I integrated it:

var body: some View {
		
		Frame(title: "My Personal Data") {
			
			ForEach(self.model.content.rows) { row in
				
				VStack {
					
					WaterfallGrid(row.cards) { card in
						
						SectionCard(content: card,
									configuration: card.configuration,
									onTapClosure: { id in
										
										debugPrint("Tapped: \(id)")
						})
					}
					.gridStyle(spacing: 50,
							   padding: EdgeInsets(top: 100, leading: 0, bottom: 0, trailing: 0))
				}
			}
		}
		.onAppear(perform: {
			
			self.model.load()
		})
	}

While on an iPad, everything looks fine:

Simulator Screen Shot - iPad Air (3rd generation) - 2020-03-20 at 21 28 54

the iPhone display is not what I expected:

Simulator Screen Shot - iPhone 11 Pro Max - 2020-03-20 at 21 29 03

Am I doing something wrong?

Problem with pagination / Load more

When i add more image in my @State variable it scrolls down 🤔

import SwiftUI
import Alamofire
import WaterfallGrid

struct HomeScreen: View {
    
    @State var newPhotos: [HomeImage] = []
    @State var pageNumber : Int = 1
    @State var isPageRefreshing : Bool = false
    @State var didAppear = false
    
    @StateObject var homeImageVm = HomeScreenViewModel()
    
    var body: some View {
        NavigationView {
            ScrollView(.vertical, showsIndicators: false) {
                LazyVStack {
                    WaterfallGrid(newPhotos) { item in
                        NavigationLink(destination:
                                        SelectedImage(image: SelectedImageClass(id: item.id, createdAt: item.createdAt, updatedAt: item.updatedAt, promotedAt: item.promotedAt, width: item.width, height: item.height, color: item.color, blur_hash: item.blur_hash, homeImageDescription: item.homeImageDescription, altDescription: item.altDescription, description: item.description, urls: item.urls, user: item.user, categories: item.categories))
                        ) {
                            AppNetworkImage(imageUrl: item.urls?.small ?? "")
                        }
                    }
                    .gridStyle(
                        columnsInPortrait: 2,
                        columnsInLandscape: 3,
                        spacing: 8,
                        animation: .linear(duration: 0.5)
                    )
                    .scrollOptions(direction: .vertical)
                .padding(EdgeInsets(top: 16, leading: 8, bottom: 16, trailing: 8))
                }
                Button("Load More") {
                    
                    getHotPhotos(page: pageNumber)
                }
                .padding()
            }
            .onAppear(perform: {
                if !didAppear {
                    getHotPhotos(page: pageNumber)
                }
                didAppear = true
            })
            .navigationBarTitle("Home", displayMode: .automatic)
            .navigationBarItems(
                trailing:
                    NavigationLink(destination:
                                    SearchImageScreen()
                                  ) {
                                      Image(systemName: "magnifyingglass")
                                  }
            )
        }
    }
    
    func getHotPhotos(page:Int) {
        let parameters: [String: Any] = [
            "client_id" : AppConst.clinetid,
            "order_by": "latest",
            "page":String(page),
            "per_page":"20"
        ]
        AF.request(AppConst.baseurl+AppConst.photoUrl,method: .get,parameters: parameters).validate().responseDecodable(of: [HomeImage].self) { (response) in
            guard let data = response.value else {
                isPageRefreshing = false
                return
            }
            withAnimation {
                newPhotos.append(contentsOf: data)
                isPageRefreshing = false
                pageNumber = pageNumber + 1
            }
        }
    }
}

struct HomeScreen_Previews: PreviewProvider {
    static var previews: some View {
        HomeScreen()
    }
}
Screen.Recording.2022-05-09.at.5.02.30.PM.mp4

Initial number of columns incorrect when in landscape

Summary
When the initial device orientation is landscape, the number of columns displayed is incorrect. The correct number of columns is displayed only after rotating to portrait and landscape again.

Expected
Screen Shot 2019-11-20 at 12 31 22 PM

Actual
Screen Shot 2019-11-20 at 12 31 08 PM

Env
Xcode 11.2, iOS 13.2, Swift 5

passing array of URLs to image grid

Hi, your WaterfallGrid seems very nice and could fit in may App. However I wonder if you could giving me some pointers or direct help on how I can adapt your image grid example so that I can pass an array of URLs (URLs of jpg's in my Apps document directory) instead of using Assets.xcassets?
Regards,
Claes

Grid missing inside scrollview

Hi, thanks for this library.

I want to ask you something,
When I put WaterfallGrid inside scrollview, the grid just disappears.
How I can fix that?

var body: some View {
        GeometryReader { geometry in
            ScrollView(.vertical) {
                Text("Hello")
                WaterfallGrid((0..<10), id: \.self) { index in
                  Image("swift_logo")
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                }
                .gridStyle(
                  columnsInPortrait: 2,
                  columnsInLandscape: 3,
                  spacing: 8,
                  padding: EdgeInsets(top: 16, leading: 8, bottom: 16, trailing: 8),
                  animation: .easeInOut(duration: 0.5)
                )
                .scrollOptions(
                  direction: .horizontal,
                  showsIndicators: true
                )
                Text("Hello")
            }
        }
    }

Screen Shot 2020-11-28 at 02 04 04

How to use multiple grid at the same screen

              Group {
                       WaterfallGrid(viewModel.categories) { category in
                          CategoryItem(category: category)
                       }
                       .gridStyle(columns: 3)
                    
                      WaterfallGrid(viewModel.products) { product in
                           ProductCell(product: product)
                      }
                      .gridStyle(columns: 2)
                   }

When I use 2 difference grid in same page , Layout will have two difference scroll.

What I need is only one scroll per screen.

thanks

The size of the picture is not displayed properly in the waterfall flow

var coverRow: some View {
        VStack {
            if selectedTask.taskCover != nil {
                Image(uiImage: selectedTask.tTaskCover)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .cornerRadius(CGFloat.bl_4.double)
                    .blendMode(colorScheme == .dark ? .screen : .normal)
                    .opacity(colorScheme == .dark ? 0.75 : 0.85)
            } else {
                Button(action: {
                    isShowingImagePicker = true
                }, label: {
                    RoundedRectangle(cornerRadius: CGFloat.bl_4.double)
                        .fill(Color.s_c.opacity(0.35))
                        .frame(height: 180)
                        .overlay(Image(systemName: "photo").modifier(SK_20(textColor: Color.t_t_c, weight: .regular)))
                })
            }
        }
    }

IMG_D754DABDA12D-1

[tvOS] can't scroll to see all screen

Hello,

I run it on simulator and I don't know if it's a bug but you can't scroll to see all screen on AppleTV, I think it's because images are not focusable..

Capture d’écran 2019-11-13 à 09 51 13

HELP WANTED - How show section in your WaterfallGrid?

Come debbo modificare il codice sotto, per visualizzare le sezioni?

ForEach(0..<3, id: \.self) { index in
                Section {
                    Text("Sezione N. \(index)")
                    WaterfallGrid(self.thumbnails) { thumb in
                        ThumbnailView(thumb: thumb)
                            .onTapGesture {
                                let index = self.thumbnails.firstIndex { thumbnails in
                                    thumbnails.id == thumb.id
                                }
                                self.thumbnails[index!].isSelected.toggle()
                        }
                    }
                }
            }

Tieni presente che se utilizzo il codice sotto:

WaterfallGrid(thumbnails) { thumb in
                ThumbnailView(thumb: thumb)
                    .onTapGesture {
                        let index = self.thumbnails.firstIndex { thumbnails in
                            thumbnails.id == thumb.id
                        }
                        self.thumbnails[index!].isSelected.toggle()
                }
            }

funziona perfettamente, come puoi vedere nello screenshot sotto.
Schermata 2020-04-13 alle 18 05 39

bug

Screen Shot 2020-02-13 at 17 00 04

precondition failure: invalid input index: 2

Performance problem

i see your code

return ScrollView(style.scrollDirection) {
            ZStack(alignment: .topLeading) {
                ForEach(data, id: self.dataId) { element in
                    self.content(element)
                        .frame(width: self.style.scrollDirection == .vertical ? columnWidth : nil,
                               height: self.style.scrollDirection == .horizontal ? columnWidth : nil)
                        .background(PreferenceSetter(id: element[keyPath: self.dataId]))
                        .alignmentGuide(.top, computeValue: { _ in self.alignmentGuides[element[keyPath: self.dataId]]?.y ?? 0 })
                        .alignmentGuide(.leading, computeValue: { _ in self.alignmentGuides[element[keyPath: self.dataId]]?.x ?? 0 })
                        .opacity(self.alignmentGuides[element[keyPath: self.dataId]] != nil ? 1 : 0)
                }
            }
            .padding(style.padding)
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .animation(self.loaded ? self.style.animation : nil)
        }

i think your ForEach can change use List
because when image count > 300 pic, use List can Recycle reuse

What do you think ??

Position Issue

I have created this view, and I noticed when I clicked on the rectangle which have more than 1 item in it, it will go into navigationLink View and then when I back to this main View, the first rectangle goes to the bottom. I have made sure that this is not my code issue. Can you help me?

截屏2020-03-17下午9 00 20

ThankYou very much.

Use Kingfisher on the waterfall grid

Hi, I was making an app and I am using Kingfisher, it is to use Url instead of images, the Url becomes an image after being published. I was using the Waterfall Grid but it won't let me use the Kingfisher. How can I do it?

iOS 14

Not show in NavigationView
Not support lazyload

Item sizes are all the same in Column / Horizontal Layout

Bug Report
The "waterfall" behavior doesn't work when using the column / horizontal layout option. If you have a number of items with varying sizes and apply the .scrollOptions(direction: .horizontal) modifier, the items take up a defined amount of height and do not "waterfall" into one another.

I believe this has to do with how the sizes of items are calculated; the calculations aren't correct for the horizontal layout because they may still be prioritizing the same factors used to calculate the vertical waterfall behavior.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.