Image for UIControlState.Selected does not appear - ios

The title says it all. Here is my code:
func createCheckBoxButton(xPos: CGFloat, yPos: CGFloat, tag: Int) -> UIButton {
var checkBox = UIButton(frame: CGRect(x: xPos, y: yPos, width: checkBoxSize, height: checkBoxSize))
checkBox.setBackgroundImage(UIImage(named: "checkbox_inactive"), forState: UIControlState.Normal)
checkBox.setBackgroundImage(UIImage(named: "checkbox_pressed"), forState: UIControlState.Highlighted)
checkBox.setBackgroundImage(UIImage(named: "checkbox_active"), forState: UIControlState.Selected)
checkBox.tag = tag
checkBox.contentMode = .ScaleAspectFit
checkBox.addTarget(self, action: "processButton:", forControlEvents: UIControlEvents.TouchUpInside)
return checkBox
}
And there is the called function when my button is pressed:
func processButton(sender: UIButton) {
if (answerViewArray[sender.tag].backgroundColor == UIColor.whiteColor()) {
answerViewArray[sender.tag].backgroundColor = myColor.pinky()
} else {
answerViewArray[sender.tag].backgroundColor = UIColor.whiteColor()
}
let tag = answerButtonsArray[sender.tag]
answer.buttonPressed(tag)
}
When I launch the app, the checkbox_inactive image is there. When I press and keep it pressed, the checkbox_pressed image appears. But when I release my click the checkbox_inactive appears again instead of checkbox_active.
I also tried with an UIImageView, which would be the best solution for me actually. I set my checkbox as an UIImageView and at the top of my general view I put an invisible view so I can click everywhere. But when I press my invisible view, the UIImageView simply disappears.
Here is the code:
func createCheckBoxButton(xPos: CGFloat, yPos: CGFloat) -> UIImageView {
var checkBox = UIImageView(frame: CGRect(x: xPos, y: yPos, width: checkBoxSize, height: checkBoxSize))
checkBox.image = UIImage(named: "checkbox_inactive")
checkBox.contentMode = .ScaleAspectFit
return checkBox
}
Here is the function called:
func processButton(sender: UIButton) {
if (answerViewArray[sender.tag].backgroundColor == UIColor.whiteColor()) {
answerViewArray[sender.tag].backgroundColor = myColor.pinky()
checkBoxArray[sender.tag].image = UIImage(named: "checkbox-active")
} else {
answerViewArray[sender.tag].backgroundColor = UIColor.whiteColor()
checkBoxArray[sender.tag].image = UIImage(named: "checkbox-inactive")
}
let tag = answerButtonsArray[sender.tag]
answer.buttonPressed(tag)
}

To make appear checkbox_active when you release your button you should make selected=true for the pressed button.
So your function should be like:
func processButton(sender: UIButton) {
// If button not selected
if(sender.selected==false){
sender.selected = true;
}
else{ // If button already selected
sender.selected = false;
}
// Do your other stuff
}

Related

Add border to buttons in iOS scroll view on click and remove border from other buttons

I have added buttons to horizontal Scroll View in iOS.
override func viewDidLoad() {
super.viewDidLoad()
setUpScrollView()
// Do any additional setup after loading the view, typically from a nib.
}
func setUpScrollView() {
let buttonPadding:CGFloat = 10
var xOffset:CGFloat = 10
for i in 0 ... 10 {
let button = UIButton()
button.tag = i
button.backgroundColor = UIColor.red
button.setTitle("\(i)", for: .normal)
if(button.tag==currentTag){
button.addTarget(self, action: #selector(btnTouchUnselect), for: UIControlEvents.touchUpInside)
}
else{
button.addTarget(self, action: #selector(btnTouch), for: UIControlEvents.touchUpInside)
}
button.frame = CGRect(x: xOffset, y: CGFloat(buttonPadding), width: 70, height: 30)
xOffset = xOffset + CGFloat(buttonPadding) + button.frame.size.width;
scrollView.addSubview(button)
}
scrollView.contentSize = CGSize(width: xOffset, height: scrollView.frame.height)
}
#objc func btnTouch(button:UIButton){
print("tap touch",button.tag)
button.layer.borderColor = UIColor.black.cgColor
button.layer.borderWidth = 1.0
currentTag = button.tag
}
#objc func btnTouchUnselect(button:UIButton){
button.layer.borderColor = UIColor.white.cgColor
button.layer.borderWidth = 1.0
}
}
I want a button to get a different border color when the user clicks it and the others to stay black. But when I am using this code it turns all clicked button borders black and doesn't turn the clicked one white.
Aim Example:-Suppose I have 10 buttons, I want when button 1's is clicked then its border turns white and others' remain black; if button 2 is clicked then the borders of all turn black again including button 1, only the border of button 2 changes to white.
I need some guidance to achieve this.
I think the problem is that your buttons are only accessible in setScrollView.
so when a button tapped, in #Anton answer, just the clicked button is known in the didTap function.
I think that a better idea is to make an array of UIButtons,
initiate them in setScrollView,
and then use #Anton didTap function
class yourClass {
var buttons : [UIButton] = Array(repeatElement(UIButton(), count: 10))
override func viewDidLoad() {
super.viewDidLoad()
setUpScrollView()
// Do any additional setup after loading the view, typically from a nib.
}
func setUpScrollView() {
let buttonPadding:CGFloat = 10
var xOffset:CGFloat = 10
for i in 0...9 {
buttons[i].tag = i
buttons[i].backgroundColor = UIColor.red
buttons[i].setTitle("\(i)", for: .normal)
//Other functionality that you had set here before...
}
#objc func didTap(clickedButton: UIButton) {
for eachButton in self.buttons {
if eachButton.tag == clickedButton.tag {
eachButton.layer.borderColor = UIColor.white.cgColor
} else {
eachButton.layer.borderColor = UIColor.balck.cgColor
}
}
currentTag = clickedButton.tag
}
}
try this code
var allButtons = [UIButton]()
override func viewDidLoad() {
super.viewDidLoad()
setUpScrollView()
// Do any additional setup after loading the view, typically from a nib.
}
func setUpScrollView() {
let buttonPadding:CGFloat = 10
var xOffset:CGFloat = 10
for i in 0 ... 10 {
let button = UIButton()
button.tag = i
button.backgroundColor = UIColor.red
button.layer.borderWidth = 1.0
button.setTitle("\(i)", for: .normal)
button.addTarget(self, action: #selector(didTap), for: UIControlEvents.touchUpInside)
button.frame = CGRect(x: xOffset, y: CGFloat(buttonPadding), width: 70, height: 30)
xOffset = xOffset + CGFloat(buttonPadding) + button.frame.size.width;
scrollView.addSubview(button)
allButtons.append(button)
}
scrollView.contentSize = CGSize(width: xOffset, height: scrollView.frame.height)
}
#objc func didTap(button: UIButton) {
print("tap touch",button.tag)
allButtons.forEach { inButton in
if inButton == button {
button.layer.borderColor = UIColor.black.cgColor
} else {
button.layer.borderColor = UIColor.white.cgColor
}
}
currentTag = button.tag
}

Remove clear button on clicking any other field or anywhere

I managed to show a custom clearbutton, the problem is that it will not be removed when clicking anywhere else or clicking other textfield. It is always showing.
Here is my extension:
extension UITextField {
func clearButtonWithImage(_ image: UIImage) {
let clearButton = UIButton()
clearButton.setImage(image, for: .normal)
clearButton.frame = CGRect(x: 0, y: 0, width: 20, height: 20)
clearButton.contentMode = .scaleAspectFit
clearButton.addTarget(self, action: #selector(self.clear(sender:)), for: .touchUpInside)
self.rightView = clearButton
self.rightViewMode = .always
}
func clear(sender: AnyObject) {
self.text = ""
}
}
and here i show the clearbutton on the method:
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
if textField == dateSearchTextField {
self.performSegue(withIdentifier: "showCalendar", sender: self)
textField.clearButtonWithImage(#imageLiteral(resourceName: "icClear"))
return false
} else if textField == timeSearchTextField {
self.performSegue(withIdentifier: "showTimePicker", sender: self)
textField.clearButtonWithImage(#imageLiteral(resourceName: "icClear"))
return false
}
return true
}
I want it to be visible only when clicking inside the textfield.
Replace this:
self.rightViewMode = .always
With:
self.rightViewMode = .whileEditing

How to Change previous button color when pressed the next button?

I have a number of buttons in a horizontal UIScrollView added programmatically. I have to change the color of the user selected button. But if user select another button the previous button color must be change to default color.
how can I do this? Please help me...
func createHorizontalScroll()
{
let scrollView = UIScrollView(frame: CGRect(x: CGFloat(0), y: CGFloat(410), width: CGFloat(view.frame.size.width), height: CGFloat(40)))
var buttonX: CGFloat = 0
for index in 0..<btnNames.count
{
//add an element and the previous element together
let sum = btnNames[index]
button = UIButton(frame: CGRect(x: CGFloat(buttonX), y: CGFloat(0), width: CGFloat(100), height: CGFloat(40)))
print("btnNames:\(sum)")
button.setTitle("\(sum)",for:.normal)
button.layer.borderWidth = 2.5
button.layer.borderWidth = 2.5
button.layer.borderColor = UIColor.white.cgColor
button.layer.backgroundColor = UIColor.black.cgColor
button.tag = index
scrollView.addSubview(button)
buttonX = button.frame.size.width + buttonX
button.addTarget(self, action: #selector(changeView), for: .touchUpInside)
}
scrollView.contentSize = CGSize(width: CGFloat(buttonX), height: CGFloat(scrollView.frame.size.height))
scrollView.backgroundColor = UIColor.clear
view.addSubview(scrollView)
}
func changeView(_ sender: UIButton)
{
print("I Clicked a button \(Int(sender.tag))")
}
Since you're already using tags it shouldn't be a problem. The changeView function should work like this:
func changeView(_ sender: UIButton)
{
let scrollView = sender.superview as! UIScrollView //This is mildly hacky - store your scroll view in an instance variable
for view in scrollView.subviews {
guard let button = view as? UIButton else {
continue
}
button.backgroundColor = sender.tag == button.tag ? UIColor.red : UIColor.black
}
}
Simple solution without tags.
Declare a property currentButton
weak var currentButton : UIButton?
In changeView reset the color of the currentButton, set the color of the sender and assign the sender to currentButton.
func changeView(_ sender: UIButton)
{
currentButton?.backgroundColor = .black
currentButton = sender
sender.backgroundColor = .red
}
Due to optional chaining the color of currentButton will not be set if currentButton is nil.
Keep a week property of type UIButton to temporally save the selected button.
weak var selectedButton: UIButton?
In the selector for your buttons make the color of the selectedButton to default, then change the color of the newly selected button and reset the selectedButton
#IBAction func actionTouchUpInside(sender: UIButton) {
if let selectedButton = self.selectedButton {
selectedButton.backgroundColor = UIColor.clear
}
sender.backgroundColor = UIColor.blue
selectedButton = sender
}

Selected/Clicked UIButton text title color need to change from number of buttons on scrollview programmatically

I added number of UIButtons on scrollview programmatically based on array count, until this much its working fine. Requirement is only selected button text title color should change into brown color remain are blue. I can’t able to solve this one please some one help using Swift 3. I need only the selected or clicked button text title color need to change remain all are in rest of the color.
for titles in arrayPageTitles {
var titleSize: CGSize = (titles as AnyObject).size(attributes: [NSFontAttributeName: UIFont.systemFont(ofSize: 14.0)])
titleSize = CGSize(width: CGFloat(ceilf(Float(titleSize.width))), height: CGFloat(ceilf(Float(titleSize.height))));
/**
creating top page strip tab Buttons
*/
buttonTitle = UIButton(type: UIButtonType.custom)
buttonTitle = UIButton(frame: CGRect(x: buttonPositionX + 5, y: 10, width: titleSize.width+40, height: (scrollViewTop?.frame.size.height)! - 20))
buttonTitle.setTitle(titles, for: .normal)
buttonTitle.setTitleColor(UIColor.blue, for: .normal)
buttonTitle.setTitleColor(UIColor.white, for: .selected
buttonTitle.clipsToBounds = true
buttonTitle.layer.masksToBounds = true
buttonTitle.layer.cornerRadius = 17
buttonTitle.layer.borderWidth = 1
buttonTitle.layer.borderColor = UIColor.darkGray.cgColor
buttonTitle.tag = increaseIndex
buttonTitle.addTarget(self, action: #selector(buttonTitleAction), for: .touchUpInside)
arrayTitleButtons .add(buttonTitle)
scrollViewTop?.addSubview(buttonTitle)
let currentButtonX:CGFloat = buttonPositionX
let buttonWidth:CGFloat = buttonTitle.frame.size.width
buttonPositionX = currentButtonX + buttonWidth + 10
if arrayPageTitles.first == titles {
viewLine.frame = CGRect(x: buttonTitle.frame.origin.x, y: buttonTitle.frame.origin.y, width: buttonTitle.frame.size.width, height: buttonTitle.frame.size.height)
viewLine.layer.cornerRadius = 17
viewLine.clipsToBounds = true
viewLine.layer.masksToBounds = true
viewLine.backgroundColor = UIColor.red
scrollViewTop?.addSubview(viewLine)
scrollViewTop?.addSubview(buttonTitle) // need to fix ... this add only first button
buttonTitle.setTitleColor(UIColor.white, for: .normal)
}
/**
creating collection views
*/
let storyBoard = UIStoryboard(name:"Main", bundle:nil)
let pageStripTypeViewController = storyBoard.instantiateViewController(withIdentifier: "kPageStripVC") as! FirstViewController
....
You could change the selection state of the sender in your #IBAction, as follows:
#IBAction func buttonAction(_ sender: UIButton) {
// create an array of buttons
var mybuttonArray: [UIButton] = view.subviews.filter{$0 is UIButton} as! [UIButton]
// filter it down to buttons that aren't the sender
mybuttonArray = mybuttonArray.filter{$0 != sender}
// figure out of it's selected
mybuttonArray.forEach({ button in
if button.isSelected {
// unselected it
button.isSelected = false
}
})
// select the sender's button
sender.isSelected = !sender.isSelected
// whatever else you need to
}
You need to pass the reference of the button when you create a selector so that you can compare with other buttons and change the isSelected state
buttonTitle.addTarget(self, action: #selector(ViewController.buttonTitleAction(_:)), for: .touchUpInside) //replace ViewController with your ViewController name
func buttonTitleAction(_ sender: UIButton) {
arrayTitleButtons.forEach { (button) in
if button == sender {
button.isSelected = true
sender.setTitleColor(UIColor.brown, for: .selected)
} else {
button.isSelected = false
}
}
}

How to change the title and action of a programmatically created UIButton on some condition

I have created a UIButton programmatically on my ViewController. I want to perform different actions on the same button depending on the condition and want to change the title as well.
First I create the button like this:
func createButton(buttonTitle: String,buttonAction: Selector) -> UIButton{
let button = UIButton(type: UIButtonType.System) as UIButton
button.frame = CGRectMake(0, 0, 414, 65)
button.setTitle(buttonTitle, forState: UIControlState.Normal)
button.addTarget(self, action:buttonAction, forControlEvents: UIControlEvents.TouchUpInside)
button.setTitleColor(UIColor.whiteColor(), forState:UIControlState.Normal)
button.titleLabel?.font = UIFont(name: Variables.MONTESERRAT_REGULAR, size: 20.0)
button.backgroundColor = UIColor().blueColor() //top
button.titleEdgeInsets = UIEdgeInsetsMake(0.0,10.0, 10.0, 0.0)
return button
}
Then I am showing like this
override func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let footerView = UIView(frame: CGRectMake(0, 0, tableView.frame.size.width, tableView.frame.size.height))
if(active == true){
bottomButton = createButton("UNPUBLISH", buttonAction: "unPublishToServer")
}else if(active == false){
bottomButton = createButton("PUBLISH", buttonAction: "publishToServer")
}else{
bottomButton = createButton("Request", buttonAction: "requestItem")
}
footerView.addSubview(bottomButton!)
return footerView
}
then on certain messages from server or conditions I am changing the button like this
func publishTripToServer(){
dispatch_async(dispatch_get_main_queue()) {
self.bottomButton?.setTitle("UNPUBLISH", forState: UIControlState.Normal)
}
}
func unPublishTripToServer(){
dispatch_async(dispatch_get_main_queue()) {
self.bottomButton?.setTitle("PUBLISH", forState: UIControlState.Normal)
}
}
The problem I am having is first it shows some background color behind the title when I click publish or unpublish. the second issue is button is not changing the action.
I'm not exactly sure what you mean for the background color issue.
But for your button, does something like this not work?
func publishTripToServer(){
self.bottomButton = createButton("UNPUBLISH", buttonAction: "unPublishToServer")
}
func unPublishTripToServer(){
self.bottomButton = createButton("PUBLISH", buttonAction: "publishToServer")
}
I don't know why you previously were trying to update the button title on the background thread, but you shouldn't ever update ui elements asynchronously.
And the reason your button action wasn't changing is that you never told it to change - you just changed the title

Resources