mirror of
https://github.com/material-components/material-components-ios.git
synced 2026-02-20 08:27:32 +08:00
249 lines
7.3 KiB
Swift
249 lines
7.3 KiB
Swift
// Copyright 2019-present the Material Components for iOS authors. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
import UIKit
|
|
import MaterialComponents.MaterialCards_Theming
|
|
import MaterialComponents.MaterialColorScheme
|
|
import MaterialComponents.MaterialContainerScheme
|
|
import MaterialComponents.MaterialTypographyScheme
|
|
|
|
class CardCellsWithRippleExample: UIViewController,
|
|
UICollectionViewDelegate,
|
|
UICollectionViewDataSource,
|
|
UICollectionViewDelegateFlowLayout
|
|
{
|
|
|
|
enum ToggleMode: Int {
|
|
case edit = 1
|
|
case reorder
|
|
}
|
|
|
|
let collectionView = UICollectionView(
|
|
frame: .zero,
|
|
collectionViewLayout: UICollectionViewFlowLayout())
|
|
var toggle = ToggleMode.edit
|
|
|
|
@objc var containerScheme: MDCContainerScheming
|
|
|
|
@objc var colorScheme: MDCColorScheming {
|
|
return containerScheme.colorScheme
|
|
}
|
|
|
|
@objc var typographyScheme: MDCTypographyScheming {
|
|
return containerScheme.typographyScheme
|
|
}
|
|
|
|
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
|
|
containerScheme = MDCContainerScheme()
|
|
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
|
|
}
|
|
|
|
required init?(coder aDecoder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
|
|
collectionView.frame = view.bounds
|
|
collectionView.dataSource = self
|
|
collectionView.delegate = self
|
|
collectionView.backgroundColor = colorScheme.backgroundColor
|
|
collectionView.alwaysBounceVertical = true
|
|
collectionView.register(MDCCardCollectionCell.self, forCellWithReuseIdentifier: "Cell")
|
|
collectionView.translatesAutoresizingMaskIntoConstraints = false
|
|
collectionView.allowsMultipleSelection = true
|
|
view.addSubview(collectionView)
|
|
|
|
navigationItem.rightBarButtonItem = UIBarButtonItem(
|
|
title: "Reorder",
|
|
style: .plain,
|
|
target: self,
|
|
action: #selector(toggleModes))
|
|
|
|
let longPressGesture = UILongPressGestureRecognizer(
|
|
target: self,
|
|
action: #selector(reorderCards(gesture:)))
|
|
longPressGesture.cancelsTouchesInView = false
|
|
collectionView.addGestureRecognizer(longPressGesture)
|
|
|
|
let guide = view.safeAreaLayoutGuide
|
|
NSLayoutConstraint.activate([
|
|
collectionView.leftAnchor.constraint(equalTo: guide.leftAnchor),
|
|
collectionView.rightAnchor.constraint(equalTo: guide.rightAnchor),
|
|
collectionView.topAnchor.constraint(equalTo: view.topAnchor),
|
|
collectionView.bottomAnchor.constraint(equalTo: guide.bottomAnchor),
|
|
])
|
|
collectionView.contentInsetAdjustmentBehavior = .always
|
|
|
|
self.updateTitle()
|
|
}
|
|
|
|
func preiOS11Constraints() {
|
|
self.view.addConstraints(
|
|
NSLayoutConstraint.constraints(
|
|
withVisualFormat: "H:|[view]|",
|
|
options: [],
|
|
metrics: nil,
|
|
views: ["view": collectionView]))
|
|
self.view.addConstraints(
|
|
NSLayoutConstraint.constraints(
|
|
withVisualFormat: "V:|[view]|",
|
|
options: [],
|
|
metrics: nil,
|
|
views: ["view": collectionView]))
|
|
}
|
|
|
|
func updateTitle() {
|
|
switch toggle {
|
|
case .edit:
|
|
navigationItem.rightBarButtonItem?.title = "Reorder"
|
|
self.title = "Cards (Edit)"
|
|
case .reorder:
|
|
navigationItem.rightBarButtonItem?.title = "Edit"
|
|
self.title = "Cards (Reorder)"
|
|
}
|
|
}
|
|
|
|
@objc func toggleModes() {
|
|
switch toggle {
|
|
case .edit:
|
|
toggle = .reorder
|
|
case .reorder:
|
|
toggle = .edit
|
|
}
|
|
self.updateTitle()
|
|
collectionView.reloadData()
|
|
}
|
|
|
|
func collectionView(
|
|
_ collectionView: UICollectionView,
|
|
cellForItemAt indexPath: IndexPath
|
|
) -> UICollectionViewCell {
|
|
|
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
|
|
guard let cardCell = cell as? MDCCardCollectionCell else { return cell }
|
|
cardCell.enableRippleBehavior = true
|
|
cardCell.applyTheme(withScheme: containerScheme)
|
|
cardCell.isSelectable = (toggle == .edit)
|
|
cardCell.isAccessibilityElement = true
|
|
cardCell.accessibilityLabel = title
|
|
|
|
return cardCell
|
|
}
|
|
|
|
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
|
guard toggle == .edit else { return }
|
|
}
|
|
|
|
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
|
|
guard toggle == .edit else { return }
|
|
}
|
|
|
|
func numberOfSections(in collectionView: UICollectionView) -> Int {
|
|
return 1
|
|
}
|
|
|
|
func collectionView(
|
|
_ collectionView: UICollectionView,
|
|
numberOfItemsInSection section: Int
|
|
) -> Int {
|
|
return 30
|
|
}
|
|
|
|
func collectionView(
|
|
_ collectionView: UICollectionView,
|
|
layout collectionViewLayout: UICollectionViewLayout,
|
|
sizeForItemAt indexPath: IndexPath
|
|
) -> CGSize {
|
|
let cardSize = (collectionView.bounds.size.width / 3) - 12
|
|
return CGSize(width: cardSize, height: cardSize)
|
|
}
|
|
|
|
func collectionView(
|
|
_ collectionView: UICollectionView,
|
|
layout collectionViewLayout: UICollectionViewLayout,
|
|
insetForSectionAt section: Int
|
|
) -> UIEdgeInsets {
|
|
return UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
|
|
}
|
|
|
|
func collectionView(
|
|
_ collectionView: UICollectionView,
|
|
layout collectionViewLayout: UICollectionViewLayout,
|
|
minimumLineSpacingForSectionAt section: Int
|
|
) -> CGFloat {
|
|
return 8
|
|
}
|
|
|
|
func collectionView(
|
|
_ collectionView: UICollectionView,
|
|
layout collectionViewLayout: UICollectionViewLayout,
|
|
minimumInteritemSpacingForSectionAt section: Int
|
|
) -> CGFloat {
|
|
return 8
|
|
}
|
|
|
|
func collectionView(
|
|
_ collectionView: UICollectionView,
|
|
canMoveItemAt indexPath: IndexPath
|
|
) -> Bool {
|
|
return toggle == .reorder
|
|
}
|
|
|
|
func collectionView(
|
|
_ collectionView: UICollectionView,
|
|
moveItemAt sourceIndexPath: IndexPath,
|
|
to destinationIndexPath: IndexPath
|
|
) {
|
|
}
|
|
|
|
@objc func reorderCards(gesture: UILongPressGestureRecognizer) {
|
|
|
|
switch gesture.state {
|
|
case .began:
|
|
guard
|
|
let selectedIndexPath = collectionView.indexPathForItem(
|
|
at:
|
|
gesture.location(in: collectionView))
|
|
else { break }
|
|
let cell = collectionView.cellForItem(at: selectedIndexPath)
|
|
guard let cardCell = cell as? MDCCardCollectionCell else { break }
|
|
collectionView.beginInteractiveMovementForItem(at: selectedIndexPath)
|
|
if toggle == .reorder {
|
|
cardCell.isDragged = true
|
|
}
|
|
case .changed:
|
|
guard let gestureView = gesture.view else { break }
|
|
collectionView.updateInteractiveMovementTargetPosition(gesture.location(in: gestureView))
|
|
case .ended:
|
|
collectionView.endInteractiveMovement()
|
|
default:
|
|
collectionView.cancelInteractiveMovement()
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
extension CardCellsWithRippleExample {
|
|
|
|
@objc class func catalogMetadata() -> [String: Any] {
|
|
return [
|
|
"breadcrumbs": ["Ripple", "Card Cell with Ripple"],
|
|
"primaryDemo": false,
|
|
"presentable": true,
|
|
]
|
|
}
|
|
}
|