如何左右滑动uitableview中的单元格,左侧显示图像,右侧显示图像

时间:2016-01-27 08:41:52

标签: ios swift uitableview

如图所示,我需要实现的是向左滑动,显示图像的按钮,蓝色按钮,向右滑动绿色按钮时,如何执行此操作?我使用swift和xcode 6.4

这是我在问之前尝试过的,我能够在单元格右侧显示两个带文本的选项,但我不想要那个,图中需要的是,如上所述,按钮需要是图像而不是文字。

enter image description here

6 个答案:

答案 0 :(得分:18)

您可以将UITableViewCell子类化为合并UIPanGestureRecognizer来操纵单元格的contentView框架,并在contentView后面添加按钮。

为了了解这是如何工作的详细信息,我在下面添加了有关如何执行此操作的示例代码以供参考。这也增加了一个轻敲手势识别器来关闭'点击操作而不是选择单元格。

此外,根据评论中的要求,这里有一个如何工作的GIF(显示侧面按钮的颜色作为行动的指示,但您可以轻松修改contentView' s框架与子类中的按钮完全重叠。)

enter image description here

//
//  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
    }
  }
}

答案 1 :(得分:4)

我可以使用滑动手势识别器获得相同的结果。希望这会有所帮助。

  1. 使用原型单元创建一个表。
  2. 在单元格的左侧和右侧添加按钮,其图像为默认控制状态(您可以根据状态控制状态更改图像)。
  3. 在覆盖整个单元区域的单元格顶部添加容器视图(此处为mainView)。
  4. 通过继承TableViewCustomCell
  5. 创建UITableViewCell
  6. 将原型单元格的类更改为自定义TableViewCustomCell
  7. TableViewCustomCell
  8. 中使用以下代码

    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;
            }
    
        }
    }
    

答案 2 :(得分:4)

有很多方法可以解决这个问题,您可以查看许多现有库中的一个,例如Massimiliano Bigatti https://github.com/mbigatti/BMXSwipableCell的BMXSwipeableCell,您可以在其中查看源代码或完全复制它。

另一种方法是阅读以下两个很棒的教程之一:

如何使用动作制作可滑动的TableViewCell - 不使用坚果ScrollViews - 作者:Ellen Shapiro: https://www.raywenderlich.com/62435/make-swipeable-table-view-cell-actions-without-going-nuts-scroll-views

如何制作一个手势驱动的待办事项列表应用程序,如Swift中的Clear - 作者:Audrey Tam:https://www.raywenderlich.com/77974/making-a-gesture-driven-to-do-list-app-like-clear-in-swift-part-1

为了给你一个快速的想法,要点如下:

我。创建自定义TableViewCell

II。添加UIPangestureRecognizer

III。保留对原始contentView框架的引用,这是必要的,因为您将向左和向右滑动(平移)此contentView。并保持对单元格原始中心的引用。

IV。将要显示的图像,按钮或其他视图添加到单元格

您将通过UIPanGestureRecognizer的{​​{1}}的三个阶段指导可滑动单元格的外观:UIGestureStateBegan, UIGestureStateChanged, UIGestureStateEnded

  1. UIGestureStateBegan:首先检查这是一个水平平移,而不是UIGestureDelegate中的垂直平移。我们这样做是为了不混淆UITableView,你可能还记得它是垂直滚动的。然后获取对单元格原始中心的引用。

  2. UIGestureStateChanged:当用户将手指向左或向右移动时,我们需要更新单元格的外观。通过使用原始中心参考移动单元格的contentView's中心,以及通过手势给我们的移动,我们可以获得我们希望实现的行为。

  3. UIGestureStateEnded:在这里,我们需要决定是否要在用户释放单元格后保留显示的图像,按钮等,或者我们是否要“快速”回来。这个阈值确实达到,但是与单元格的总宽度相比,左边或右边会有某种百分比变化。如果你想“反弹”,只需将contentView的帧设置为我们保留引用的原始帧即可。如果没有,请将其设置为一个偏好,以便很好地显示您希望显示的内容。

  4. 我希望这有助于理解这个概念,请查看其中一个令人惊叹的教程,以获得更详细的解释!

答案 3 :(得分:1)

如果你想使用库来实现这样的功能,我建议你使用 https://github.com/MortimerGoro/MGSwipeTableCell ......

易于使用且易于定制。

答案 4 :(得分:0)

总体思路很简单 - 您的单元格内容视图是UIScrollView,其中包含两侧的视图。

然而,完整的工作解决方案有点复杂,可能过于宽泛而无法回答。

我建议您从已经实施的解决方案开始,例如: SWTableViewCell(但还有其他人)并查看源代码。或者直接使用它。大多数解决方案都可以使用cocoapods安装,它们可以在Swift和Objective-C中使用。

答案 5 :(得分:-2)

基于@Tobi Nary的答案,这是4.2的快速版本。

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 : UIView.AnimationOptions = [.allowUserInteraction, .beginFromCurrentState]
    var animationDuration : TimeInterval = 0.5
    var animationDelay : TimeInterval = 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 = CGPoint.zero
    weak var rightButton : UIButton! {
        willSet(val) {
            if let r = self.rightButton {
                r.removeFromSuperview()
            }
            if let b = val {
                self.addSubview(b)
                b.addTarget(self, action: Selector(("didTapButton:")), for: .touchUpInside)
                b.translatesAutoresizingMaskIntoConstraints = false
                self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-(0)-[v]-(0)-|", options: [], metrics: nil, views: ["v":b]))
                self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "[v]-(0)-|", options: [], metrics: nil, views: ["v":b]))
                let wc = NSLayoutConstraint(item: b, attribute: NSLayoutConstraint.Attribute.width, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil,     attribute: NSLayoutConstraint.Attribute.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: Selector("didTapButton:"), for: .touchUpInside)
                b.translatesAutoresizingMaskIntoConstraints = false
                self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-(0)-[v]-(0)-|", options: [], metrics: nil, views: ["v":b]))
                self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "|-(0)-[v]", options: [], metrics: nil, views: ["v":b]))
                let wc = NSLayoutConstraint(item: b, attribute: NSLayoutConstraint.Attribute.width, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil,     attribute: NSLayoutConstraint.Attribute.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: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        commonInit()
    }

    private func commonInit() {

        let pan = UIPanGestureRecognizer(target: self, action: Selector(("didPan:")))
        pan.delegate = self
        self.addGestureRecognizer(pan)
        self.panRecognizer = pan

        let tap = UITapGestureRecognizer(target: self, action: Selector(("didTap:")))
        tap.delegate = self
        self.addGestureRecognizer(tap)
        self.buttonCancelTap = tap

        self.contentView.backgroundColor = UIColor.clear
    }


    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.translation(in: 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.animate(withDuration: 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(cell: self)
            self.beginPoint = sender.location(in: self)
            self.beginPoint.x -= self.contentView.frame.origin.x

        case .changed:
            let now = sender.location(in: 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.isEnabled = false
                    sender.isEnabled = 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.isEnabled = false
                    sender.isEnabled = true
                }
            }

        default:
            delegate?.swipeableTableViewCellDidRecognizeSwipe(cell: self)
            let offset = self.contentView.frame.origin.x
            if offset > self.buttonWidth && self.leftButton != nil {
                UIView.animate(withDuration: 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.animate(withDuration: 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.animate(withDuration: 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.animate(withDuration: 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.isEnabled = false
                    self.panRecognizer.isEnabled = true
                }, completion: nil)
            }
            else {
                self.contentView.frame.origin.x = 0
                self.panRecognizer.isEnabled = false
                self.panRecognizer.isEnabled = true

            }
            return true
        }
        else {
            return false
        }
    }

    func didTapButton(sender:UIButton!) {
        if let d = delegate {
            if let l = self.leftButton {
                if sender == l {
                    d.swipeableTableViewCellDidTapLeftButton(cell: self)
                }
            }
            if let r = self.rightButton {
                if sender == r {
                    d.swipeableTableViewCellDidTapRightButton(cell: self)
                }
            }
        }
        self.closeButtonsIfShown(animated: 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
        }
    }
}