一:簡介
在有支付相關(guān)的APP中冒冬,都有對應(yīng)的錢包,雖然現(xiàn)在的支付寶撬码,微信支付很流行,但是都是需要綁定自己的銀行卡版保,那么這個銀行卡的卡包頁面該怎么實(shí)現(xiàn)呢呜笑?在網(wǎng)上找了許久也沒有找到合適的,那就索性自己造輪子彻犁。
為了實(shí)現(xiàn)相應(yīng)的功能叫胁,仿照支付寶的銀行卡卡包開發(fā)出相應(yīng)的頁面,頁面長這個樣子:
下面詳細(xì)說明頁面是如何實(shí)現(xiàn)的汞幢,功能簡單實(shí)用驼鹅,如有需求請繼續(xù)閱讀,如不需要勿噴請飄過森篷。
二:說明目錄
創(chuàng)建錢包視圖容器WalletView
初始化WalletView并加載錢包頭部視圖walletHeader
在錢包視圖中重新加載卡片視圖
在錢包視圖中實(shí)現(xiàn)添加卡片方法
在錢包視圖中實(shí)現(xiàn)卡片展示和隱藏回調(diào)方法
創(chuàng)建卡片視圖ColoredCardView繼承于CardView
在CardView中實(shí)現(xiàn)點(diǎn)擊手勢展示隱藏卡片
導(dǎo)入項(xiàng)目使用介紹
三:具體實(shí)現(xiàn)
1. 創(chuàng)建錢包視圖容器WalletView
創(chuàng)建繼承UIView的WalletView視圖输钩, 通過調(diào)用contentInset方法來控制top、left仲智、bottom买乃、right四個方向的邊距,代碼如下:
public var contentInset: UIEdgeInsets {
set {
scrollView.contentInset = newValue
calculateLayoutValues()
}
get {
return scrollView.contentInset
}
}
創(chuàng)建walletHeader方法钓辆,用來加載錢包的頭部視圖剪验,代碼如下:
@IBOutlet public weak var walletHeader: UIView? {
willSet {
if let walletHeader = newValue {
scrollView.addSubview(walletHeader)
}
}
didSet {
oldValue?.removeFromSuperview()
calculateLayoutValues()
}
}
2. 初始化WalletView并加載錢包頭部視圖walletHeader
在需要加載錢包的地方初始化WalletView,并自定義頭部視圖walletHeader和卡片視圖前联,Demo 中以ViewController頁面為例功戚,代碼如下:
walletView = WalletView(frame: CGRect(x: 10, y: 0, width: screenw - 20, height: screenh - 20))
self.view.addSubview(walletView)
walletView.walletHeader = walletHeaderView
walletView.useHeaderDistanceForStackedCards = true
walletView.contentInset = UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 0)
3. 在錢包視圖中重新加載卡片視圖
在錢包視圖中重新加載卡片視圖,在這里為了靈活修改方便使用蛀恩,頁面布局可以自定義疫铜,Demo中模仿支付寶頁面進(jìn)行設(shè)計(jì),在CardView視圖中双谆,主要實(shí)現(xiàn)頁面的交互等功能壳咕,具體的UI實(shí)現(xiàn)在ColoredCardView中實(shí)現(xiàn)并繼承于CardView席揽,下面會詳細(xì)說明,重新加載卡片視圖方法源碼如下:
open func reload(cardViews: [CardView]) {
insert(cardViews: cardViews)
calculateLayoutValues()
}
func insert(cardViews: [CardView]) {
self.insertedCardViews = cardViews
if insertedCardViews.count == 1 {
presentedCardView = insertedCardViews.first
}
}
public var insertedCardViews = [CardView]() {
didSet {
calculateLayoutValues(shouldLayoutWalletView: false)
}
}
在ViewController中調(diào)用reload方法代碼如下:
walletView.reload(cardViews: coloredCardViews)
4. 在錢包視圖中實(shí)現(xiàn)添加卡片方法
在展示頁面中我們可以看到谓厘,在頁面的左上角有一個添加按鈕幌羞,這個按鈕的UI布局在頭部視圖中實(shí)現(xiàn),具體的功能是竟稳,添加一個卡片属桦,具體的實(shí)現(xiàn)方法如下:
open func insert(cardView: CardView, animated: Bool = false, presented: Bool = false, completion: InsertionCompletion? = nil) {
presentedCardView = presented ? cardView : self.presentedCardView
if animated {
let y = scrollView.convert(CGPoint(x: 0, y: frame.maxY), from: self).y
cardView.frame = CGRect(x: 0, y: y, width: frame.width, height: cardViewHeight)
cardView.layoutIfNeeded()
scrollView.insertSubview(cardView, at: 0)
UIView.animateKeyframes(withDuration: WalletView.insertionAnimationSpeed, delay: 0, options: [.beginFromCurrentState, .calculationModeCubic], animations: { [weak self] in
UIView.addKeyframe(withRelativeStartTime: 0.0, relativeDuration: 1.0, animations: {
self?.insert(cardViews: [cardView] + (self?.insertedCardViews ?? []))
self?.layoutWalletView(placeVisibleCardViews: false)
})
}, completion: { [weak self] (_) in
self?.reload(cardViews: self?.insertedCardViews ?? [])
completion?()
})
} else {
reload(cardViews: [cardView] + insertedCardViews)
placeVisibleCardViews()
completion?()
}
}
在ViewController中按鈕的觸發(fā)事件addCardButtonClick方法中調(diào)用insert方法代碼如下:
@objc func addCardButtonClick(addCardButton:UIButton) {
walletView.insert(cardView: ColoredCardView(), animated: true, presented: true)
}
5. 在錢包視圖中實(shí)現(xiàn)卡片展示和隱藏回調(diào)方法
在錢包視圖中實(shí)現(xiàn)卡片展示和隱藏回調(diào)方法,在展示狀態(tài)下他爸,需要隱藏掉添加卡片按鈕聂宾,禁止繼續(xù)添加卡片,并且顯示卡片詳細(xì)設(shè)置內(nèi)容和刪除按鈕诊笤。在隱藏狀態(tài)下系谐,需要恢復(fù)添加卡片按鈕,并且隱藏卡片詳細(xì)設(shè)置內(nèi)容和刪除按鈕讨跟,核心源碼如下:
public var didPresentCardViewBlock: PresentedCardViewDidUpdateBlock?
public var presentedCardView: CardView? {
didSet {
oldValue?.presented = false
presentedCardView?.presented = true
didPresentCardViewBlock?(presentedCardView)
}
}
在ViewController中實(shí)現(xiàn)回調(diào)功能纪他,代碼如下:
walletView.didPresentCardViewBlock = { [weak self] (_) in
self?.showAddCardViewButtonIfNeeded()
}
6. 創(chuàng)建卡片視圖ColoredCardView繼承于CardView
創(chuàng)建卡片視圖ColoredCardView繼承于CardView,這個視圖主要實(shí)現(xiàn)UI界面以及加載內(nèi)容晾匠,定義界面屬性代碼如下:
class ColoredCardView: CardView, UITableViewDataSource, UITableViewDelegate {
// 銀行l(wèi)ogo
@objc var cardLogo: UIImageView!
// 開戶行名稱
@objc var cardName: UILabel!
// 卡片類型
@objc var cardAddress: UILabel!
// 銀行卡號
@objc var cardNumber: UILabel!
// 設(shè)置列表
@objc var cardTableView: UITableView!
// 卡片視圖
@objc var bankCardView: UIView!
// 刪除按鈕
@objc var removeCardViewButton: UIButton!
override init(frame: CGRect) {
super.init(frame: frame)
setupSubViews()
}
}
7. 在CardView中實(shí)現(xiàn)點(diǎn)擊手勢展示隱藏卡片
在Demo中實(shí)現(xiàn)在CardView中點(diǎn)擊除了刪除按鈕外任何位置茶袒,都可以觸發(fā)隱藏卡片的功能,這里是在CardView中添加了手勢來實(shí)現(xiàn)該功能凉馆,代碼如下:
public let tapGestureRecognizer = UITapGestureRecognizer()
public let panGestureRecognizer = UIPanGestureRecognizer()
public let longGestureRecognizer = UILongPressGestureRecognizer()
// MARK: Private methods
func setupGestures() {
tapGestureRecognizer.addTarget(self, action: #selector(CardView.tapped))
tapGestureRecognizer.delegate = self
addGestureRecognizer(tapGestureRecognizer)
panGestureRecognizer.addTarget(self, action: #selector(CardView.panned(gestureRecognizer:)))
panGestureRecognizer.delegate = self
addGestureRecognizer(panGestureRecognizer)
longGestureRecognizer.addTarget(self, action: #selector(CardView.longPressed(gestureRecognizer:)))
longGestureRecognizer.delegate = self
addGestureRecognizer(longGestureRecognizer)
}
8. 導(dǎo)入項(xiàng)目使用介紹
最后介紹一下該如何在項(xiàng)目中導(dǎo)入該功能薪寓,下載Demo,將Demo中的FBYBankCard.framework文件和ColoredCardView.swift文件導(dǎo)入項(xiàng)目中,在需要加載的頁面中直接引用即可:
import FBYBankCard
class ViewController: UIViewController {
@objc var walletView: WalletView!
override func viewDidLoad() {
super.viewDidLoad()
}
}