Wie dargestellt, muss ich beim Wischen nach links einen Button mit einem Bild anzeigen, den blauen, und wenn Sie nach rechts wischen, wird der grüne Button angezeigt. Wie soll das gehen? Ich verwende Swift und Xcode 6.4
Das habe ich versucht, bevor ich gefragt habe. Ich konnte zwei Optionen mit Text rechts von einer Zelle anzeigen, aber ich möchte das nicht. Was benötigt wird, ist in der Abbildung. Wie gesagt, die Schaltflächen müssen Bilder sein kein Text.
Sie können die Unterklasse UITableViewCell
einschließen, um einen UIPanGestureRecognizer
aufzunehmen, der den contentView
s-Rahmen der Zelle bearbeitet und Ihre Schaltflächen hinter dem contentView
hinzufügt.
Um zu sehen, wie dies im Detail funktionieren kann, habe ich Beispielcode hinzugefügt, wie das unten als Referenz beschrieben wird. Dadurch wird auch eine Tippen-Gesten-Erkennung hinzugefügt, um die Aktion beim Tippen zu schließen, anstatt die Zelle auszuwählen.
Wie in den Kommentaren angefordert, finden Sie hier ein Gif, wie dies funktioniert (wobei die Farben der Schaltflächen auf der Seite als Hinweis auf eine Aktion angezeigt werden. Sie können jedoch den Rahmen von contentView
leicht ändern, um die Schaltflächen in Ihrer Unterklasse vollständig zu überlappen. )
//
// MWSwipeableTableViewCell.Swift
// MW UI Toolkit
//
// Created by Jan Greve on 02.12.14.
// Copyright (c) 2014 Markenwerk GmbH. All rights reserved.
//
import UIKit
protocol MWSwipeableTableViewCellDelegate : NSObjectProtocol {
func swipeableTableViewCellDidRecognizeSwipe(cell : MWSwipeableTableViewCell)
func swipeableTableViewCellDidTapLeftButton(cell : MWSwipeableTableViewCell)
func swipeableTableViewCellDidTapRightButton(cell : MWSwipeableTableViewCell)
}
class MWSwipeableTableViewCell: UITableViewCell {
weak var delegate : MWSwipeableTableViewCellDelegate?
var animationOptions : UIViewAnimationOptions = [.AllowUserInteraction, .BeginFromCurrentState]
var animationDuration : NSTimeInterval = 0.5
var animationDelay : NSTimeInterval = 0
var animationSpingDamping : CGFloat = 0.5
var animationInitialVelocity : CGFloat = 1
private weak var leftWidthConstraint : NSLayoutConstraint!
private weak var rightWidthConstraint : NSLayoutConstraint!
var buttonWidth :CGFloat = 80 {
didSet(val) {
if let r = self.rightWidthConstraint {
r.constant = self.buttonWidth
}
if let l = self.leftWidthConstraint {
l.constant = self.buttonWidth
}
}
}
private weak var panRecognizer : UIPanGestureRecognizer!
private weak var buttonCancelTap : UITapGestureRecognizer!
private var beginPoint : CGPoint = CGPointZero
weak var rightButton : UIButton! {
willSet(val) {
if let r = self.rightButton {
r.removeFromSuperview()
}
if let b = val {
self.addSubview(b)
b.addTarget(self, action: "didTapButton:", forControlEvents: .TouchUpInside)
b.translatesAutoresizingMaskIntoConstraints = false
self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-(0)-[v]-(0)-|", options: [], metrics: nil, views: ["v":b]))
self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("[v]-(0)-|", options: [], metrics: nil, views: ["v":b]))
let wc = NSLayoutConstraint(item: b, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: self.buttonWidth)
b.addConstraint(wc)
self.rightWidthConstraint = wc
self.sendSubviewToBack(b)
}
}
}
weak var leftButton : UIButton! {
willSet(val) {
if let l = self.leftButton {
l.removeFromSuperview()
}
if let b = val {
self.addSubview(b)
b.addTarget(self, action: "didTapButton:", forControlEvents: .TouchUpInside)
b.translatesAutoresizingMaskIntoConstraints = false
self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-(0)-[v]-(0)-|", options: [], metrics: nil, views: ["v":b]))
self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("|-(0)-[v]", options: [], metrics: nil, views: ["v":b]))
let wc = NSLayoutConstraint(item: b, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: self.buttonWidth)
b.addConstraint(wc)
self.leftWidthConstraint = wc
self.sendSubviewToBack(b)
}
}
}
override func awakeFromNib() {
super.awakeFromNib()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
commonInit()
}
private func commonInit() {
let pan = UIPanGestureRecognizer(target: self, action: "didPan:")
pan.delegate = self
self.addGestureRecognizer(pan)
self.panRecognizer = pan
let tap = UITapGestureRecognizer(target: self, action: "didTap:")
tap.delegate = self
self.addGestureRecognizer(tap)
self.buttonCancelTap = tap
self.contentView.backgroundColor = UIColor.clearColor()
}
override func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
if let tap = gestureRecognizer as? UITapGestureRecognizer {
if tap == self.buttonCancelTap {
return self.contentView.frame.Origin.x != 0
}
else {
return super.gestureRecognizerShouldBegin(gestureRecognizer)
}
}
else if let pan = gestureRecognizer as? UIPanGestureRecognizer {
let trans = pan.translationInView(self)
if abs(trans.x) > abs(trans.y) {
return true
}
else if self.contentView.frame.Origin.x != 0 {
return true
}
else {
return false
}
}
else {
return super.gestureRecognizerShouldBegin(gestureRecognizer)
}
}
func didTap(sender : UITapGestureRecognizer) {
UIView.animateWithDuration(self.animationDuration, delay: self.animationDelay, usingSpringWithDamping: self.animationSpingDamping, initialSpringVelocity: self.animationInitialVelocity, options: self.animationOptions, animations: { () -> Void in
self.contentView.frame.Origin.x = 0
}, completion: nil)
}
func didPan(sender: UIPanGestureRecognizer) {
switch sender.state {
case .Began:
self.delegate?.swipeableTableViewCellDidRecognizeSwipe(self)
self.beginPoint = sender.locationInView(self)
self.beginPoint.x -= self.contentView.frame.Origin.x
case .Changed:
let now = sender.locationInView(self)
let distX = now.x - self.beginPoint.x
if distX <= 0 {
let d = max(distX,-(self.contentView.frame.size.width-self.buttonWidth))
if d > -self.buttonWidth*2 || self.rightButton != nil || self.contentView.frame.Origin.x > 0 {
self.contentView.frame.Origin.x = d
}
else {
sender.enabled = false
sender.enabled = true
}
}
else {
let d = min(distX,self.contentView.frame.size.width-self.buttonWidth)
if d < self.buttonWidth*2 || self.leftButton != nil || self.contentView.frame.Origin.x < 0 {
self.contentView.frame.Origin.x = d
}
else {
sender.enabled = false
sender.enabled = true
}
}
default:
delegate?.swipeableTableViewCellDidRecognizeSwipe(self)
let offset = self.contentView.frame.Origin.x
if offset > self.buttonWidth && self.leftButton != nil {
UIView.animateWithDuration(self.animationDuration, delay: self.animationDelay, usingSpringWithDamping: self.animationSpingDamping, initialSpringVelocity: self.animationInitialVelocity, options: self.animationOptions, animations: { () -> Void in
self.contentView.frame.Origin.x = self.buttonWidth
}, completion: nil)
}
else if -offset > self.buttonWidth && self.rightButton != nil {
UIView.animateWithDuration(self.animationDuration, delay: self.animationDelay, usingSpringWithDamping: self.animationSpingDamping, initialSpringVelocity: self.animationInitialVelocity, options: self.animationOptions, animations: { () -> Void in
self.contentView.frame.Origin.x = -self.buttonWidth
}, completion: nil)
}
else {
UIView.animateWithDuration(self.animationDuration, delay: self.animationDelay, usingSpringWithDamping: self.animationSpingDamping, initialSpringVelocity: self.animationInitialVelocity, options: self.animationOptions, animations: { () -> Void in
self.contentView.frame.Origin.x = 0
}, completion: nil)
}
}
}
func closeButtonsIfShown(animated:Bool = true) -> Bool {
if self.contentView.frame.Origin.x != 0 {
if animated {
UIView.animateWithDuration(self.animationDuration, delay: self.animationDelay, usingSpringWithDamping: self.animationSpingDamping, initialSpringVelocity: self.animationInitialVelocity, options: self.animationOptions, animations: { () -> Void in
self.contentView.frame.Origin.x = 0
self.panRecognizer.enabled = false
self.panRecognizer.enabled = true
}, completion: nil)
}
else {
self.contentView.frame.Origin.x = 0
self.panRecognizer.enabled = false
self.panRecognizer.enabled = true
}
return true
}
else {
return false
}
}
func didTapButton(sender:UIButton!) {
if let d = delegate {
if let l = self.leftButton {
if sender == l {
d.swipeableTableViewCellDidTapLeftButton(self)
}
}
if let r = self.rightButton {
if sender == r {
d.swipeableTableViewCellDidTapRightButton(self)
}
}
}
self.closeButtonsIfShown(false)
}
override func setHighlighted(highlighted: Bool, animated: Bool) {
let showing = self.contentView.frame.Origin.x != 0
if !showing {
super.setHighlighted(highlighted, animated: animated)
self.rightButton?.alpha = showing || !highlighted ? 1 : 0
self.leftButton?.alpha = showing || !highlighted ? 1 : 0
}
}
override func setSelected(selected: Bool, animated: Bool) {
let showing = self.contentView.frame.Origin.x != 0
if !showing {
super.setSelected(selected, animated: animated)
self.rightButton?.alpha = showing || !selected ? 1 : 0
self.leftButton?.alpha = showing || !selected ? 1 : 0
}
}
}
Es gibt viele Möglichkeiten, dies zu tun. Sie können in eine der vielen vorhandenen Bibliotheken wie BMXSwipeableCell von Massimiliano Bigatti https://github.com/mbigatti/BMXSwipableCell schauen, wo Sie entweder den Quellcode betrachten können oder kopiere es komplett.
Ein weiterer Ansatz ist das Lesen einer der folgenden zwei großartigen Tutorials:
So erstellen Sie eine swipeable TableViewCell mit Aktionen - ohne gehende Muttern ScrollViews - von Ellen Shapiro: https://www.raywenderlich.com/62435/make-swipeable-table-view-cell-actions -ohne verrückte Bildlauf-Ansichten
So erstellen Sie eine gestengesteuerte To-Do-Liste wie in Swift - von Audrey Tam: https://www.raywenderlich.com/77974/making-a-gesture-driven-to-do -list-app-like-clear-in-Swift-part-1
Um Ihnen eine schnelle Vorstellung zu geben, lautet der Gist wie folgt:
ich. Erstellen Sie eine benutzerdefinierte TableViewCell
ii. UIPangestureRecognizer
hinzufügen
iii. Behalten Sie einen Verweis auf dem ursprünglichen contentView
-Rahmen bei, dies ist erforderlich, da Sie diese contentView
nach links und rechts bewegen (schwenken). Halten Sie einen Verweis auf das OriginalCenter der Zelle.
iv. Fügen Sie der Zelle die Bilder, Schaltflächen oder anderen Ansichten hinzu, die Sie anzeigen möchten
Was passiert, ist, dass Sie das Erscheinungsbild Ihrer zuschaltbaren Zelle durch die drei Stufen der UIPanGestureRecognizer
führen: UIGestureStateBegan, UIGestureStateChanged, UIGestureStateEnded
UIGestureStateBegan
: Prüfen Sie zunächst, ob es sich um eine horizontale Verschiebung und nicht um eine vertikale Verschiebung in der UIGestureDelegate
handelt. Wir machen dies, um die UITableView nicht zu verwechseln, da Sie sich vielleicht erinnern, vertikal zu scrollen. Dann erhalten Sie einen Verweis auf das ursprüngliche Zentrum der Zelle.
UIGestureStateChanged
: Wenn ein Benutzer seinen Finger nach links oder rechts bewegt, müssen wir das Erscheinungsbild der Zelle aktualisieren. Durch Verschieben des contentView's
-Mittelpunkts der Zelle unter Verwendung der ursprünglichen Mittelpunktsreferenz und der Bewegung, die uns durch die Geste gegeben wird, erhalten wir genau das Verhalten, das wir erreichen möchten.
UIGestureStateEnded
: Hier müssen wir entscheiden, ob wir das enthüllte Bild, die Schaltfläche usw. nach dem Freigeben der Zelle in Sicht behalten möchten oder ob wir zurückschnappen wollen. Der Schwellenwert dafür ist wirklich bis zu, wird jedoch eine prozentuale Änderung nach links oder rechts sein, verglichen mit der Gesamtbreite der Zelle. Wenn Sie zurückschnappen möchten, setzen Sie einfach den Frame der contentView
auf den ursprünglichen Frame, auf den wir einen Verweis gehalten haben. Ist dies nicht der Fall, stellen Sie einen Versatz ein, der den Inhalt, den Sie anzeigen möchten, schön darstellt.
Ich hoffe, dass dies dazu beigetragen hat, dass das Konzept vermittelt wird. Bitte lesen Sie eines der beiden erstaunlichen Tutorials für eine detailliertere Erklärung!
Mit der Swipe-Gestenerkennung konnte ich dasselbe Ergebnis erzielen. Hoffe das würde helfen.
TableViewCustomCell
durch Unterklasse der UITableViewCell
TableViewCustomCell
.TableViewCustomCell
SWIFT-Code :
import UIKit
class TableViewCustomCell:UITableViewCell {
@IBOutlet weak var rightButton: UIButton!
@IBOutlet weak var leftButton: UIButton!
@IBOutlet weak var mainView: UIView!
@IBAction func leftButtonTap(sender: AnyObject) {
print("leftTap")
}
@IBAction func rightButtonTap(sender: AnyObject) {
print("rightTap")
}
override func awakeFromNib() {
let leftSwipe = UISwipeGestureRecognizer(target: self, action:Selector("swipe:"))
leftSwipe.direction = .Left;
self.mainView.addGestureRecognizer(leftSwipe)
let rightSwipe = UISwipeGestureRecognizer(target: self, action:Selector("swipe:"))
rightSwipe.direction = .Right;
self.mainView.addGestureRecognizer(rightSwipe)
}
func swipe(sender:AnyObject)
{
let swipeGesture:UISwipeGestureRecognizer = sender as! UISwipeGestureRecognizer
if(swipeGesture.direction == .Left)
{
var frame:CGRect = self.mainView.frame;
frame.Origin.x = -self.leftButton.frame.width;
self.mainView.frame = frame;
}
else if(swipeGesture.direction == .Right)
{
var frame:CGRect = self.mainView.frame;
frame.Origin.x = +self.rightButton.frame.width;
self.mainView.frame = frame;
}
}
}
Wenn Sie die Bibliothek für eine solche Funktion verwenden möchten, würde ich vorschlagen, https://github.com/MortimerGoro/MGSwipeTableCell ... zu verwenden.
es ist einfach zu bedienen und einfach anzupassen.
Die allgemeine Idee ist einfach: Die Inhaltsansicht Ihres Zellen ist eine UIScrollView
mit Ansichten auf den Seiten.
Die komplette Arbeitslösung ist jedoch etwas kompliziert und wahrscheinlich zu breit für eine Antwort.
Ich würde Ihnen empfehlen, mit einer bereits implementierten Lösung zu beginnen, z. SWTableViewCell (aber es gibt andere) und schauen Sie in den Quellcode. Oder nutzen Sie es einfach direkt. Die meisten Lösungen können mit cocoapods
installiert werden und funktionieren sowohl in Swift als auch in Objective-C.