Skip to main content

一个折叠牌样式的可滑动 UI 效果实现

· 4 min read

当前正在做一个普通的商场项目, 不过 UI 设计师突发奇想设计了一个秒杀界面, 里面需要一个卡片视图, 卡片可以左右滑动, 类似折叠牌的效果. 这里正好找到一个库叫 Koloda, 可以仿照它来实现折叠牌, 顺便记录下来整个实现过程.

类似折叠牌视图​

当前的需求是实现一个类似一沓折叠牌的 UI, 可以左右滑动, 每一张牌就是一个秒杀活动的内容页. 找到 Koloda 库, 看到它的实现比较接近 UI 设计, 故仿照它来实现.

并且看到这个的关键字都是叫 Tinder 或者是 Tinder like, 记下方便搜索, 果然在谷歌上可以找到很多这样的文章.

目前的 UI 设计就是类似这篇文章所描述的效果. 普通的代码实现可以看看Github 上的这里.

先来看是否可以通过库来实现, 如果可以直接使用库, 否则就参考文章来手动实现.

使用 Koloda 库实现​

先来看利用 Koloda 库来实现的过程, 这里使用 Carthage 作为依赖管理工具(因为库中有些内容在 pod 下编译不通过, 且 pod 识别到版本是 4.4, 没有最新的).

使用 Carthage 时, 需要将里面额外携带的 pop 动画库也链接进工程.

如果要使用 Pod, 则引入的时候这样来: pod 'Koloda', '~> 4.5'.

而实际上实现也是非常简单, 引入库之后直接使用即可, 自定义视图内容可以在数据源方法 viewForCardAt 中指定:

import UIKit
import Koloda
import SnapKit

private var numberOfCards: Int = 5

class ViewController: UIViewController {

private var kolodaView: KolodaView!

private var dataSource: [String] = {
var array = [String]()
for index in 0..<numberOfCards {
array.append("Card_like_\(index + 1)")
}

return array
}()

// MARK: Lifecycle

override func viewDidLoad() {
super.viewDidLoad()

kolodaView = KolodaView()
kolodaView.dataSource = self
kolodaView.delegate = self

view.addSubview(kolodaView)
kolodaView.snp.makeConstraints {
$0.center.equalToSuperview()
$0.width.height.equalToSuperview().multipliedBy(0.6)
}
}
}

// MARK: KolodaViewDelegate

extension ViewController: KolodaViewDelegate {

func kolodaDidRunOutOfCards(_ koloda: KolodaView) {
let position = kolodaView.currentCardIndex
for i in 1...4 {
dataSource.append("Card_like_\(i)")
}
kolodaView.insertCardAtIndexRange(position..<position + 4, animated: true)
}

func koloda(_ koloda: KolodaView, didSelectCardAt index: Int) {
UIApplication.shared.openURL(URL(string: "https://yalantis.com/")!)
}

}

// MARK: KolodaViewDataSource

extension ViewController: KolodaViewDataSource {

func kolodaNumberOfCards(_ koloda: KolodaView) -> Int {
return dataSource.count
}

func kolodaSpeedThatCardShouldDrag(_ koloda: KolodaView) -> DragSpeed {
return .default
}

func koloda(_ koloda: KolodaView, viewForCardAt index: Int) -> UIView {
let cardView = UIView()
cardView.backgroundColor = UIColor.random()
return cardView
}

func koloda(_ koloda: KolodaView, viewForCardOverlayAt index: Int) -> OverlayView? {
return nil
}
}

故只需要按需实现内容视图即可, 并且是否循环也可以直接控制, 效果如下所示:

顺便给出上述随机颜色的实现代码, 方便直接验证:

extension CGFloat {
static func random() -> CGFloat {
return CGFloat(arc4random()) / CGFloat(UInt32.max)
}
}

extension UIColor {
static func random() -> UIColor {
return UIColor(red: .random(),
green: .random(),
blue: .random(),
alpha: 1.0)
}
}

代码手动实现​

需要好好看看这里面的原理, 特别是 Koloda 库以及之前说的那几篇文章(搜索一下关键字看看有没有更多优质文章), 可以学到很多东西应该, 另外可以看看这篇文章讲许多 iOS 效果实现, 这样可以对视图的实现有一个更深层次的认识.