I'm creating voice collection app separated 4 genres(I control genres by using switch statement).You can choose one in four genres in segmentedcontroll and change buttons shown above segmentedcontroll. And I'm creating Buttons by using double for statement.
When changing genres and updating Button I coded like
loadView()
viewDidLoad()
to update buttons.But that update banner ads(disappear and appear again)
as well.How can I stop updating banner ads?.Sorry for my poor English and messy code.Thank you.
I used addsubView but which didn't work.
//this is a part of whole code
import UIKit
import AVFoundation
import GoogleMobileAds
class ViewController: UIViewController{
var spaceForiPhoneX = 0
var fontOfText = 9
var adView:UIWindow! = UIWindow()
var admobView:GADBannerView!
var window:UIWindow!
// true:テスト
let AdMobTest:Bool = true
var player = AVAudioPlayer()
var buttonArray:[UIButton]!
var currentArray:[String] = []
var first = true
override var prefersStatusBarHidden: Bool{
return true
}
lazy var buttonSegmentedControl: UISegmentedControl = {
let sc = UISegmentedControl(items: ["outou","outou2","bougen","meigen"])
sc.translatesAutoresizingMaskIntoConstraints = false
sc.tintColor = UIColor.white
sc.selectedSegmentIndex = 0
sc.addTarget(self, action: #selector(handleButtonsChange), for: .valueChanged)
return sc
}()
#objc func handlebuttonsChange(){
switch buttonSegmentedControl.selectedSegmentIndex {
case 0:
currentArray = outou
case 1:
currentArray = outou2
case 2:
currentArray = bougen
case 3:
currentArray = meigen
default:
print("not selected")
}
loadView()
viewDidLoad()
}
override func viewDidLoad() {
super.viewDidLoad()
if(first) {
currentArray = reloadViewController.outou
first = false
print("Google Mobile Ads SDK version: \(GADRequest.sdkVersion())")
var admobView = GADBannerView()
admobView = GADBannerView(adSize:kGADAdSizeBanner)
// iPhone X のポートレート決め打ちです
admobView.frame.origin = CGPoint(x:0, y:self.view.frame.size.height - admobView.frame.height + CGFloat(spaceForiPhoneX))
admobView.frame.size = CGSize(width: self.view.frame.width, height:admobView.frame.height)
admobView.adUnitID = TEST_ID
admobView.rootViewController = self
admobView.load(GADRequest())
navigationItem.titleView?.addSubview(admobView)
}
view.backgroundColor = UIColor(r: 61, g: 91, b: 151)
let numberOfrows = 6
let numberOfLines = 3
var count = 0
var buttonArray:[UIButton] = []
let sizeOfButton = view.frame.height / 10
let widthOfSpace = ((view.frame.width - sizeOfButton * 4) / 5 )
forloop : for row in 0 ... numberOfrows {
for line in 0 ... numberOfLines {
let button = UIButton(type: .custom)
button.backgroundColor = UIColor(r: 1, g: 101, b: 161)
button.setTitleColor(UIColor.white, for: .normal)
button.titleLabel?.numberOfLines = 0
button.setTitle(currentArray[row * 4 + line], for: .normal)
button.frame = CGRect(x: (widthOfSpace + sizeOfButton) * CGFloat(line) + widthOfSpace, y: view.frame.height / 9.3 * CGFloat(row) + 50, width: sizeOfButton ,height: sizeOfButton )
button.layer.cornerRadius = 10
button.layer.borderColor = UIColor.white.cgColor
button.layer.borderWidth = 1
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: CGFloat(fontOfText))
button.tag = row * 4 + line
button.addTarget(self, action: #selector(buttonPushed), for:.touchUpInside)
button.showsTouchWhenHighlighted = true
buttonArray.append(button)
count += 1
if (count == currentArray.count) {break forloop}
}
}
for button in buttonArray{
view.addSubview(button)
}
view.addSubview(buttonSegmentedControl)
setupbuttonSegmentedControl()
}
#objc func buttonPushed(button : UIButton){
let audioPath = Bundle.main.path(forResource: currentArray[button.tag], ofType: "mp3")
do {
try player = AVAudioPlayer(contentsOf: URL(fileURLWithPath: audioPath!))
player.play()
}catch{
print(error)
}
}
func setupbuttonSegmentedControl(){
buttonSegmentedControl.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
buttonSegmentedControl.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -90).isActive = true
buttonSegmentedControl.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -24).isActive = true
buttonSegmentedControl.heightAnchor.constraint(equalToConstant: 60).isActive = true
}
You should never call loadView and viewDidLoad by yourself. This is even mentioned in the documentation.
Extract the button update part from viewDidLoad to a separate method and call that method instead.
For example:
Declare an instance variable to store the buttons:
private var buttons: [UIButton] = []
And extract the update code into a method:
private func updateButtons() {
for buttons in buttons {
button.removeFromSuperview()
}
let numberOfrows = 6
let numberOfLines = 3
var count = 0
buttons = []
let sizeOfButton = view.frame.height / 10
let widthOfSpace = ((view.frame.width - sizeOfButton * 4) / 5 )
forloop : for row in 0 ... numberOfrows {
for line in 0 ... numberOfLines {
let button = UIButton(type: .custom)
button.backgroundColor = UIColor(r: 1, g: 101, b: 161)
button.setTitleColor(UIColor.white, for: .normal)
button.titleLabel?.numberOfLines = 0
button.setTitle(currentArray[row * 4 + line], for: .normal)
button.frame = CGRect(x: (widthOfSpace + sizeOfButton) * CGFloat(line) + widthOfSpace, y: view.frame.height / 9.3 * CGFloat(row) + 50, width: sizeOfButton ,height: sizeOfButton )
button.layer.cornerRadius = 10
button.layer.borderColor = UIColor.white.cgColor
button.layer.borderWidth = 1
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: CGFloat(fontOfText))
button.tag = row * 4 + line
button.addTarget(self, action: #selector(buttonPushed), for:.touchUpInside)
button.showsTouchWhenHighlighted = true
buttons.append(button)
count += 1
if (count == currentArray.count) {break forloop}
}
}
for button in buttons {
view.addSubview(button)
}
}
Call this method from both viewDidLoad and from handlebuttonsChange.
By the way, note that the code could be significantly simplified and ideally you should use UICollectionView instead.
Related
There is a UIImage inside the MainViewController as seen in the picture. There is also a button in TabBarViewController. When I press the button, I want the impulse animation I wrote for the UIView to start and stop.When i click to play button animation is not started. How can I do this?
Thanks.
enter image description here
Here is my code;
class MainViewObject: UIView {
//Center Image View Container
lazy var centerContainerView: UIView = {
let view = UIView()
view.backgroundColor = .white
view.layer.cornerRadius = 113
view.backgroundColor = Colors.lightOrangeColor
return view
}()
}
class TabbarViewController: UITabBarController {
var object: MainViewObject!
//Create Play Button
let middleButton: UIButton = {
let btn = UIButton(frame: CGRect(x: (UIScreen.main.bounds.width / 2) - 32, y: -8, width: 65, height: 65))
btn.setImage(UIImage(named: "play"), for: UIControl.State.normal)
btn.layer.shadowColor = UIColor.black.cgColor
btn.layer.shadowOpacity = 0.1
btn.layer.shadowOffset = CGSize(width: 4, height: 4)
btn.backgroundColor = Colors.mainColor
btn.layer.cornerRadius = 32
btn.tintColor = UIColor.clear
btn .addTarget(self, action:#selector(menuButtonAction), for: .touchUpInside
return btn
}()
//Play Pause Button Function
#objc func menuButtonAction(sender: UIButton) {
sender.isSelected = !sender.isSelected
if sender.isSelected {
middleButton.setImage(UIImage(named: "pause"), for: UIControl.State.normal)
playRadio()
pulseAnimationStart()
}else{
middleButton.setImage(UIImage(named: "play"), for: UIControl.State.normal)
player!.pause()
pulseAnimationStop()
}
}
}
extension TabbarViewController {
//Main Page Main Image Pulse Animation Start
func pulseAnimationStart() {
let fadingAnimation = CABasicAnimation(keyPath: "opacity")
fadingAnimation.fromValue = 1
fadingAnimation.toValue = 0
let expandingAnimation = CABasicAnimation(keyPath: "transform.scale")
expandingAnimation.fromValue = 1
expandingAnimation.toValue = 1.1
let animationGroup = CAAnimationGroup()
animationGroup.animations = [expandingAnimation,
fadingAnimation]
animationGroup.duration = 1.5
animationGroup.repeatCount = .infinity
self.object.centerContainerView.layer.add(animationGroup, forKey: "pulse")
}
//Main Page Main Image Pulse Animation Stop
func pulseAnimationStop() {
UIView.animate(withDuration: 0.0) {
self.object.centerContainerView.layer.removeAllAnimations()
}
}
}
I have create 2 buttons using loop. Also I have addTarget for them in same loop. But target for button at index 0 is never called, while it is called everytime for button at index 1. Here is my code
let buttonTitles = ["GIFs","Stickers"]
let enumberatedTitles = buttonTitles.enumerated()
var originX: CGFloat = 2.5
var buttonWidth = 100
self.containerView.frame.size.width = CGFloat(buttonTitles.count) * buttonWidth + 5
self.containerView.frame.size.height = 50
self.containerView.center.x = self.frame.width/2
self.containerView.center.y = self.frame.height/2
for(index,item) in enumberatedTitles {
var button = UIButton()
button.setTitle(item, for: .normal)
button.setTitleColor(.white, for: .normal)
button.backgroundColor = .clear
button.frame.origin.x = originX
button.frame.origin.y = 2.5
button.frame.size.width = buttonWidth
button.frame.size.height = 45
button.tag = index
button.accessibilityHint = item
button.addTarget(self, action: #selector(buttonPressed(sender:)), for: .touchUpInside)
self.containerView.addSubview(button)
originX += longestLabelWidth
}
Target for button
#objc private func buttonPressed(sender: UIButton) {
if let touchedButton = self.containerView.subviews.first(where: {
$0.tag == sender.tag
}) {
self.selectedView.frame = touchedButton.frame
}
}
I have a list of category add I created buttons for each category in a scroll view
and a last button is ALL button for all products. But some how it didn't have any action I added.
this is my code
First I make a function to create buttons to add to view
func catButtonView(buttonSize:CGSize) -> UIView {
let buttonView = UIView()
buttonView.backgroundColor = UIColor(colorLiteralRed: 1, green: 1, blue: 1, alpha: 0)
buttonView.frame.origin = CGPoint(x: 0,y: 0)
let padding = CGSize(width:0, height:0)
buttonView.frame.size.width = (buttonSize.width + padding.width) * CGFloat(categories.count)
buttonView.frame.size.height = (buttonSize.height + 2.0 * padding.height )
//add buttons to the view
var buttonPosition = CGPoint(x:padding.width * 0.5, y:padding.height)
let buttonIncrement = buttonSize.width + padding.width
let hueIncrement = 1.0 / CGFloat(categories.count)
var newHue = hueIncrement
for i in 0...(categories.count) {
let button = UIButton.init(type: .custom) as UIButton
button.frame.size = buttonSize
button.frame.origin = buttonPosition
button.setBackgroundImage(R.image.button(), for: .normal)
button.setBackgroundImage(R.image.button_selected(), for: .selected)
if(i==categories.count) {
button.setTitle("ALL", for: .normal)
} else {
button.setTitle(categories[i].name, for: .normal)
}
button.setTitleColor(UIColor.white, for: .normal)
buttonPosition.x = buttonPosition.x + buttonIncrement
newHue = newHue + hueIncrement
button.tag = i+1
button.addTarget(self, action: #selector(catButtonPressed(sender:)), for: .touchUpInside)
buttonView.addSubview(button)
}
return buttonView
}
this is action func
func catButtonPressed(sender:UIButton){
print(sender.tag)
if(self.selectedCat != sender.tag-1) {
let lastBtn = catScrollView.viewWithTag(selectedCat+1) as? UIButton
lastBtn?.setBackgroundImage(R.image.button(), for: .normal)
self.selectedCat = sender.tag-1
self.itemsCollection.reloadData()
sender.setBackgroundImage(R.image.button_selected(), for: .normal)
}
}
then add to scroll view
let catScrollingView = catButtonView(buttonSize: CGSize(width: 200.0, height:50.0))
catScrollView.contentSize = catScrollingView.frame.size
catScrollView.subviews.forEach({ $0.removeFromSuperview() })
catScrollView.addSubview(catScrollingView)
catScrollView.showsHorizontalScrollIndicator = true
catScrollView.indicatorStyle = .default
self.itemsCollection.reloadData()
Anyone know what I missed?
It is because the if statement in your catButtonPressed function is false with the last button's tag, which makes the code inside never be executed.
Let's say you have 5 categories so your categories.count = 5. So your self.selectedCat ranges from 0 to 4. In your for i in 0...(categories.count) the last button's tag is button.tag = 5
Now in your catButtonPressed function. If the last button is the last category, then your self.selectedCat will be 4 and sender.tag will be 5
func catButtonPressed(sender:UIButton){
print(sender.tag)
if(4 != 5-1) {
// Any code in here will never be executed because 4 != 4 is false
}
}
sorry,I have a problem.I don't use storyBoard.
I want to make a view like this.
photo by terenceLuffy/AppStoreStyleHorizontalScrollView
but I try to do this.
Finlly,scrollView just show last button like this.
This is code:
var scView:UIScrollView = UIScrollView()
var buttonPadding:CGFloat = 10
var xOffset:CGFloat = 10
scView.backgroundColor = UIColor.blue
scView.translatesAutoresizingMaskIntoConstraints = false
func viewDidLoad() {
for i in 0 ... 10 {
let button = UIButton()
button.tag = i
button.backgroundColor = UIColor.darkGray
button.setTitle("\(i)", for: .normal)
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
scView.addSubview(button)
}
scView.contentSize = CGSize(width: xOffset, height: scView.frame.height)
}
please help me.
Thanks all!
There are two ways of achieving it :) One the hard way using scrollView and calculating offset and setting views programmatically on ScrollView as subView else use CollectionView
Step 1:
Add a UICollectionView to storyboard, set the height of collectionView to match your requirement :)
Step 2
Create a cell, size of which depends on your requirement. I have created a cell with background colour orange/pink. Added a label on it to show your number.
Step 3:
Set the reusable cell identifier to the cell and set its class as well :)
Step 4 :
Set collectionView scroll direction to horizontal :)
Step 5:
Now implement collectionView delegates and data source methods :)
extension ViewController : UICollectionViewDataSource,UICollectionViewDelegate {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "myCell", for: indexPath) as! MyCollectionViewCell
cell.myLabel.text = "ABCD"
return cell;
}
}
Thats all :)
Final O/P
Look at collectionView with cell ABCD :D
Additional Info
If you are dragging a collectionView on UIViewController, you might see that the collectionView leaves a gap at the top which you can solve by unchecking Adjust ScrollView Insets of ViewController :)
I have tried your code and changed it a bit. It works as expected, unless you have something other going on:
var scView:UIScrollView!
let buttonPadding:CGFloat = 10
var xOffset:CGFloat = 10
override func viewDidLoad() {
super.viewDidLoad()
scView = UIScrollView(frame: CGRect(x: 0, y: 120, width: view.bounds.width, height: 50))
view.addSubview(scView)
scView.backgroundColor = UIColor.blue
scView.translatesAutoresizingMaskIntoConstraints = false
for i in 0 ... 10 {
let button = UIButton()
button.tag = i
button.backgroundColor = UIColor.darkGray
button.setTitle("\(i)", for: .normal)
//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
scView.addSubview(button)
}
scView.contentSize = CGSize(width: xOffset, height: scView.frame.height)
}
import UIKit
class ViewController: UIViewController {
var imageStrings:[String] = []
var myScrollView:UIScrollView!
#IBOutlet weak var previewView: UIImageView!
var scrollWidth : CGFloat = 320
let scrollHeight : CGFloat = 100
let thumbNailWidth : CGFloat = 80
let thumbNailHeight : CGFloat = 80
let padding: CGFloat = 10
override func viewDidLoad() {
super.viewDidLoad()
imageStrings = ["image01","image02","image03","image04","image05","image06","image07","image08"]
scrollWidth = self.view.frame.width
//setup scrollView
myScrollView = UIScrollView(frame: CGRectMake(0, self.view.frame.height - scrollHeight, scrollWidth, scrollHeight))
//setup content size for scroll view
let contentSizeWidth:CGFloat = (thumbNailWidth + padding) * (CGFloat(imageStrings.count))
let contentSize = CGSize(width: contentSizeWidth ,height: thumbNailHeight)
myScrollView.contentSize = contentSize
myScrollView.autoresizingMask = UIViewAutoresizing.FlexibleWidth
for(index,value) in enumerate(imageStrings) {
var button:UIButton = UIButton.buttonWithType(.Custom) as! UIButton
//calculate x for uibutton
var xButton = CGFloat(padding * (CGFloat(index) + 1) + (CGFloat(index) * thumbNailWidth))
button.frame = CGRectMake(xButton,padding, thumbNailWidth, thumbNailHeight)
button.tag = index
let image = UIImage(named:value)
button.setBackgroundImage(image, forState: .Normal)
button.addTarget(self, action: Selector("changeImage:"), forControlEvents: .TouchUpInside)
myScrollView.addSubview(button)
}
previewView.image = UIImage(named: imageStrings[0])
self.view.addSubview(myScrollView)
}
// Do any additional setup after loading the view, typically from a nib.
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func changeImage(sender:UIButton){
let name = imageStrings[sender.tag]
previewView.image = UIImage(named: name)
}
}
Its easy with minimal use of storyboard. You can avoid that rather easily. All you need are:
Scroll view
Horizontal stack view
Set the constraints of the above as shown in the project
A number of buttons - as many view controllers that need to be displayed.
A container view - this will be the view that will hold the active view controller.
Please refer to this project for some sample code:
https://github.com/equitronix/horizontalScrollMenu
//make that variable gloabl
let button = UIButton.init(type: .custom)
var arrMmenu : NSMutableArray = []
var selectedIndex : Int = 0
#IBOutlet weak var btnScrollView: UIScrollView!
var lineArray : NSMutableArray = []
var buttonArray : NSMutableArray = []
//Call buttonCreated()
//MARK:- Create an Horizontral LayOut
func buttonCreated()
{
btnScrollView.contentSize.width = 0
namesOfMenu = ["GMC","GPA","GTL"]
var scrollwidth: CGFloat = 10.0
for j in 0..<namesOfMenu.count
{
let name = namesOfMenu[j] as! String
let size : CGSize? = name.size(withAttributes : [NSAttributedStringKey.font : UIFont.systemFont(ofSize: 10.0)])
let textsize = CGSize(width : CGFloat(ceilf(Float(size!.width))), height : CGFloat(ceilf(Float(size!.height))))
var strikwidth : CGFloat = textsize.width
strikwidth = textsize.width + 30
let frame = CGRect(x: scrollwidth , y : CGFloat(7),width :CGFloat(strikwidth + 20) , height :CGFloat(20))
let frameLine = CGRect(x: scrollwidth , y : CGFloat(30),width :CGFloat(strikwidth + 20) , height :CGFloat(2))
let button = UIButton(type: .custom)
let line = UIView()
line.frame = frameLine
button.tag = j
view.tag = j
button.frame = frame
line .backgroundColor = UIColor.red
button.backgroundColor = UIColor.red
button.setTitleColor(UIColor.white, for: UIControlState.normal)
button.layer.borderColor = UIColor.white.cgColor
button.titleLabel?.textAlignment = .center
button.addTarget(self, action: #selector(self.buttonEvent(_:)), for: .touchUpInside)
button.setTitle(name, for : .normal)
scrollwidth = scrollwidth + strikwidth + 30
let strofMenu = namesOfMenu[selectedIndex] as! String
if (j == selectedIndex)
{
if(strofMenu == "GMC")
{
// apicall()
}
line.backgroundColor = hexStringToUIColor(hex: "#3174C7")
button.backgroundColor = UIColor.clear
button.setTitleColor(hexStringToUIColor(hex: "#3174C7"), for: UIControlState.normal)
}else
{
line.backgroundColor = UIColor.clear
button.backgroundColor = UIColor.clear
button.setTitleColor(MyConstant.Color.dark_gray_shade, for: UIControlState.normal)
}
button.titleLabel?.font = MyConstant.fontApp.Regular
buttonArray.add(button)
lineArray.add(line)
btnScrollView.addSubview(button)
btnScrollView.addSubview(line)
}
btnScrollView.contentSize = CGSize(width : CGFloat(scrollwidth), height : CGFloat(40.0))
btnScrollView.isPagingEnabled = false
btnScrollView.showsHorizontalScrollIndicator = false
btnScrollView.showsVerticalScrollIndicator = false
}
//MARK:- Button Event
#objc func buttonEvent(_ sender : UIButton)
{
let index = sender.tag
selectedIndex = index
let getRepoName = namesOfMenu[index] as! String
print(getRepoName)
for i in 0..<buttonArray.count
{
let buttonone : UIButton = (buttonArray[i] as! UIButton)
let line : UIView = (lineArray[i]) as! UIView
if i == selectedIndex
{
buttonone.backgroundColor = UIColor.clear
line.backgroundColor = hexStringToUIColor(hex: "#3174C7")
buttonone.setTitleColor(hexStringToUIColor(hex: "#3174C7"), for: .normal)
//
// if(getRepoName == "GMC")
// {
// clickedCellIndexes.add(0)
//
// arrmutablefordata.removeAllObjects()
// tblhome.reloadData()
// apicall()
// }
//buttonone.titleLabel
}else
{
buttonone.backgroundColor = UIColor.clear
line.backgroundColor = UIColor.clear
buttonone.setTitleColor(MyConstant.Color.dark_gray_shade, for: .normal)
}
}
}
Doing it from the storyboard using scroll view and stack views makes this a very simple solution. Along with a bunch of sub view controllers and transitions. I have posted sample code on GitHub. Please take a look here:
https://github.com/equitronix/horizontalScrollMenu
Let me know if this works.
I have the following buttons which are adding dynamically based on some condition. Now i need to change all added buttons behaviour as radio buttons. so that I can do some actions based on the selection..
var posX = 0
var posY = 0
if trim.contains("0"){
print("contaim 0")
let button1 = UIButton(frame: CGRect(x: posX, y: posY, width: 60, height: 20))
button1.setTitleColor(UIColor.blackColor(), forState: .Normal)
button1.setTitle("No", forState: .Normal)
button1.setImage(UIImage(named: "checkbox untick.png")!, forState: .Normal)
button1.addTarget(self, action: #selector(buttonAction), forControlEvents: .TouchUpInside)
myStackview.addSubview(button1)
posX = 60
}
if trim.contains("1") {
print("contaim 1")
let button2 = UIButton(frame: CGRect(x: posX, y: posY, width: 60, height: 20))
button2.setTitleColor(UIColor.blackColor(), forState: .Normal)
button2.setTitle("Less", forState: .Normal)
button2.setImage(UIImage(named: "checkbox untick.png")!, forState: .Normal)
button2.addTarget(self, action: #selector(buttonAction), forControlEvents: .TouchUpInside)
myStackview.addSubview(button2)
posX = posX + 60
}
if trim.contains("2"){
print("contaim 2")
let button3 = UIButton(frame: CGRect(x: posX, y: posY, width: 60, height: 20))
button3.setTitleColor(UIColor.blackColor(), forState: .Normal)
button3.setTitle("Half", forState: .Normal)
button3.setImage(UIImage(named: "checkbox untick.png")!, forState: .Normal)
button3.addTarget(self, action: #selector(buttonAction), forControlEvents: .TouchUpInside)
myStackview.addSubview(button3)
posX = posX + 60
}
I have set the buttonAction methods as below buts its not working
func buttonAction(sender: UIButton!) {
print("Button tapped")
sender.setImage(UIImage(named: "checkboxredtick.png")!, forState: .Normal)
}
let buttons = [UIButton]()
// create button1
let button1 = UIButton(frame: CGRect(x: posX, y: posY, width: 60, height: 20))
button1.setTitleColor(UIColor.blackColor(), forState: .Normal)
button1.setTitle("No", forState: .Normal)
button1.setImage(UIImage(named: "checkbox untick.png")!, forState: .Normal)
// if the selected button cannot be reclick again, you can use .Disabled state
button1.setImage(UIImage(named: "checkboxredtick.png")!, forState: .Selected)
button1.addTarget(self, action: #selector(buttonAction), forControlEvents: .TouchUpInside)
myStackview.addSubview(button1)
buttons.append(button1)
// create other buttons and add into buttons ...
func buttonAction(sender: UIButton!){
for button in buttons {
button.selected = false
}
sender.selected = true
// you may need to know which button to trigger some action
// let buttonIndex = buttons.indexOf(sender)
}
In case anyone finds this useful. Here is an example of how I use DLRadioButton library (https://github.com/DavydLiu/DLRadioButton) to create RadioButtons dynamically.
You can check a complete small project to show a working code in here https://github.com/omhack/DynamicRadioButtons
import UIKit
import DLRadioButton
//Delegate to manage the Polls
protocol QuestionsDialogDelegate : class{
func questionsAnswered(polls: [Poll])
}
class QuestionsDialog: UIViewController {
#IBOutlet weak var stackView: UIStackView!
#IBOutlet var rootView: UIView!
#IBOutlet weak var nestedView: UIView!
weak var delegate: QuestionsDialogDelegate?
var questions : [Question]!
var polls = [Poll]()
var serviceType : Int = 0
var indexView : Int = 0
override func viewDidLoad() {
super.viewDidLoad()
//setting the stack view properties
stackView.alignment = UIStackViewAlignment.leading
stackView.axis = .vertical
}
//this is where the heavy logic, to create the dynamic radio buttons takes place
func showQuestions(){
if(questions.count <= 1){
rootView.frame.size.height = 200
nestedView.frame.size.height = 200
}else{
rootView.frame.size.height = 400
nestedView.frame.size.height = 400
}
for question in questions{
var otherButtons : [DLRadioButton] = []
let frame1 = CGRect(x: self.view.frame.size.width / 2 - 131, y: 350, width: 262, height: 17);
//we create a base radio button to use it as an anchor view
let firstRadioButton = createRadioButton(frame: frame1, title: "", color: UIColor.purple);
let label = UILabel()
label.textAlignment = .center
label.font = UIFont.boldSystemFont(ofSize: 17.0)
label.textColor = UIColor.darkGray.withAlphaComponent(0.85)
label.adjustsFontSizeToFitWidth = true
label.minimumScaleFactor = 0.25
label.frame = CGRect(x: 0, y: 0, width: 200, height: 30)
label.text = question.question
self.stackView.insertArrangedSubview(label, at: self.indexView)
self.indexView += 1
let poll = Poll()
poll.idQuestion = question.idQuestion
var i = 0;
for answer in question.answers{
let frame = CGRect(x: self.view.frame.size.width / 2 - 131, y: 380 + 30 * CGFloat(i), width: 300, height: 17);
let radioButton = createRadioButton(frame: frame, title: answer.answer! + " ", color: UIColor.purple)
radioButton.tag = answer.idAnswer
radioButton.params["poll"] = poll
otherButtons.append(radioButton)
self.stackView.insertArrangedSubview(radioButton, at: self.indexView)
i += 1;
self.indexView += 1
}
firstRadioButton.otherButtons = otherButtons
firstRadioButton.isHidden = true
firstRadioButton.otherButtons[1].isSelected = true
}
}
//Method to create a custom button
private func createRadioButton(frame : CGRect, title : String, color : UIColor) -> MyDLUIButton {
let radioButton = MyDLUIButton(frame: frame);
radioButton.titleLabel?.translatesAutoresizingMaskIntoConstraints = false
radioButton.titleLabel!.font = UIFont.systemFont(ofSize: 14);
radioButton.setTitle(title, for: []);
radioButton.setTitleColor(UIColor.darkGray, for: []);
radioButton.iconColor = color;
radioButton.indicatorColor = color;
radioButton.contentHorizontalAlignment = UIControlContentHorizontalAlignment.left;
radioButton.addTarget(self, action: #selector(QuestionsDialog.selectedAnswer(_:)), for: UIControlEvents.touchUpInside)
self.view.addSubview(radioButton);
return radioButton;
}
#objc func selectedAnswer(_ sender: MyDLUIButton){
let poll = sender.params["poll"] as? Poll
poll?.idAnswer = sender.tag
if let row = self.polls.index(where: {$0.idQuestion == poll?.idQuestion}) {
self.polls[row] = poll!
}else{
self.polls.append(poll!)
}
print("polls size: \(self.polls.count)")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func viewDidDisappear(_ animated: Bool) {
if(self.polls.count < self.questions.count){
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "questionsDialogDismissed"), object: nil)
}
}
#IBAction func requestService(_ sender: UIButton) {
delegate?.questionsAnswered(polls: self.polls)
}
}
class MyDLUIButton: DLRadioButton{
var params: Dictionary<String, Any>
override init(frame: CGRect) {
self.params = [:]
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
self.params = [:]
super.init(coder: aDecoder)
}
}
I would create a tag for every UIButton, then add your UIButton to be send to your ButtonAction:
button.tag = 0
button.addTarget(object, action: #selector(YourViewController.buttonAction(_:)),
forControlEvents: .TouchUpInside)
func buttonAction(sender: UIButton!) {
let selectedButton = sender as! UIButton
print(selectedButton.tag) // here stands the correct button which is pressed
}
You could also create an Array containing all Buttons, for example:
let myButtons = [UIButton]()
let button1 = UIButton()...
button1.tag = 0
myButtons.add(button1)
And now change it like this way:
myButtons[0].setImage(.....)
Where 0 is your first button (so with tag 0) // you should set your tags in the same order in which you append it to your myButtons Array.