q-mobile / qgrid Goto Github PK
View Code? Open in Web Editor NEWπ QGrid: The missing SwiftUI collection view.
License: MIT License
π QGrid: The missing SwiftUI collection view.
License: MIT License
Tried to bring QGrid into a SwiftUI project via package manager , Xcode 11.4.1, received a very vague error: "QGrid could not be resolved" "An unknown error occurred"
Hi @karolkulesza,
Amazing stuff mate, been waiting for this since SwiftUI was introduced! : )
Im trying to make a simple grid without data (static cells), but got the error bellow. Any idea what is wrong?
I am using:
Xcode 11 Beta 5
Catalina Beta 5
`// GridView.swift
import QGrid
import SwiftUI
struct GridView: View {
var body: some View {
QGrid(columns: 4, { ProductCell() }
}
}
#if DEBUG
struct GridView_Previews : PreviewProvider {
static var previews: some View {
GridView()
}
}
#endif`
I try to add this to my project but it's falied ,The Xcode show me
Showing All Messages
: The repository could not be found. Make sure a valid repository exists at the specified location and try again.
I don't know why
In every grid I place, in the canvas preview, it takes up the whole screen of the device. Is there a way to limit this so that the height of the whole view is restricted to the items in the grid? i.e. to remove unnecessary white space
When using the GeometryReader inside of a cell, the grid is not rendered as expected. The cells are overlapping as shown in the image below.
struct DataPoint: Identifiable{
var id = UUID()
var name:String
}
struct ContentView: View {
var data:Array<DataPoint> = [DataPoint(name: "A"), DataPoint(name: "B"), DataPoint(name: "C"), DataPoint(name: "D"), DataPoint(name: "E"), DataPoint(name: "F"), DataPoint(name: "G"), DataPoint(name: "H"), DataPoint(name: "J"), DataPoint(name: "K"), DataPoint(name: "L"), DataPoint(name: "M")]
var body: some View {
QGrid(data,
columns: 3,
columnsInLandscape: 4,
vSpacing: 0,
hSpacing: 0,
vPadding: 0,
hPadding: 0,
content: {data in
GeometryReader{g in
VStack{
Text(data.name)
}.frame(width:g.size.width, height: g.size.width).background(Color.yellow)
}
})
}
}
Any suggestions how to make sure that every cell is squared, independent from the screen size?
I cannot find a way to add a header view to the QGrid like a header section for UITableView
Is there a way to return different cells based on row and/or column?
Testing this in the simulator and every cell is generated on launch, not as you scroll (like SwiftUI List).
Or have I misunderstood something?
When NavigationLink is embedded like this:
CollectionView(self.Containers.containers, columns: 3) { container in
NavigationLink(destination: ContainerDetailView(container: container)) {
ContainerCell(container: container)
.environmentObject(self.Containers)
.accentColor(.primary)
}
}
tapping on it sometimes doesn't open NavigationLink
destination. onTapGesture
works always though.
There is also another issue: when NavigationLink
destination is open, NavigationLink
destination from navigationBarItems
opens and closes instantly after opening.
I am trying to use QGrid on my iOS 10+ app with no luck.
Compiling for iOS 10.0, but module 'QGrid' has a minimum deployment target of iOS 13.0
I would like to import it and use it conditionally just like import SwiftUI
does. Any ideas?
Thank you
Is it possible to add the functionality to have cells with different heights in collection? Something like pinterestLayout? https://github.com/MagicLab-team/PinterestLayout
I noticed that the QGrid only works well when not contained in a NavigationView.
It seems to not correctly respect the safe area and cuts off part of the UI that seem to have the hight of the navigation bar.
Here are some examples of what I mean:
As you can see part of the UI underneath the navigation bar is cut out.
Also the lower part of the grid is cut out due to the home indicator.
NavigationView {
QGrid(profiles, columns: 2) { profile in
ProfileCardView(profile: profile)
}
}
If I add the .edgesIgnoringSafeArea([.all])
to the grid, this is what happens:
NavigationView {
QGrid(profiles, columns: 2) { profile in
ProfileCardView(profile: profile)
}
.edgesIgnoringSafeArea(.all)
}
Do you have any examples of how to use navigation when clicking on a cell in the QGrid?
MacOS build does not scroll works fine for IOS
struct GridCell: View {
var person: Person
var body: some View {
NavigationLink(
destination: Text("")
) {
VStack() {
Image(person.imageName)
.resizable()
.scaledToFit()
.clipShape(Circle())
.shadow(color: .primary, radius: 5)
.padding([.top, .leading, .trailing], 7)
Text(person.firstName).lineLimit(1)
Text(person.lastName).lineLimit(1)
}
.font(.headline).foregroundColor(.white)
}
}
}
If I put Qgrid in the section, how to detect the height of each row so that Qgrid will be shown properly.
I have the QGrid
setup to render a list of objects that are converted to views inside the QGrid
βs block.
When my API fetches updated data the view is rebuilt.
I confirmed that the QGrid
is called again, yet, it keeps rendering the initial list of views and not the newly created views.
If I switch to List
it works properly. Only with QGrid
it doesnβt refresh.
Here is the code in question:
var body: some View { self.makeView()
.onReceive(timer) { _ in
self.refreshView()
}
}
private func makeView() -> some View {
VStack {
Text("Dashboard").font(.largeTitle)
if self.circuits.count > 0 {
// need to use an if, b/c showing scrollable view without content will not refresh later on
QGrid<[CircuitInfo], CircuitCell>(self.circuits, columns: 2, columnsInLandscape: 4, vSpacing: 10, vPadding: 10, isScrollable: true) { circuit in
CircuitCell(circuit: circuit)
}
}
Spacer()
HStack {
Text("\(self.circuitsCount())").font(.footnote).padding(5)
Spacer()
Text("Updated: \(lastUpdated)").font(.footnote).padding(5)
}
}
}
Any ideas as to what I might be doing wrong?
This library looks awesome, but probably not going to use it without cocoapods support. For me, it's probably not worth using two dependency managers in the same project (especially with SPM being such a new technology).
I totally understand if you don't want to support multiple dependency managers, but if you did, you'd probably get more traction, usage, and PRs.
Hi,
Is it possible to add paging functionality when sliding. Thanks.
Andy
If you embed QGrid in a List or Form then it doesn't appear. It is created but in the wrong coordinate space (I think),
I like QGrid, it is a very elegant solution like collection view.
I am looking for a SwiftUI component like LazyGrid (https://stackoverflow.com/questions/62606907/swiftui-using-ondrag-and-ondrop-to-reorder-items-within-one-single-lazygrid), but needs to be forward compatible with iOS 13.x or macOS 10.15.x.
Does QGrid have this feature please?
ContentView.swift
as follows:
import SwiftUI
import QGrid
struct Item: Identifiable {
let id = UUID()
}
struct ContentView: View {
let array = Array(repeating: Item(), count: 15)
var body: some View {
QGrid(array, columns: 3) { value in
Image("") // empty image is being used for simplicity. Using real image doesn't prevent the crash
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
The app window resized.
The app crashed with the following log:
2020-03-25 13:26:59.993525+0800 qgrid test[40447:1852701] *** Assertion failure in -[_TtC7SwiftUIP33_A874FC5B9DB530D4375C25AE2AA39DF215HostingClipView setBoundsOrigin:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/AppKit/AppKit-1894.30.142/AppKit.subproj/NSView.m:5645
2020-03-25 13:26:59.994618+0800 qgrid test[40447:1852701] [General] Invalid parameter not satisfying: !isnan(newOrigin.x)
2020-03-25 13:26:59.998896+0800 qgrid test[40447:1852701] [General] (
0 CoreFoundation 0x00007fff2c4f48ab __exceptionPreprocess + 250
1 libobjc.A.dylib 0x00007fff627ae805 objc_exception_throw + 48
2 CoreFoundation 0x00007fff2c51dd10 +[NSException raise:format:arguments:] + 88
3 Foundation 0x00007fff2ec16241 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 191
4 AppKit 0x00007fff296bc20f -[NSView setBoundsOrigin:] + 621
5 AppKit 0x00007fff296bbf80 -[NSClipView setBoundsOrigin:] + 42
6 SwiftUI 0x00007fff39950033 $s7SwiftUI15HostingClipView33_A874FC5B9DB530D4375C25AE2AA39DF2LLC12setFrameSizeyySo6CGSizeVF + 547
7 SwiftUI 0x00007fff39950720 $s7SwiftUI15HostingClipView33_A874FC5B9DB530D4375C25AE2AA39DF2LLC12setFrameSizeyySo6CGSizeVFTo + 48
8 AppKit 0x00007fff29687ca2 -[NSView setFrame:] + 423
9 AppKit 0x00007fff296e45f0 -[NSScrollView _setContentViewFrame:] + 328
10 AppKit 0x00007fff296e3f34 -[NSScrollView _applyContentAreaLayout:] + 1054
11 AppKit 0x00007fff296e125e -[NSScrollView tile] + 773
12 AppKit 0x00007fff296e0f3c -[NSScrollView _tileWithoutRecursing] + 35
13 AppKit 0x00007fff2977ae5b -[NSScrollView _update] + 27
14 AppKit 0x00007fff29675cf6 -[NSView setFrameSize:] + 1714
15 AppKit 0x00007fff2977abb4 -[NSScrollView setFrameSize:] + 242
16 AppKit 0x00007fff29687ca2 -[NSView setFrame:] + 423
17 SwiftUI 0x00007fff397f29b3 $s7SwiftUI16PlatformViewHostC012updateHostedD6BoundsyyF + 195
18 SwiftUI 0x00007fff397f7245 $s7SwiftUI16PlatformViewHostC6layoutyyFTo + 21
19 AppKit 0x00007fff2969d100 _NSViewLayout + 600
20 AppKit 0x00007fff2969cba3 -[NSView _layoutSubtreeWithOldSize:] + 388
21 AppKit 0x00007fff2969ccfd -[NSView _layoutSubtreeWithOldSize:] + 734
22 AppKit 0x00007fff2969ccfd -[NSView _layoutSubtreeWithOldSize:] + 734
23 AppKit 0x00007fff2969bfd2 -[NSView _layoutSubtreeIfNeededAndAllowTemporaryEngine:] + 1137
24 AppKit 0x00007fff2969ba6e -[NSWindow(NSConstraintBasedLayout) _layoutViewTree] + 148
25 AppKit 0x00007fff29698434 -[NSWindow _oldPlaceWindow:fromServer:] + 805
26 AppKit 0x00007fff296966dd -[NSWindow _setFrameCommon:display:fromServer:] + 1352
27 AppKit 0x00007fff29a1ef8a -[NSWindow(NSWindowResizing) _resizeWithEvent:] + 2664
28 AppKit 0x00007fff298f76a6 -[NSTitledFrame attemptResizeWithEvent:] + 177
29 AppKit 0x00007fff298f7387 -[NSThemeFrame handleMouseDown:] + 294
30 AppKit 0x00007fff29992004 -[NSThemeFrame mouseDown:] + 30
31 AppKit 0x00007fff29879b0d -[NSWindow(NSEventRouting) _handleMouseDownEvent:isDelayedEvent:] + 4907
32 AppKit 0x00007fff297e3c5c -[NSWindow(NSEventRouting) _reallySendEvent:isDelayedEvent:] + 2612
33 AppKit 0x00007fff297e3005 -[NSWindow(NSEventRouting) sendEvent:] + 349
34 AppKit 0x00007fff297e137c -[NSApplication(NSEvent) sendEvent:] + 352
35 AppKit 0x00007fff2962d0cf -[NSApplication run] + 707
36 AppKit 0x00007fff295ff465 NSApplicationMain + 777
37 qgrid test 0x000000010000535d main + 13
38 libdyld.dylib 0x00007fff63b1c7fd start + 1
39 ??? 0x0000000000000003 0x0 + 3
)
2020-03-25 13:27:00.018820+0800 qgrid test[40447:1852701] It's not legal to call -layoutSubtreeIfNeeded on a view which is already being laid out. If you are implementing the view's -layout method, you can call -[super layout] instead. Break on void _NSDetectedLayoutRecursion(void) to debug. This will be logged only once. This may break in the future.
Upon adding the Swift Package, I get the compile time error Use of unresolved identifier 'UIDevice'
even when not using the package yet.
The line throwing the error is
private var cols: Int {
UIDevice.current.orientation.isLandscape ? columnsInLandscape : columns
}
in QGrid.swift.
Target is macOS Catalina.
If you embed the ZStack in a List as in the following:
var body: some View {
GeometryReader { geometry in
List {
ZStack {
self.backgroundGradient
.edgesIgnoringSafeArea(.all)
VStack {
if (QConstants.showDesigner) { self.designerView(geometry) }
self.gridView(geometry)
}
}
}
}
}
Then you get this in the simulator:
I have tried various experiments and the best I can come up with is to add a frame modifier as in:
var body: some View {
GeometryReader { geometry in
List {
ZStack {
self.backgroundGradient
.edgesIgnoringSafeArea(.all)
VStack {
if (QConstants.showDesigner) { self.designerView(geometry) }
self.gridView(geometry)
.frame(width: geometry.size.width,
height: geometry.size.height)
}
}
}
}
}
But this is still wrong because the grid is in the wrong place (see screenshot) and I can't work out how to fix it. Any ideas?
I have a 1 x 8 grid in portrait mode and 2x4 grid in landscape mode.
I have a button in each view in the grid that toggles using @State
I set button 1 and 2 on (it change color to green).
I rotate the simulator to landscape mode. columns are displayed correctly (2 x 4 grid).
but now, buttons 1 and 3 show the green button.
Looks like there's some recycling going on? Each gridview has the state internally.
Hello,
I am wondering if is there any solution for navigating to different items inside the QGrid.
When clicking in an item it processes all the items click actions and navigates to all the links one after the other.
QGrid(self.dashboardViewModel.dashboardItems, columns: 2, isScrollable: false, showScrollIndicators: false) { dashboardItem in
NavigationLink(destination: PlayerProfileView(playerLocalId: dashboardItem.actionId)) {
DashboardItem(dashboardItemVE: dashboardItem)
}.buttonStyle(PlainButtonStyle())
}
I have a use case where I need to have a parent scroll view with some other content and then I have a QGrid view that scrolls by itself
How do I handle this case as the scrolling is not intuitive
I would like to know if I could do something to resolve this
VStack{
ScrollView(.vertical , showsIndicators: false){
// VStack(alignment: .leading, spacing: 10) {
BannerView()
CategoryRow().environmentObject(self.latestViewModel)
ColorRow().environmentObject(self.latestViewModel)
}
if(latestViewModel.error.isEmpty){
QGrid(latestViewModel.wallpapers,columns: self.columns, vSpacing : 20.0, hSpacing: 5.0,
hPadding: 10.0, endReached: {
//print("End Reached")
self.latestViewModel.getMoreWallpapers()
}){wallpaper in
self.getLatestTabItem(wallpaper: wallpaper)
}
Just a code snippet to demonstrate what I exactly want to do
Can this Data.Element : Identifiable
remove from
public struct QGrid<Data, Content> : View where Data : RandomAccessCollection, Content : View, Data.Element : Identifiable
to support Core Data NSManagedObjects
When you scroll there is a layout issue at the top of the screen. The GIF below compares expected and actual behaviour.
App keeps crashing if I try to override the darkmode colorscheme for views where I use QGrid
The wrong number of columns are displayed, when opening the app directly in landscape. The initial device orientation is not detected.
In QGrid.swift:
UIDevice.current.orientation.isLandscape ? columnsInLandscape : columns
Hello! Here is an example where I expect the grid appears after button tap, but I got empty grid
struct ContentView: View {
@ObservedObject var viewModel = ContentViewModel()
var body: some View {
VStack {
Button("Get all values") {
self.viewModel.tap()
}
Text(String(self.viewModel.models.count))
QGrid(self.viewModel.models, columns: 3) {
GridCell(value: $0)
}
}
}
}
class ContentViewModel: ObservableObject {
@Published var models: [String] = [ ]
func tap() {
self.models = ["1", "2", "3"]
}
}
extension String: Identifiable {
public var id: String {
return self
}
}
struct GridCell: View {
var value: String
var body: some View {
Text(self.value)
}
}
However it works correctly if models value has at least one initial element. Can you explain what should I do in this case? Or is it a bug?
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.