11

Inside a UITableViewCell, I am trying to implement a button with both an image and a text.

It seems the standard UIButton cannot achieve that. So I created a UIView which contains a UIImageView and a UILabel.

You can see the implementation here on the right hand side, the "follow trip" button (the "+" is an UIImageView, and "follow trip" is a UILabel)

enter image description here

I am now trying to make such UIView (i.e. the button) clickable, but I cannot find a way.

This is my implementation, but it doesn't work:

class StationsIntroHeader: UITableViewCell {

    @IBOutlet weak var bigButton: UIView!

    override  func awakeFromNib() {
        super.awakeFromNib()
        let tap = UITapGestureRecognizer(target: self, action: Selector("followTrip:"))
        bigButton.addGestureRecognizer(tap)
    }

    func followTrip(sender:UITapGestureRecognizer) {
        print("tap working")
    }
}

I have made sure the User Interaction Enabled is ON on the UIView and OFF on both the UIImageView and UILabel

Daniele B
  • 19,801
  • 29
  • 115
  • 173
  • 2
    you can just do a orange image with plus sign as background image for your button and right align the follow trip label, or also you can add a custom button same size as your view and add it to your view with transparent background and no label so you can click it – SpaceDust__ Nov 11 '15 at 20:25
  • 1
    The touches are being "absorbed" by the `UITableView`. Add a gesture recogniser to the `UITableView` instead and use the coordinates to figure out which cell and which button was clicked. – R Menke Nov 11 '15 at 20:26
  • for me an implementation like yours is totally working! are you sure you set up everything correctly? – André Slotta Nov 11 '15 at 21:07

2 Answers2

9

for me a sample setup like the following totally works:

class TableViewController: UITableViewController {
  override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 5
  }

  override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    return tableView.dequeueReusableCellWithIdentifier("CustomCell", forIndexPath: indexPath)
  }
}

class CustomCell: UITableViewCell {
  @IBOutlet weak var bigButton: UIView!

  override func awakeFromNib() {
    super.awakeFromNib()
    let tap = UITapGestureRecognizer(target: self, action: Selector("bigButtonTapped:"))
    bigButton.addGestureRecognizer(tap)
  }

  func bigButtonTapped(sender: UITapGestureRecognizer) {
    print("bigButtonTapped")
  }
}

i did not change any of the default values of userInteractionEnabled for the view or imageview or label. compare my implementation with yours and see if you maybe forgot something... did you e.g. connect the outlet?

sample project: https://www.dropbox.com/sh/hpetivhc3gfrapf/AAAf6aJ0zhvRINPFJHD-iMvya?dl=0

edit for your project

func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
  let headerCell = tableView.dequeueReusableCellWithIdentifier("StationsIntroHeader") as! StationsIntroHeader
  headerCell.update()
  return headerCell
  // return headerCell.update().contentView
}
André Slotta
  • 13,774
  • 2
  • 22
  • 34
  • Hi Andrè! I just run your project, and it works indeed! I am trying now to compare the Interface Builder settings of the controls to spot any difference – Daniele B Nov 12 '15 at 11:45
  • If you do not find what is going wrong, share your project via dropbox - if available - and I take a look! – André Slotta Nov 12 '15 at 11:48
  • I can't find the fix! I uploaded a simplified version: https://www.dropbox.com/sh/rgfvrn1jpqcfloj/AADEar4aryx08rwb6je5s_mqa?dl=0 – Daniele B Nov 12 '15 at 12:42
0

You can simply subclass UIButton, and implement the custom drawing in it. UIButton is the simplest way to do the task without interfering the tableview touches. If you implement tap gesture on table view, it will cause problems to the cell touches.

You can simply get the custom image (both + sign and text as one image) and use it as background image.

Or you can even draw it with code.

For example, you can try this:

 func drawCanvas1(frame frame: CGRect = CGRectMake(3, 8, 209, 109)) {
    //// General Declarations
    let context = UIGraphicsGetCurrentContext()

    //// Color Declarations
    let color = UIColor(red: 0.967, green: 0.423, blue: 0.211, alpha: 1.000)

    //// Image Declarations
    let screenShot20151111At32900PM = UIImage(named: "screenShot20151111At32900PM.png")!

    //// Rectangle Drawing
    let rectanglePath = UIBezierPath(roundedRect: CGRectMake(frame.minX + 39, frame.minY + 23, 113, 46), cornerRadius: 8)
    color.setFill()
    rectanglePath.fill()


    //// Rectangle 2 Drawing
    let rectangle2Rect = CGRectMake(frame.minX + 51, frame.minY + 27, 33, 34)
    let rectangle2Path = UIBezierPath(rect: rectangle2Rect)
    CGContextSaveGState(context)
    rectangle2Path.addClip()
    screenShot20151111At32900PM.drawInRect(CGRectMake(floor(rectangle2Rect.minX - 16 + 0.5), floor(rectangle2Rect.minY - 15 + 0.5), screenShot20151111At32900PM.size.width, screenShot20151111At32900PM.size.height))
    CGContextRestoreGState(context)


    //// Text Drawing
    let textRect = CGRectMake(frame.minX + 97, frame.minY + 23, 73, 46)
    let textTextContent = NSString(string: "\nfollow\ntrip\n")
    let textStyle = NSParagraphStyle.defaultParagraphStyle().mutableCopy() as! NSMutableParagraphStyle
    textStyle.alignment = .Left

    let textFontAttributes = [NSFontAttributeName: UIFont.systemFontOfSize(UIFont.labelFontSize()), NSForegroundColorAttributeName: UIColor.whiteColor(), NSParagraphStyleAttributeName: textStyle]

    let textTextHeight: CGFloat = textTextContent.boundingRectWithSize(CGSizeMake(textRect.width, CGFloat.infinity), options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: textFontAttributes, context: nil).size.height
    CGContextSaveGState(context)
    CGContextClipToRect(context, textRect);
    textTextContent.drawInRect(CGRectMake(textRect.minX, textRect.minY + (textRect.height - textTextHeight) / 2, textRect.width, textTextHeight), withAttributes: textFontAttributes)
    CGContextRestoreGState(context)
}

and the result will be something like:

enter image description here

shim
  • 9,289
  • 12
  • 69
  • 108
Teja Nandamuri
  • 11,045
  • 6
  • 57
  • 109