2

I am trying to add multiple buttons to an UIView subclass. In the init() method of the UIView subclass (called leftPanel), I added multiple calls to different functions to add each button. This is how my init() looks like:

override init(frame: CGRect){
    super.init(frame: frame)
    components = self.setupView()
    print("Checkpoint: [leftPanel] init() call finished") // basic debug checkpoint
}

The init() calls a function named setupView() which contains the calls to each of the functions that creates a button. Here is my code for setupView():

func setupView() -> [UIView] {
    let addButton = self.setupAddButton()
    let infoButton = self.setupInfoButton()
    let orderPromoteButton = self.setupOrderPromoteButton()
    let orderDemoteButton = self.setupOrderDemoteButton()
    let refreshItemsButton = self.setupRefreshItemsButton()

    let components = [lessonActionsLabel, addButton, infoButton, orderPromoteButton, orderDemoteButton, refreshItemsButton]
    return components
}

And each of the calls in the setupView function is to a smaller function which contains the code to add each button to the leftPanel subclass. I have done it this way so I can remove each member as I need, and can use each individual setup function to re-add each individual item onto my view as required. Most of the functions are nearly the same, and uses this code:

func setupRefreshItemsButton() -> UIButton {
    let refreshItemsButton = UIButton(type: UIButtonType.infoLight)
    refreshItemsButton.frame = CGRect(x:0, y:screenHeight*55/100, width: screenWidth*30/100, height: screenHeight*5/100)
    refreshItemsButton.setTitle("  Refresh lesson items", for: UIControlState.normal)
    refreshItemsButton.setImage(UIImage(contentsOfFile: "up.png"), for: UIControlState.normal)
    self.addSubview(refreshItemsButton)
    return refreshItemsButton
}

to setup each of the buttons. However, when I run this on the iOS Simulator, the line which is supposed to set the image for each button does not seem to work. When I initialise each button, I initialise them with a type of UIButtonType.infoLight because I want to use the same style of the normal infoLight button (such as the text colour). The only attribute of the infoLight type I would like to change, is the image next to it (which is the (i) by default). I would like to make the icon into an UIImage(contentsOfFile: "up.png"), but it doesn't seem to work. Please can anybody suggest any changes that I could make to achieve this?

I have currently tried to make some changes to what I have, such as changing the type to .custom, seeing if that would change the image, but that does not work either. It only resets the formatting from .infoLight which I'd like to use, so I have switched it back. However, if your solution requires me to change it back to .custom, then I can do it.

I have also tried changing my code to replace up.png with only up but it still doesn't work.

None of my code raises any warnings or errors.

Edit: Most answers have suggested that I change my UIImage(contentsOfFile: "") to UIImage(named: ""), which I have done, but it takes up the entire frame of the UIButton, which I'd like to change, and keep the same as an .infoLight, by keeping a small image with a label on the right. Can anyone suggest a workaround for that too?

What is unique about this question?: Though the .setImage() has been solved by using: UIImage(named:) instead of UIImage(contentsOfFile:), I'd also like to keep the .setTitle() label in the button object. The UIImage(named:) call makes the image fill in the entire frame of the button, but I'd like to keep it the same as .infoLight, with the small image with the title on the right.

sccoding
  • 356
  • 3
  • 18
  • Mistake No. 1: UIImage(contentsOfFile: "up.png" Mistake No. 2: Why do you even set a title if you are going to set an image to the button? Mistake No. 3: UIButton(type: UIButtonType.infoLight) – El Tomato Aug 05 '17 at 06:59
  • Thank you for your comment. I set a title and image as I wanted to have my button a lot like the default `.infoLight` class, which has both a title and an image, which is what I'd like to have. Essentially, I'm trying to get a `.infoLight` button with the (i) changed to a custom image. – sccoding Aug 05 '17 at 07:02
  • Possible duplicate of [How to set image for bar button with swift?](https://stackoverflow.com/questions/27499998/how-to-set-image-for-bar-button-with-swift) – ItsMeMihir Aug 05 '17 at 10:08
  • Added edits to point out possible differences from the other question @ItsMeMihir – sccoding Aug 05 '17 at 16:39

6 Answers6

3

Use the background image, like this:

refreshItemsButton.setBackgroundImage(
   UIImage(named:"up.png"),
   for:UIControlState.normal)
vicegax
  • 4,709
  • 28
  • 37
  • Thank you for your answer too! As this is essentially the same as Harshal's answer, I seem to have the same problems as I've commented on Harshal's answer. Please can you suggest a workaround for it? In specific, please can you suggest how I could have the image only to the left of the title in my button? – sccoding Aug 05 '17 at 15:32
  • Sorry I missed the point that you actually wanted the text displayed to the right and not centred. Just as a clarification, my answer is slightly different from Harshal's, I'm suggesting to set `backgroundImage` property not `image`. – vicegax Aug 05 '17 at 16:10
  • Thanks! Alright, I have tried the `setBackgroundImage` as you have suggested, but it still doesn't seem to work, it just fills up the frame. Any suggestions on how to fix that? – sccoding Aug 05 '17 at 16:23
0

Use this code -

func setupRefreshItemsButton() -> UIButton {
            let refreshItemsButton = UIButton(type: UIButtonType.custom)
            refreshItemsButton.frame = CGRect(x:0, y:screenHeight*55/100, width: screenWidth*30/100, height: screenHeight*5/100)
            refreshItemsButton.setTitle("  Refresh lesson items", for: UIControlState.normal)
            refreshItemsButton.setImage(UIImage(named: "up.png"), for: UIControlState.normal)
            self.addSubview(refreshItemsButton)
            return refreshItemsButton
        }
Abhishek Jain
  • 4,557
  • 2
  • 32
  • 31
  • Thank you for your answer too! As this is essentially the same as Harshal's answer, I seem to have the same problems as I've commented on Harshal's answer. Please can you suggest a workaround for it? – sccoding Aug 05 '17 at 06:37
0

If you want image on left of button title try this-:

refreshItemsButton.setImage(UIImage(named: "up.png"), for: .normal)
refreshItemsButton.imageEdgeInsets = UIEdgeInsetsMake(0,-10, 0, 0)
refreshItemsButton.imageView?.layer.masksToBounds = true
refreshItemsButton.contentMode = .scaleAspectFit

Hope it helps.

Tushar Sharma
  • 2,839
  • 1
  • 16
  • 38
  • Thank you for your answer! I think you understand what I mean when I say that I need an image on the left of the button title, and you are working towards it, but this code still doesn't work. Could you possibly edit your answer to include the entire code from this function, in case I am misplacing where I should put in this code? – sccoding Aug 05 '17 at 15:31
  • @sccoding what is the size of image you have? – Tushar Sharma Aug 05 '17 at 17:52
  • My image is a square 50x50 image, but I'd like to have it the same as the default image size of the (i) in the `.infoLight` setting. And I'd like to keep the title, please. Any suggestions? – sccoding Aug 05 '17 at 18:21
  • Can you do one thing for testing ? Can you download any small icon image and apply on button as I mentioned just to check method works fine, or use any icon image you have around 25×25 – Tushar Sharma Aug 05 '17 at 18:29
  • I have done as you said with one sample image. I am still encountering the same problem. The image will fill up the entire frame of the button, and the title still will not show up. Any suggestions on what I could do? – sccoding Aug 05 '17 at 23:04
  • @sccoding can you send your code so I can check and correct it. – Tushar Sharma Aug 06 '17 at 11:28
  • Sadly, I cannot send the entire project code, but only the parts that I've posted. I believe the error is in there as everything else in my project works just fine. – sccoding Aug 06 '17 at 17:56
0

Use this code, it's actually :

button.setBackgroundImage(UIImage.init(named: "image"), for: .normal)
button.titleLabel?.textAlignment = .left
  • Thank you for your answer too! As this is essentially the same as Harshal's answer, I seem to have the same problems as I've commented on Harshal's answer. Please can you suggest a workaround for it? In specific, please can you suggest how I could have the image only to the left of the title in my button? – sccoding Aug 05 '17 at 15:32
  • I'm updating answer now @sccoding –  Aug 05 '17 at 15:48
  • Hello, thank you for your new answer! I haven't tested this out yet, but I would like to request a clarification, why have you used `UIImage.init(named: "")` instead of just `UIImage(named: "")`? – sccoding Aug 05 '17 at 15:53
  • Hello, I have tested this but it still doesn't seem to work, with the same results as the other answers. However, could you edit your answer to include all the code in the function `setupRefreshItemsButton` just so that I can make sure I am not misplacing where your code should go? – sccoding Aug 05 '17 at 15:55
  • Do not differentiate them both true @sccoding –  Aug 05 '17 at 15:55
  • Also, lastly, you have used `setBackgroundImage`, but shouldn't it be `setImage`? – sccoding Aug 05 '17 at 15:56
  • My current version of the `setupRefreshItemsButton` function is in my question, please check the last block of code. Thanks! – sccoding Aug 05 '17 at 15:57
  • If you write 'setImage' you can't add setTitle but if you write 'setBackgroundImage' you can add setTitle of button, try this and see that ! @sccoding –  Aug 05 '17 at 16:02
  • It's the same result - but I would want to keep the same other settings of `infoLight` if possible. Any suggestions for that? – sccoding Aug 05 '17 at 18:22
0

After some research, I've found out more about UIButton in particular. It inherits from UIView, which means you can use .addSubview() on the UIButton like you would on an UIView.

For example, this is possible to do:

let myButton = UIButton(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
let myButtonBackgroundImage = UIImage(named: "icon.png")
let myButtonBackgroundImageView = UIImageView(frame: x: 0, y: 0, width: 20, height: 20)
myButtonBackgroundImageView.image = myButtonBackgroundImage
myButton.addSubview(myButtonBackgroundImageView)
let myButtonTitleLabel = UILabel(x: 5, y:5, width: 10, height: 10)
myButtonTitleLabel.text = "Hi"
myButton.addSubview(myButtonTitleLabel)

So essentially, while there is no direct method way of doing it, treating UIButton like an UIView can form a workaround like above, which displays with a background image and a title in front of it, exactly what I was looking for.

sccoding
  • 356
  • 3
  • 18
0

You can try this:

element.setImage 

and

element.reloadInputViews()

This working for me...

GYaN
  • 2,327
  • 4
  • 19
  • 39
Jarboox
  • 23
  • 1
  • 7
  • According to the documentation it has nothing to do with the image: "Updates the custom input and accessory views when the object is the first responder." I am guessing it worked for you because you a custom button – OhadM May 09 '21 at 14:17