soysaucelab / collectionkit Goto Github PK
View Code? Open in Web Editor NEWReimagining UICollectionView
License: MIT License
Reimagining UICollectionView
License: MIT License
Hello! Thanks for the wonderful framework! I looked at the demo project and read the documentation, but I did not find the mention of "section" headers anywhere. I understand that on providers they replace sections (and do much more), but is it possible to do "section" header out of the box? Thank you.
Maybe the class like ArrayDataProvider should use ContiguousArray instead of Array. When
Element type is a class or @objc protocoll, it would be more predictable performance.
The examples in the README refer to dataSource.layout
which should now be provider.layout
I think.
Managed to crash ComposedHeaderProvider tapHandler on line (ComposedHeaderProvider #135) let context = TapContext(view: view as! HeaderView, index: at, section: sections[at])
Index out of range.
Attached example project below. Crash happens if you try tap Title 4 or above.
CollectionCrash.zip
Have I done something wrong or possibly a bug?
Thanks
Hi, I've cloned this commit and there're some build errors due to swiftlint.
Sources/Layout/SimpleLayout.swift:12:3: error: Identifier Name Violation: Variable name should only contain alphanumeric characters: '_contentSize' (identifier_name)
/Sources/Addon/SpaceCollectionProvider.swift:20:3: error: Identifier Name Violation: Variable name should only contain alphanumeric characters: '_contentSize' (identifier_name)
Wobbling animation is extensively used in apps, at least more than the scale animation, although WobbleAnimator can be added by dragging code from the example, it makes sense to add this animator to the framework, since there are only 2 animators available as of yet.
Thanks for a good library!
I wanted to ask how best to add Search Bar?
I downloaded entire project and copied Examples folder to new project. then I setup pod and run the project but got 11 errors. Tried to do by some quick suggestions but still not working.
Hello!
Let's imagine we have ComposedProvider:
collectionView.provider = ComposedProvider(sections: [firstProvider, secondProvider])
The issue is when we've updated dataSource in firstProvider, like:
firstProviderDataSource.data = [newData]
viewUpdater and sizeSource are called for secondProvider too.
So everytime when we update data in some dataSource, all other providers will recalculate their sizeSource..
Is it right behavior?
Thanks!
I have a view that consists of a label for a title, a label for a subtitle and a textfield. Since I don't know of the lenght of title + subtitle, it is possible for them to have multiple lines.
This is the view:
`
import Foundation
import UIKit
class GenericSingleLineInputView: GenericView<String> {
var viewModel: GenericSingleLineInputViewModel?
private let title: UILabel = {
let title = UILabel()
title.font = Config.Font.text
title.textColor = Config.Color.text
title.backgroundColor = UIColor.red
title.numberOfLines = 0
return title
}()
private let subtitle: UILabel = {
let title = UILabel()
title.font = Config.Font.smallText
title.textColor = Config.Color.text
title.backgroundColor = UIColor.yellow
title.numberOfLines = 0
return title
}()
private let textfield: UITextField = {
let textfield = UITextField()
textfield.addTarget(self, action: #selector(inputValueChanged), for: .valueChanged)
textfield.backgroundColor = UIColor.blue
return textfield
}()
override func didLoad() {
addSubview(title)
addSubview(subtitle)
addSubview(textfield)
self.backgroundColor = UIColor.green
title.snp.makeConstraints { (make) in
make.top.equalTo(self).offset(12)
make.left.equalTo(self)
make.right.equalTo(self)
make.bottom.equalTo(subtitle.snp.top)
}
subtitle.snp.makeConstraints { (make) in
make.left.equalTo(self)
make.right.equalTo(self)
make.bottom.equalTo(textfield.snp.top)
}
textfield.snp.makeConstraints { (make) in
make.height.equalTo(30)
make.left.equalTo(self)
make.right.equalTo(self)
make.bottom.equalTo(self).offset(-12)
}
}
@objc func inputValueChanged() {
if let text = textfield.text {
viewModel?.valueChanged(text)
}
}
func setup(with viewModel: GenericSingleLineInputViewModel) {
self.viewModel = viewModel
title.text = viewModel.title
subtitle.text = viewModel.subtitle
textfield.text = viewModel.value
}
}
`
Now I know to implement the sizeProvider property to set the size. I've tried it that way:
`
let provider1 = CollectionProvider(dataProvider: CreateBudgetAddBudgetDataProvider(), viewProvider: CreateBudgetAddBudgetProvider())
provider1.sizeProvider = {index, viewModel, size in
let view = provider1.view(at: index)
log.debug(view.sizeThatFits(CGSize(width: size.width, height: CGFloat.greatestFiniteMagnitude)))
return CGSize(width: size.width, height: 100)
}
collectionView.provider = CollectionComposer(
provider1
)
`
However, this does not work, since
let view = provider1.view(at: index) log.debug(view.sizeThatFits(CGSize(width: size.width, height: CGFloat.greatestFiniteMagnitude)))
will always return zero.
And this are the provider classes:
`
class CreateBudgetAddBudgetProvider: CollectionViewProvider<BudgetViewModel, UIView> {
override func update(view: UIView, data: BudgetViewModel, index: Int) {
if let view = view as? GenericSingleLineInputView, let viewModel = data as? GenericSingleLineInputViewModel {
view.setup(with: viewModel)
}
}
override func view(data: BudgetViewModel, index: Int) -> UIView {
let view: UIView
if data is GenericSingleLineInputViewModel {
view = reuseManager.dequeue(GenericSingleLineInputView())
}
else {
view = UIView()
}
update(view: view, data: data, index: index)
return view
}
}
class CreateBudgetAddBudgetDataProvider: CollectionDataProvider {
var data: [BudgetViewModel] = []
override init() {
super.init()
data.append(GenericSingleLineInputViewModel(title: "Name",valueChanged: { (value) in
}, subtitle: "Hier könne Ihr name stehen"))
}
override var numberOfItems: Int {
get {
return data.count
}
}
override func data(at: Int) -> BudgetViewModel {
return data[at]
}
}
`
edit: I'm sorry for the code formatting, can't get it to work 😅
In the example if you scroll horizontal gallery to left or right and scroll the whole view to down, and back scroll to top again the horizontal gallery back to zero offset.
ArticleExampleViewController
, AnimatorExampleViewController
and others do the same!
Is there a way for the scroll views (horizontal & vertical) in the HorizontalGalleryViewController
to keep their scroll position?
Hello!
Don't understand why, but in your example when cell is adding or removing we can see the animation properly, but in my project removing the latest cell, even if I call removeFirst() :
collectionView.provider = BasicProvider(
dataSource: dataSource,
viewSource: ClosureViewSource(viewGenerator: { (data, index) -> UILabel in
let cell = UILabel()
cell.text = data.name
cell.backgroundColor = .yellow
return cell
}, viewUpdater: { (view: UILabel, data: Match, at: Int) in
view.text = data.name
}),
sizeSource: sizeSource,
layout: FlowLayout(lineSpacing: 10,justifyContent: .center),
animator: WobbleAnimator(),
tapHandler: { [weak self] context in
self?.dataSource.data.remove(at: context.index)
}
)
Video:
http://dropmefiles.com/KrXuP
Thank you for a wonderful library!
I was wondering what is the best way to add a refresh control at the top of CollectionView?
@lkzhao Hello!
I have ComposedProvider with 3 providers(1 provider = 1 cells) with RowLayout have size == view.frame.width. I have only 3 cells and want they be displayed always, so I use this code:
let visibleFrameInsets = UIEdgeInsets(top: 0, left: -view.frame.width * 5, bottom: 0, right: -view.frame.width * 5)
matchProvider = ComposedProvider(layout: RowLayout().insetVisibleFrame(by: visibleFrameInsets),
sections: [infoProvider])
.....
matchProvider.sections.append(videoProvider)
matchProvider.sections.append(webViewProvider)
Those providers don't have their own layout.
But only 2 cells are initialized and Third isn't. Although I multiplied view.frame.width by 5 and visibleFrameInsets is right (-1875 left and right).
What's wrong? Seems it should work. But there is no changes between -view.frame.width
and -view.frame.width * 5
.
Is there an example of how to achieve the 3D cascading animator shown in the readme? It looks like exactly what I need!
I just use the example of readme but I've got this error "Cannot convert value of type 'ArrayDataSource' to expected argument type 'DataSource<_>'" on line 17.
class CategoriesViewController: UIViewController {
let collectionView = CollectionView()
let dataSource = ArrayDataSource(data: ["1","2", "3", "4"])
let viewSource = ClosureViewSource { (view: RoundedCardWrapperView, data: String, index: Int) in
view.cardView.titleLabel.text = data
view.cardView.subtitleLabel.text = nil
view.cardView.imageView.image = UIImage(named: data)
}
let sizeSource = { (index: Int, data: Int, collectionSize: CGSize) -> CGSize in
return CGSize(width: collectionSize.width, height: collectionSize.width + 20)
}
override func viewDidLoad() {
super.viewDidLoad()
let provider = BasicProvider(
dataSource: dataSource,
viewSource: viewSource,
sizeSource: sizeSource
)
//lastly assign this provider to the collectionView to display the content
collectionView.provider = provider
}
}
Hello!
I've tried to create dummyCells and showing it, for example, first 5 sec and then clear collectionView and show real cells. But when I set new data some cells didn't remove from collectionView even I set empty array to dataSource:
var dummyModels: [Model] = []
for _ in 0..<20 {
let model = Model(object: [:])
dummyModels.append(model)
}
dataSource.data = dummyModels
and after sometime call:
dataSource.data = matches
And on the screen I can see 2 empty cells and bellow them real cells:
http://joxi.ru/D2P6pJspD1XQr3
http://joxi.ru/xAe8abupz6aY2y
If I call
dataSource.data.removeAll()
On the screen I can see 2 cells. I've debugged and dataSource.data.count == 0.
Hi,
quick questions:
Thanks
build in Xcode9, pod-version:1.3.1, it has errors
scroll to bottom, and keep scroll with scrollview bounce, the table shake when finger scroll to the margin of two item view
Carthage:
...
This usually indicates that project itself failed to compile. Please check the xcodebuild log for more details:
...
SpaceProvider.swift:14:10: error: Identifier Name Violation: Enum element name should only contain alphanumeric characters: 'absolute(_:)' (identifier_name)
SimpleViewProvider.swift:16:10: error: Identifier Name Violation: Enum element name should only contain alphanumeric characters: 'absolute(_:)' (identifier_name)
How can I solve this?
Thanks for the wonderful framework!
How could I add any selection style?
It seems to have no interaction style for select or tap.
Even when I used a UIButton in my viewsource, it has no state change style interaction.
How could I use it to enable the default button click interaction style?
How could I make a background color or shadow change when I click the cell or any style change when I click a UIControl?
let deviceProvider = BasicProvider(
dataSource: ArrayDataSource(data: deviceEntities),
...
)
where deviceEntities is a list of some CoreData entities. When I do this, the compiler said Cannot convert value of type '[CoreDataDevice]' to expected argument type '[_]'.
Does it only support String and Int type?
I am using Realm for my local db.
Any way to use Realm's Results for dataSource?
Not to change Results list to a swift Array.
I did not find any mention of "drag and drop" support. Any thoughts or best practices how to implement it with CollectionKit?
Hello!
When user scroll every cell are creating again. My cells creating from xib, so it too expensive to create every cells again when scroll.
Is there any built-in layout or something else, so my cells will reuse, not create again?
Thanks!
Hi . First great work with CollectionKit . I Love it but I have huge performance issues with it. And noticed some strange things.
There are no prefetch and no preload of views(cells) . running simple print() debug I can see that the views are created just as they become visible . That can't be right . That creates huge performance issues when scrolling . I need to be able to draw the view graphics before it enters the visibleframe.
Looking at for example Texture by Facebook https://github.com/texturegroup/texture .. they preload not only one but 2-3 cells/views/nodes before becoming visible in order to get 60 fps scroll
There are no control of how many view I would like to preload / prefetch
I really really like this kit but I can't use it because of this ... and I really would not like to rewrite all of my code ...
Hi. It's really a nice framework.
I got some problems when I wrap UICollectionView/UITableView into a SimpleViewProvider.
import UIKit
class TableTestVC: UITableViewController {
let data = [1, 2, 3, 4, 5, 6, 7]
override func viewDidLoad() {
super.viewDidLoad()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.data.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "celllll")
cell.textLabel?.text = "\(self.data[indexPath.row])"
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
NSLog("Select TableViewCell")
}
}
import UIKit
import CollectionKit
open class ControllerViewProvider: SimpleViewProvider {
public var contentView: UIView {
return view(at: 0)
}
private var contentVC: UIViewController?
public init(identifier: String? = nil, controllerType: UIViewController.Type, height: CGFloat, insets: UIEdgeInsets = .zero) {
contentVC = controllerType.init()
let content = contentVC!.view!
super.init(identifier: identifier, views: [content], sizeStrategy: (.fill, .absolute(height)), layout: insets == .zero ? FlowLayout() : FlowLayout().inset(by: insets))
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.provider = ComposedProvider(sections: [
space(64),
LabelProvider(text: "Label 1234567", font: .systemFont(ofSize: 20)),
space(20),
ButtonProvider(identifier: "HIBUTTON", text: "Button Test", font: .systemFont(ofSize: 24), color: .blue, insets: UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)),
space(20),
ControllerViewProvider(identifier: "Kuangren", controllerType: TableTestVC.self, height: 180.0, insets: .zero),
space(20)
])
}
tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
can not be trigged when I tap the table row.
And when I have a long long long long press on the table row, it will reach the delegate methods tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
.
It may stupid to use any UIScrollView in CollectionView, but I want to reuse some pods for UICollectionView or UITableView, such as FSPagerView.
Is it not recommended to wrap any UIScrollView into SimpleViewProvider?
Or am I using it in a wrong way?
Thanks.
hello,
Is there a way to get custom view from a xib?
thanks a lot
For example, I want to make a collection view of buttons. Just wondering what the best way to go about this is with this library.
Example target link binary with libraryYetAnotherAnimationLibrary.framework
, which is not existed in the project.
I set provider's layout with this code:
provider.layout = WaterfallLayout<UIImage>(columns: 2, spacing: 0.0)
I set columns = 2, then I provide imagesize
`func imageSizeProvider(at: Int, data: UIImage, collectionSize: CGSize) -> CGSize {
if at == 0 {
return CGSize(width: collectionSize.width, height: 150)
}
else if at == 1 {
return CGSize(width: collectionSize.width/2, height: 150)
}
else {
return CGSize(width: collectionSize.width/2, height: 150)
}
}`
I want get this layout display ,
I find this waterfalllayout, must demand equal width through set column = 2?
My question is, what's wrong I use, or has a better solution for this?
Thanks.
Hi,
is there a way to detect when an item is selected?
Like in collectionView didSelectItemAtIndexPath etc.?
Greetings
After building with carthage and linking framework, module still invisible in storyboard.
Am I doing smth. wrong?
let examples: [(String, UIViewController.Type)] = [
("Horizontal Gallery", HorizontalGalleryViewController.self),
("Grid", GridViewController.self),
("Articles", ArticleExampleViewController.self),
("Reload", ReloadDataViewController.self),
("Reload Animation", ReloadAnimationViewController.self),
("Header", HeaderExampleViewController.self),
("Chat", MessagesViewController.self),
("Animators", AnimatorExampleViewController.self)
]
override func viewDidLoad() {
super.viewDidLoad()
let examplesSection = BasicProvider(
dataSource: ArrayDataSource(data: examples),
viewSource: ClosureViewSource(viewUpdater: {
(view: ExampleView, data: (String, UIViewController.Type), at: Int) in
view.populate(title: data.0, contentViewControllerType: data.1)
}),
sizeSource: { (index, data, size) -> CGSize in
// I want to control the height of each item here. If the data changes, it will change here by collectionView reloadData.
},
layout: FlowLayout(lineSpacing: 30).inset(by: bodyInset)
)
provider = ComposedProvider(sections: [
space(100),
LabelProvider(text: "CollectionKit", font: .boldSystemFont(ofSize: 38), insets: headerInset),
LabelProvider(text: "A modern swift framework for building reusable collection view components.", font: .systemFont(ofSize: 20), insets: bodyInset),
space(30),
LabelProvider(text: "Examples", font: .boldSystemFont(ofSize: 30), insets: headerInset),
examplesSection,
space(30)
])
}
extensions and methods in Utils.swift
should be marked as public so you don't have to repeat in demo project.
'In the latest version of iOS toolchain, this utility func is no longer needed, because the same function was added to the standard library. If you try to automatically convert to the latest swift version, then UIEdgeInsetsInsetRect converts to 'inset(by insets:' and this leads to infinite recursive func.
i just quickly create full workaround, using "Non-trivial Podfile in Artsy/Eigen" as a base. If some one needs, just append this code in your Podfile
require 'fileutils'
def edit_pod_file(file, old_code, new_code)
code = File.read(file)
if code.include?(old_code)
FileUtils.chmod("+w", file)
File.write(file, code.sub(old_code, new_code))
end
end
post_install do |installer|
stringToRemove = 'func inset(by insets: UIEdgeInsets) -> CGRect {\n' +
' return UIEdgeInsetsInsetRect(self, insets)\n' + '}\n'
edit_pod_file("Pods/CollectionKit/Sources/Extensions/Util.swift", stringToRemove, '')
end
I test WaterfallLayout and WobblePresenter. With transposed() option, scroll work well but when remove transposed(), scroll at top and bottom not good (bounce of scrollView).
I attached my code. Please check for me, whether i do something wrong or not. Thanks
My Examples.zip
Hello,
So I'm pretty much new to swift and still learning a few things.
Tried to use the CollectionKit framework because it looked really nice.
I have an issue though, not too sure why, but I suppose I'm doing something wrong?
Trying to have a nice CollectionKit with UIButton so I mostly took back the code from the example and tweaked it to behave the way I want. The problem is that the UIViews are weirdly positioned.
Would any of you have any idea on the why?
Here is my code:
func sizeProvider(at: Int, data: UIButton, collectionSize: CGSize) -> CGSize {
var size = data.frame.size
if size.width > collectionSize.width {
size.height /= size.width / collectionSize.width
size.width = collectionSize.width
}
if size.height > collectionSize.height {
size.width /= size.height / collectionSize.height
size.height = collectionSize.height
}
return size
}
class GenericCollectionView {
class func createForButton(frame: CGRect, buttons: [UIButton]) -> CollectionView {
let collectionView = CollectionView(frame: frame)
collectionView.contentInset = UIEdgeInsetsMake(10, 10, 10, 10)
let provider = CollectionProvider(
data: buttons,
viewUpdater: { (view: UIView, data: UIButton, index: Int) in
view.addSubview(data)
})
let visibleFrameInsets = UIEdgeInsets(top: 0, left: -100, bottom: 0, right: -100)
provider.layout = WaterfallLayout<UIButton>(columns: 2).transposed().insetVisibleFrame(by: visibleFrameInsets)
provider.sizeProvider = sizeProvider
collectionView.provider = provider
return collectionView
}
}
collectionView is screen's height / 2 and placed in the centre.
And here is what it looks like, the views are like off-centred:
Oh and on a sidenote the buttons are not clickable.
Is the SizeProvider called for every data object in the Data Provider when the Collection View Size is changing? I have around 1300 items in my data and when using the Large Navigationbars the scrolling is seriously stuttering.
I checked what the source of the stuttering might be and I found that the sizeProvider of every cell is called every time when the size of the collectionView changes. That might be the culprit.
Can you please explain in steps how to run the project using cocoapods or with direct download ?
1.I download the project zip and open it
2.opened CollectionKit.xcodeproj
3.build "CollectionKit"
4. now what ?
I'm objective-c developer and will be nice to run the samples in simple step.
Thanks.
Hello!
First of all thanks for this great lib!
I have a dataSource:
let dataSource = ArrayDataSource(data: self.presenter.matches) / / [Match]
My data is updating every x seconds and I need to update my collection view with the new data. I'm doing like this:
func display(_ matches: [Match]) {
dataSource.data = matches
}
matches.count is about 100.
So seems it's not good way to do like this, because when display method is calling, scrolling begins to lag.
So how can I update my dataSource then?
Thanks!
In a realistic case where the collection requires many different data/object types, how to implement this ?
For example a settings page may require TextAndSwitchView, TextAndSliderView, LongTextView and so on..
if there was something like...
provider.viewClassForData = { dataObj in
return dataObj.viewClass
}
In the current state of CollectionKit, SizeSource
is defined as a function/closure that takes (Int, Data, CGSize)
and returns CGSize
. It is simple to use but it presents some problems.
public typealias SizeSource<Data> = (Int, Data, CGSize) -> CGSize
While writing a SizeSource inside BasicProvider's initializer, it is easy to forget the what are the parameters and what is order of these parameter.
DataSource, ViewSource, and Layout are class based, while sizeSource is not. there is a inconsistency.
Hard for function based SizeSource to store value. We might want a size source that can cache sizes for each data.
Hard to have CollectionKit provide built-in SizeProvider.
With function type, built-in SizeSource will be lying around as some function like imageSizeSource
.
We cannot provide parameters to these built-in SizeSource. and they will be hard to find, and hard to document as well.
Would love to have something like ImageSizeSource(contentMode: .aspectFit)
or AutoLayoutSizeSource(dummyView: MyCell())
included in the repo.
SimpleViewProvider
currently implements its own sizing strategy which is pretty bad. It is another system that developer have to learn. It is easy to write but it doesn't have the flexibility of SizeSource. The tuple also has the problem of not displaying the parameter name when it is used.SimpleViewProvider
support SizeSource
but at the same time, provide some built-in SizeSource so that developers don't have to write a closure every time they use it. Best of both world!Therefore, here I propose that we change SizeSource
into a abstract base class of some sort.
class SizeSource<Data> {
// override point for subclass
func size(index: Int, data: Data, collectionSize: CGSize) -> CGSize {}
}
We will also provide a ClosureSizeSource
similar to ClosureViewSource
.
We will also implement some default SizeSource.
class ImageSizeSource: SizeSource<UIImage> {
// ...
}
// provide a dummy cell that use autolayout to calculate size for each cell
class AutoLayoutSizeSource: SizeSource<Data> {
// ...
}
// cache sizes for each cell based on their identifier
class CacheSizeSource<Data>: SizeSource<Data> {
// ..
}
SimpleViewSizeSource(widthStrategy: ViewSizeStrategy, heightStrategy: ViewSizeStrategy)
With this change, we can also change SimpleViewProvider
to use SizeSource
.
I'm trying to update the HorizontalGalleryViewController in your examples, like ReloadDataViewController.
However, the view is not updating the new image.
I'm using the code below.
//
// HorizontalGalleryViewController.swift
// CollectionKitExample
//
// Created by Luke Zhao on 2016-06-14.
// Copyright © 2016 lkzhao. All rights reserved.
//
import UIKit
import CollectionKit
func imageSizeProvider(at: Int, data: UIImage, collectionSize: CGSize) -> CGSize {
var imageSize = data.size
if imageSize.width > collectionSize.width {
imageSize.height /= imageSize.width/collectionSize.width
imageSize.width = collectionSize.width
}
if imageSize.height > collectionSize.height {
imageSize.width /= imageSize.height/collectionSize.height
imageSize.height = collectionSize.height
}
return imageSize
}
class HorizontalGalleryViewController: CollectionViewController {
let addButton02: UIButton = {
let button = UIButton()
button.setTitle("+", for: .normal)
button.titleLabel?.font = .boldSystemFont(ofSize: 20)
button.backgroundColor = UIColor(hue: 0.6, saturation: 0.68, brightness: 0.98, alpha: 1)
button.layer.shadowColor = UIColor.black.cgColor
button.layer.shadowOffset = CGSize(width: 0, height: -12)
button.layer.shadowRadius = 10
button.layer.shadowOpacity = 0.1
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
addButton02.addTarget(self, action: #selector(add02), for: .touchUpInside)
view.addSubview(addButton02)
collectionView.contentInset = UIEdgeInsetsMake(10, 10, 10, 10)
let provider = CollectionProvider(data: testImages, viewGenerator: { (data, index) -> UIImageView in
let view = UIImageView()
view.layer.cornerRadius = 5
view.clipsToBounds = true
return view
}, viewUpdater: { (view: UIImageView, data: UIImage, at: Int) in
view.image = data
})
provider.layout = WaterfallLayout(columns: 2).transposed()
provider.sizeProvider = imageSizeProvider
provider.presenter = WobblePresenter()
self.provider = provider
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let viewWidth = view.bounds.width
let viewHeight = view.bounds.height
addButton02.frame = CGRect(x: 0, y: viewHeight - 44, width: viewWidth, height: 44)
collectionView.frame = CGRect(x: 0, y: 0, width: viewWidth, height: viewHeight - 44)
}
@objc func add02() {
let test = UIImage(named: "6")!
testImages.append(test)
collectionView.reloadData()
print(testImages)
}
}
Hey, great library!
I know tvOS isn't officially supported (I just made a PR to add it to Carthage and Cocoapods #54), but it would be nice to get it fully working.
At the moment if you make a view focusable, you can scroll through the collection. But if you scroll off screen, the scroll view jumps back to top of the scrollview. This is maybe because the focus engine tries to automatically scroll to the focused view which may be reused and now in a different place?
In addition to this it would be great to have a focusHandler
similar to the tapHandler
Hello guys, this framework seems to be cool. I have a few questions.
let headers: [String?] = [
nil, nil, "推荐视频", "热门直播", "推荐音频", "热门图文"
]
let headerComposedProvider = ComposedHeaderProvider(
identifier: nil,
layout: FlowLayout().inset(by: UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 8)),
headerViewSource: ClosureViewSource(
viewUpdater: { (view: UIButton, data, index) in
view.backgroundColor = UIColor.white
if index < headers.count {
if let x = headers[index] {
view.setTitle(x, for: .normal)
view.setTitleColor(UIColor.darkGray, for: .normal)
view.contentHorizontalAlignment = .left
}
}
}),
headerSizeSource: { (index, data, size) -> CGSize in
if index < headers.count {
if let _ = headers[index] {
return CGSize(width: size.width, height: 40)
}
}
return CGSize.zero
},
sections: sections)
headerComposedProvider.isSticky = false
self.provider = headerComposedProvider
The layout: FlowLayout().inset(by: UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 8))
is for header?
I set this layout, but it affects the sections' layout.
And any way to pass dataSource to header?
BTW: justifyContent, alignItems, alignContent in Layout, any documents?
Thanks.
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.