Я смог создать UITableViewCell
, чтобы показать UIButton
адаптирующий прохождение Рэя Вендерлиха здесь .
Целью была вставка со всех сторон contentView
, где onPanLeft
он будет вытягиваться справа uiButton
с аналогичными верхними / нижними вставками.
Мне удалось этого добиться, однако у меня невероятно трудное время для решения одной проблемы:
- Если я начинаю медленно перетаскивать влево,
contentView
быстро разбрасывает влево / вправо назад и вперед.
Начальное состояние contentView с отступом 20 пунктов в начале или в конце к контейнеру UITableViewCell.
Завершение состояния ContentView с расширенной шириной (желтая линия - это то место, где должны встретиться синие / серые субвиды, голубая ширина субвидения - ИСПРАВЛЕНО)
Ниже приведен мой соответствующий код для справки:
var panStartPoint = CGPoint.zero
var startingRightLayoutConstraintConstant: CGFloat = 20
let kBounceValue: CGFloat = 20.0
func buttonTotalWidth() -> CGFloat {
return deleteButton.frame.width
}
func updateConstraintsIfNeeded(_ animated: Bool, completion: @escaping (_ finished: Bool) -> Void) {
var duration: Float = 0
if animated {
duration = 0.1
}
UIView.animate(withDuration: TimeInterval(duration), delay: 0, options: .curveEaseOut, animations: {
self.layoutIfNeeded()
}, completion: completion)
}
@objc func panThisCell(_ sender: UIPanGestureRecognizer) {
if let cell = sender.view?.superview?.superview as? PostTableViewCell {
switch sender.state {
case .began:
cell.panStartPoint = sender.translation(in: cell.myContentView)
cell.startingRightLayoutConstraintConstant = cell.contentViewRightConstraint.constant
break
case .changed:
let currentPoint: CGPoint = sender.translation(in: cell.myContentView)
let deltaX: CGFloat = currentPoint.x - cell.panStartPoint.x
var panningLeft = false
if (currentPoint.x < cell.panStartPoint.x) { panningLeft = true }
if (cell.startingRightLayoutConstraintConstant == 20) {
if (!panningLeft) {
let constant: CGFloat = max(-deltaX, 20)
if (constant == 20) {
resetConstraintContstants(cell, toZero: true, notifyDelegateDidClose: true)
} else {
cell.contentViewLeftConstraint.constant = 20 - constant
cell.contentViewRightConstraint.constant = 20 + constant
}
} else {
let constant: CGFloat = min(-deltaX, cell.buttonTotalWidth())
if (constant == cell.buttonTotalWidth()) {
setConstraintsToShowAllButtons(cell, true, notifyDelegateDidOpen: true)
} else {
cell.contentViewLeftConstraint.constant = 20 - constant
cell.contentViewRightConstraint.constant = 20 + constant
}
}
} else {
let adjustment: CGFloat = cell.startingRightLayoutConstraintConstant - deltaX
if (!panningLeft) {
let constant: CGFloat = max(adjustment, 20)
if (constant == 20) {
resetConstraintContstants(cell, toZero: true, notifyDelegateDidClose: true)
} else {
cell.contentViewLeftConstraint.constant = 20 - constant
cell.contentViewRightConstraint.constant = 20 + constant
}
} else {
let constant: CGFloat = min(adjustment, cell.buttonTotalWidth())
if (constant == cell.buttonTotalWidth()) {
setConstraintsToShowAllButtons(cell, true, notifyDelegateDidOpen: true)
} else {
cell.contentViewLeftConstraint.constant = 20 - constant
cell.contentViewRightConstraint.constant = 20 + constant
}
}
}
break
case .ended:
let halfOfButton: CGFloat = cell.deleteButton.frame.width / 2
if cell.contentViewRightConstraint.constant >= halfOfButton {
setConstraintsToShowAllButtons(cell, true, notifyDelegateDidOpen: true)
} else {
resetConstraintContstants(cell, toZero: true, notifyDelegateDidClose: true)
}
break
case .cancelled:
if cell.startingRightLayoutConstraintConstant == 20 {
resetConstraintContstants(cell, toZero: true, notifyDelegateDidClose: true)
} else {
setConstraintsToShowAllButtons(cell, true, notifyDelegateDidOpen: true)
}
break
default:
break
}
}
}
func setConstraintsToShowAllButtons(_ cell: PostTableViewCell, _ animated: Bool, notifyDelegateDidOpen notifyDelegate: Bool) {
if cell.startingRightLayoutConstraintConstant == 20 + cell.buttonTotalWidth() && cell.contentViewRightConstraint.constant == 20 + cell.buttonTotalWidth() {
return
}
cell.contentViewLeftConstraint.constant = 20 - cell.buttonTotalWidth() - cell.kBounceValue
cell.contentViewRightConstraint.constant = 20 + cell.buttonTotalWidth() + cell.kBounceValue
cell.deleteButtonTrailingConstraint.constant = cell.kBounceValue
cell.updateConstraintsIfNeeded(animated) { finished in
cell.contentViewLeftConstraint.constant = 20 - cell.buttonTotalWidth()
cell.contentViewRightConstraint.constant = 20 + cell.buttonTotalWidth()
cell.deleteButtonTrailingConstraint.constant = 0
cell.updateConstraintsIfNeeded(animated) { finished in
cell.startingRightLayoutConstraintConstant = cell.contentViewRightConstraint.constant
}
}
}
func resetConstraintContstants(_ cell: PostTableViewCell,toZero animated: Bool, notifyDelegateDidClose notifyDelegate: Bool) {
if cell.startingRightLayoutConstraintConstant == 20 && cell.contentViewRightConstraint.constant == 20 {
//Already all the way closed, no bounce necessary
return
}
cell.contentViewRightConstraint.constant = 20 - cell.kBounceValue
cell.contentViewLeftConstraint.constant = 20 + cell.kBounceValue
cell.deleteButtonTrailingConstraint.constant = -cell.deleteButton.frame.width - cell.kBounceValue
cell.updateConstraintsIfNeeded(animated) { finished in
cell.contentViewRightConstraint.constant = 20
cell.contentViewLeftConstraint.constant = 20
cell.deleteButtonTrailingConstraint.constant = -cell.deleteButton.frame.width
cell.updateConstraintsIfNeeded(animated) { finished in
cell.startingRightLayoutConstraintConstant = cell.contentViewRightConstraint.constant
}
}
}