Library collection view basic function

This commit is contained in:
Chris Li 2017-01-23 17:08:00 -05:00
parent ddfde941ea
commit 1a72bd0d14
7 changed files with 283 additions and 13 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 479 B

View File

@ -10,7 +10,7 @@
},
{
"idiom" : "universal",
"filename" : "more-2.png",
"filename" : "rsz_1more-2.png",
"scale" : "3x"
}
],

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -39,7 +39,7 @@ class BookmarkCollectionController: CoreDataCollectionBaseController, UICollecti
func configureItemWidth(collectionViewWidth: CGFloat) {
let itemsPerRow = ((collectionViewWidth - 10) / 320).rounded()
self.itemWidth = floor((collectionViewWidth - (itemsPerRow + 1) * 10) / itemsPerRow)
itemWidth = floor((collectionViewWidth - (itemsPerRow + 1) * 10) / itemsPerRow)
}
// MARK: - UI Control

View File

@ -8,14 +8,159 @@
import UIKit
import CoreData
import ProcedureKit
import DZNEmptyDataSet
class LibraryBooksController: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
class LibraryBooksController: CoreDataCollectionBaseController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, LibraryCollectionCellDelegate {
private(set) var itemWidth: CGFloat = 0.0
@IBAction func dismissButtonTapped(_ sender: UIBarButtonItem) {
dismiss(animated: true, completion: nil)
}
func configureItemWidth(collectionViewWidth: CGFloat) {
let itemsPerRow = (collectionViewWidth / 320).rounded()
itemWidth = (collectionViewWidth - 1 * (itemsPerRow - 1)) / itemsPerRow
}
override func viewDidLoad() {
super.viewDidLoad()
configureRefreshControl()
if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
layout.minimumInteritemSpacing = 1
layout.minimumLineSpacing = 1
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
refreshAutomatically()
collectionView.collectionViewLayout.invalidateLayout()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
configureItemWidth(collectionViewWidth: collectionView.frame.width)
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
configureItemWidth(collectionViewWidth: collectionView.frame.width)
collectionView.collectionViewLayout.invalidateLayout()
}
// MARK: - Refresh
private(set) var isRefreshing = false // used to control text on empty table view
private func configureRefreshControl() {
collectionView.refreshControl = RefreshLibControl()
collectionView.refreshControl?.addTarget(self, action: #selector(refresh), for: .valueChanged)
}
func refreshAutomatically() {
guard let date = Preference.libraryLastRefreshTime else { refresh(); return }
guard date.timeIntervalSinceNow < -86400 else {return}
refresh()
}
func refresh() {
let operation = RefreshLibraryOperation()
operation.add(observer: WillExecuteObserver { (operation) in
OperationQueue.main.addOperation({
// Configure empty table data set, so it shows "Refreshing..."
self.isRefreshing = true
self.collectionView.reloadEmptyDataSet()
})
})
operation.add(observer: DidFinishObserver { (operation, errors) in
guard let operation = operation as? RefreshLibraryOperation else {return}
OperationQueue.main.addOperation({
defer {
self.collectionView.refreshControl?.endRefreshing()
self.isRefreshing = false
self.collectionView.reloadEmptyDataSet()
}
if let _ = errors.first {
// handle error [network, xmlparse]
} else {
if operation.firstTime {
//self.showLanguageFilterAlert()
//self.configureNavBarButtons()
} else {
// self.showRefreshSuccessMessage()
}
}
})
})
GlobalQueue.shared.add(operation: operation)
}
// MARK: - UICollectionView Data Source
func numberOfSections(in collectionView: UICollectionView) -> Int {
return fetchedResultController.sections?.count ?? 0
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return fetchedResultController.sections?[section].numberOfObjects ?? 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! LibraryCollectionCell
let book = fetchedResultController.object(at: indexPath)
cell.delegate = self
cell.imageView.image = UIImage(data: book.favIcon ?? Data())
cell.titleLabel.text = book.title
cell.subtitleLabel.text = [
book.dateDescription,
book.fileSizeDescription,
book.articleCountDescription
].flatMap({$0}).joined(separator: " ")
cell.descriptionLabel.text = book.desc
cell.hasPicLabel.isHidden = book.hasPic
return cell
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "Header", for: indexPath) as! LibraryCollectionHeader
header.textLabel.text = fetchedResultController.sections?[indexPath.section].name
return header
}
// MARK: - UICollectionViewDelegateFlowLayout
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: itemWidth, height: 66)
}
// MARK: - LibraryCollectionCellDelegate
func didTapMoreButton(cell: LibraryCollectionCell) {
guard let indexPath = collectionView.indexPath(for: cell) else {return}
print("\(indexPath) tapped")
}
// MARK: - NSFetchedResultsController
let managedObjectContext = AppDelegate.persistentContainer.viewContext
lazy var fetchedResultController: NSFetchedResultsController<Book> = {
let fetchRequest = Book.fetchRequest()
let langDescriptor = NSSortDescriptor(key: "language.name", ascending: true)
let titleDescriptor = NSSortDescriptor(key: "title", ascending: true)
fetchRequest.sortDescriptors = [langDescriptor, titleDescriptor]
fetchRequest.predicate = NSPredicate(format: "language.name != nil")
//// fetchRequest.predicate = self.onlineCompoundPredicate
let controller = NSFetchedResultsController(fetchRequest: fetchRequest,
managedObjectContext: self.managedObjectContext,
sectionNameKeyPath: "language.name", cacheName: nil)
controller.delegate = self
try? controller.performFetch()
return controller as! NSFetchedResultsController<Book>
}()
}

View File

@ -6,6 +6,7 @@
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
@ -44,22 +45,118 @@
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="10" minimumInteritemSpacing="10" id="FMe-0w-Xez">
<size key="itemSize" width="50" height="50"/>
<size key="itemSize" width="320" height="66"/>
<size key="headerReferenceSize" width="0.0" height="0.0"/>
<size key="footerReferenceSize" width="0.0" height="0.0"/>
<size key="footerReferenceSize" width="50" height="22"/>
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
</collectionViewFlowLayout>
<cells>
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="Aea-Om-Uku">
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="Cell" id="Aea-Om-Uku" customClass="LibraryCollectionCell" customModule="Kiwix" customModuleProvider="target">
<rect key="frame" x="28" y="0.0" width="320" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
<rect key="frame" x="0.0" y="0.0" width="320" height="66"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Wbk-Lp-yTb">
<rect key="frame" x="8" y="8" width="50" height="50"/>
<constraints>
<constraint firstAttribute="width" constant="50" id="Lfz-Bj-qPh"/>
<constraint firstAttribute="height" constant="50" id="Xc4-8W-tr6"/>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="q2k-12-zti">
<rect key="frame" x="66" y="8" width="42" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="rmy-yO-cBy">
<rect key="frame" x="66" y="29" width="31" height="14.5"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="wmd-Qv-2ia">
<rect key="frame" x="66" y="43.5" width="31" height="14.5"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Pic" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="aKZ-e6-Ikq">
<rect key="frame" x="117" y="9.5" width="26" height="16"/>
<constraints>
<constraint firstAttribute="height" constant="16" id="58f-me-IXF"/>
<constraint firstAttribute="width" constant="26" id="FBn-H0-tNj"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="12"/>
<color key="textColor" red="1" green="0.50196081400000003" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="nTw-d7-YqD">
<rect key="frame" x="270" y="10" width="42" height="46"/>
<constraints>
<constraint firstAttribute="width" constant="42" id="lBA-pd-Pa2"/>
<constraint firstAttribute="height" constant="46" id="qqN-B2-nid"/>
</constraints>
<state key="normal" image="Dots"/>
<connections>
<action selector="moreButtonTapped:" destination="Aea-Om-Uku" eventType="touchUpInside" id="Cxh-DD-Tyi"/>
</connections>
</button>
</subviews>
</view>
<color key="backgroundColor" red="1" green="0.50196081400000003" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<constraints>
<constraint firstItem="Wbk-Lp-yTb" firstAttribute="centerY" secondItem="Aea-Om-Uku" secondAttribute="centerY" id="3Lj-sz-46B"/>
<constraint firstAttribute="trailingMargin" secondItem="nTw-d7-YqD" secondAttribute="trailing" id="5JR-74-PhA"/>
<constraint firstItem="wmd-Qv-2ia" firstAttribute="leading" secondItem="Wbk-Lp-yTb" secondAttribute="trailing" constant="8" id="6DI-9y-Igu"/>
<constraint firstItem="aKZ-e6-Ikq" firstAttribute="leading" secondItem="q2k-12-zti" secondAttribute="trailing" constant="9" id="Bvy-Bq-O5f"/>
<constraint firstItem="aKZ-e6-Ikq" firstAttribute="centerY" secondItem="q2k-12-zti" secondAttribute="centerY" constant="-1" id="LIs-SX-crF"/>
<constraint firstItem="wmd-Qv-2ia" firstAttribute="top" secondItem="rmy-yO-cBy" secondAttribute="bottom" id="MEV-c5-uqZ"/>
<constraint firstItem="rmy-yO-cBy" firstAttribute="leading" secondItem="Wbk-Lp-yTb" secondAttribute="trailing" constant="8" id="Mn8-60-6ii"/>
<constraint firstItem="nTw-d7-YqD" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="rmy-yO-cBy" secondAttribute="trailing" id="TOj-hZ-bSG"/>
<constraint firstItem="nTw-d7-YqD" firstAttribute="centerY" secondItem="Aea-Om-Uku" secondAttribute="centerY" id="VLl-VW-z7E"/>
<constraint firstItem="q2k-12-zti" firstAttribute="leading" secondItem="Wbk-Lp-yTb" secondAttribute="trailing" constant="8" id="g7u-6E-fy5"/>
<constraint firstAttribute="leadingMargin" secondItem="Wbk-Lp-yTb" secondAttribute="leading" id="hkU-Yw-gmi"/>
<constraint firstItem="nTw-d7-YqD" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="aKZ-e6-Ikq" secondAttribute="trailing" id="pmb-V3-HIM"/>
<constraint firstAttribute="topMargin" secondItem="q2k-12-zti" secondAttribute="top" id="qG1-In-0ae"/>
<constraint firstItem="nTw-d7-YqD" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="wmd-Qv-2ia" secondAttribute="trailing" id="qRe-Xm-jjX"/>
<constraint firstItem="rmy-yO-cBy" firstAttribute="top" secondItem="q2k-12-zti" secondAttribute="bottom" id="tUM-uu-aX5"/>
</constraints>
<connections>
<outlet property="descriptionLabel" destination="wmd-Qv-2ia" id="SYF-xK-ewN"/>
<outlet property="hasPicLabel" destination="aKZ-e6-Ikq" id="ZgS-qb-zdm"/>
<outlet property="imageView" destination="Wbk-Lp-yTb" id="QZJ-hP-zJr"/>
<outlet property="subtitleLabel" destination="rmy-yO-cBy" id="sx5-Ij-QaQ"/>
<outlet property="titleLabel" destination="q2k-12-zti" id="LU3-St-SwQ"/>
</connections>
</collectionViewCell>
</cells>
<collectionReusableView key="sectionFooterView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="Header" id="Vew-wk-bdN" customClass="LibraryCollectionHeader" customModule="Kiwix" customModuleProvider="target">
<rect key="frame" x="0.0" y="66" width="375" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uBe-10-mcY">
<rect key="frame" x="28" y="3" width="36" height="17"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
<constraints>
<constraint firstItem="uBe-10-mcY" firstAttribute="centerY" secondItem="Vew-wk-bdN" secondAttribute="centerY" id="bOA-89-aKD"/>
<constraint firstItem="uBe-10-mcY" firstAttribute="leading" secondItem="Vew-wk-bdN" secondAttribute="leadingMargin" constant="20" id="iWL-kS-Hu6"/>
</constraints>
<connections>
<outlet property="textLabel" destination="uBe-10-mcY" id="pab-il-9r3"/>
</connections>
</collectionReusableView>
<connections>
<outlet property="dataSource" destination="cDq-va-k4I" id="C1Z-rn-cDB"/>
<outlet property="delegate" destination="cDq-va-k4I" id="O4e-0Y-jYL"/>
</connections>
</collectionView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
@ -144,5 +241,6 @@
</scenes>
<resources>
<image name="Cross" width="16" height="16"/>
<image name="Dots" width="16" height="16"/>
</resources>
</document>

View File

@ -101,8 +101,6 @@ class ArticleSnippetCell: ArticleCell {
@IBOutlet weak var snippetLabel: UILabel!
}
// MARK: - Bookmark Cell
class BookmarkCollectionCell: UICollectionViewCell {
override func awakeFromNib() {
clipsToBounds = false
@ -144,6 +142,35 @@ class BookmarkCollectionCell: UICollectionViewCell {
}
}
class LibraryCollectionCell: UICollectionViewCell {
override func awakeFromNib() {
imageView.clipsToBounds = true
imageView.layer.cornerRadius = 2.0
hasPicLabel.layer.borderWidth = 1.5
hasPicLabel.layer.borderColor = UIColor.orange.cgColor
hasPicLabel.layer.cornerRadius = 8.0
}
@IBAction func moreButtonTapped(_ sender: UIButton) {
delegate?.didTapMoreButton(cell: self)
}
weak var delegate: LibraryCollectionCellDelegate?
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var subtitleLabel: UILabel!
@IBOutlet weak var descriptionLabel: UILabel!
@IBOutlet weak var hasPicLabel: UILabel!
}
protocol LibraryCollectionCellDelegate: class {
func didTapMoreButton(cell: LibraryCollectionCell)
}
class LibraryCollectionHeader: UICollectionReusableView {
@IBOutlet weak var textLabel: UILabel!
}