I'm sorry but if I have a number of buttons that comes from a plist file ...
how do I re-create all the buttons?
Example I tried in this way :
func loadSavedButtons() {
// I extract the number from the plist file
var number: AnyObject? = data.valueForKey("NumberOfButton")
var someNumb: Int = ("\(number!)").toInt()!
if (someNumb != 0) {
self.countButton = someNumb
for (var i=0; i < someNumb; i++) {
In This Point I should do
var newButton6: () = CreateButtonWithIndex(i)
self.view.addSubview(newButton6)
}}}
and
#IBAction func CreateButtonWithIndex(sender: AnyObject){
let button = UIButton.buttonWithType(UIButtonType.System) as UIButton
ecc…
self.view.addSubview(button)
but don't go ... i don't have all save button please help me !!!
In your function
Change the following
let button = UIButton.buttonWithType(UIButtonType.System) as UIButton
to
var button = UIButton.buttonWithType(UIButtonType.System) as UIButton
then after
self.view.addSubview(button)
add the following:
button = UIButton.new()
Related
I am using .animationImages for UIImageViews in my project (it's a game). When the user presses a hint button I programmatically create a variable number of UIImageViews that will appear on screen and play the same image sequence once. I need to remove the UIImageViews from the view when the animation has stopped but I can't figure out how to do this.
I've been through the swift documentation for both .animationImages and .startAnimating but it's literally one paragraph and one line, neither of which is in relation to a completion or finish notifications etc. Any help will be much appreciated.
private func hideAnswerButtonsHint() {
// Clear all of the answer boxes that aren't hint locked
resetAnswerBoxes()
var imageArray = [UIImage]()
var remainingLetters = [String]()
for imageCount in 1...8 {
let imageName = "green_smoke_puff_0\(imageCount)"
let image = UIImage(named: imageName)!
imageArray.append(image)
}
for answerBox in answerBoxArray where answerBox.hintLock == false {
if let letter = answerBoxDict[answerBox.tag] {
remainingLetters.append(letter)
}
}
for answerButton in answerButtonArray where answerButton.hintLock == false {
if let index = remainingLetters.index(of: answerButton.titleText) {
answerButton.decompress()
remainingLetters.remove(at: index)
} else {
let frame = answerButton.superview?.convert(answerButton.frame.origin, to: nil)
let imageView = UIImageView()
imageView.animationImages = imageArray
imageView.animationDuration = 0.5
imageView.animationRepeatCount = 1
imageView.frame = CGRect(x: frame!.x, y: frame!.y, width: answerButton.frame.width, height: answerButton.frame.height)
view.addSubview(imageView)
imageView.startAnimating()
answerButton.compress()
answerButton.hintLock = true
}
}
}
UIImageView is an NSObject so you can always use KVO to watch its properties:
var observation: NSKeyValueObservation?
override func viewDidLoad() {
super.viewDidLoad()
observation = imageView.observe(\.isAnimating) { [weak self] imageView, change in
if let value = change.newValue,
value == true {
imageView.removeFromSuperview()
self?.observation = nil
}
}
}
open var buttonInit: ((_ index: Int) -> UIButton?)?
...
if let button: UIButton = self.buttonInit?(i) {
finButton = button
}else {
let button = UIButton(type: .custom)
button.setTitleColor(button.tintColor, for: [])
button.layer.borderColor = button.tintColor.cgColor
button.layer.borderWidth = 1
button.layer.cornerRadius = buttonHeight/2
finButton = button
}
I don't find any function description about buttonInit in AZDialogViewController. Does it mean button: UIButton = self.buttonInit?(i) will always be nil and finButton = button will not be executed?
The latter part of the code you quoted is in the setUpButton method:
fileprivate func setupButton(index i:Int) -> UIButton{
if buttonHeight == 0 {buttonHeight = CGFloat(Int(deviceHeight * 0.07))}
let finButton: UIButton
if let button: UIButton = self.buttonInit?(i) {
finButton = button
}else {
let button = UIButton(type: .custom)
button.setTitleColor(button.tintColor, for: [])
button.layer.borderColor = button.tintColor.cgColor
button.layer.borderWidth = 1
button.layer.cornerRadius = buttonHeight/2
finButton = button
}
This method is called here:
open func addAction(_ action: AZDialogAction){
actions.append(action)
if buttonsStackView != nil{
let button = setupButton(index: actions.count-1)
self.buttonsStackView.addArrangedSubview(button)
//button.frame = buttonsStackView.bounds
button.center = CGPoint(x: buttonsStackView.bounds.midX,y: buttonsStackView.bounds.maxY)
animateStackView()
}
}
From this we can see that buttonInit seems to be used to let the user of the library specify what kind of button they want as the action buttons. Another piece of evidence is that buttonInit is declared open, so it is likely that it is the client code who should set this, not the AZDialogViewController.
Plus, the README file showed this usage:
Use custom UIButton sub-class:
dialog.buttonInit = { index in
//set a custom button only for the first index
return index == 0 ? HighlightableButton() : nil
}
So to answer your question, the if branch will be executed if you set buttonInit.
#Huwell,
the documentation in the repository states to initialize the button in the following manner:
dialog.buttonInit = { index in
//set a custom button only for the first index
return index == 0 ? HighlightableButton() : nil
}
The button should be part of your DialogViewController.
I have the following code:
cell.rightButtons = [MGSwipeButton(title: "Save", backgroundColor:UIColor.redColor(),callback: {
(sender: MGSwipeTableCell!) -> Bool in
print("Saved")
return true
}))]
cell.rightSwipeSettings.transition = MGSwipeTransition.Rotate3D
return cell
This works fine but I want to change the title from "Save" to remove afterward. Tried it many different ways but doesn't seem to be working.
As explained in the official project: MGSwipeTableCell
you can obtain the button pressed by calling the delegate method:
-(BOOL) swipeTableCell:(MGSwipeTableCell*) cell tappedButtonAtIndex:(NSInteger) index direction:(MGSwipeDirection)direction fromExpansion:(BOOL) fromExpansion;
/**
* Delegate method to setup the swipe buttons and swipe/expansion settings
* Buttons can be any kind of UIView but it's recommended to use the convenience MGSwipeButton class
* Setting up buttons with this delegate instead of using cell properties improves memory usage because buttons are only created in demand
* #param swipeTableCell the UITableVieCel to configure. You can get the indexPath using [tableView indexPathForCell:cell]
* #param direction The swipe direction (left to right or right to left)
* #param swipeSettings instance to configure the swipe transition and setting (optional)
* #param expansionSettings instance to configure button expansions (optional)
* #return Buttons array
**/
In Swift you can write:
func swipeTableCell(cell: MGSwipeTableCell!, tappedButtonAtIndex index: Int, direction: MGSwipeDirection, fromExpansion: Bool) -> Bool {
if let button = cell.rightbuttons[index] {
print(button.titleLabel.text)
button.setTitle("Button Title", forState: UIControlState.Normal)
... (do whatever you want with your tapped button..)
}
}
To help you can launch the MGSwipeDemo project included in the bundle source, and add these lines in objective c like in this screenshots:
-(BOOL) swipeTableCell:(MGSwipeTableCell*) cell tappedButtonAtIndex:(NSInteger) index direction:(MGSwipeDirection)direction fromExpansion:(BOOL) fromExpansion
{
...
if (direction == MGSwipeDirectionRightToLeft && index == 1) {
NSLog(#"more pressed");
id button = cell.rightButtons[index];
UIButton *pressedBtn = button;
[pressedBtn setTitle:#"Less" forState:UIControlStateNormal];
NSLog(#"pressedBtn title: %#",pressedBtn.titleLabel.text);
}
...
}
P.S.: update: this part was added to help during comments:
About your personal project you must add to your datasource any boolean var, i make an example (in Swift code):
Class rowData{
var title: String! = String()
var subTitle:String! = String()
var button1Title : String! = String()
var button2Title : String! = String()
var isSaved : Bool! = false
}
var myDataSource : [rowData]! = [rowData]()
So, when you had populate your datasource you can use the delegate:
func swipeTableCell(cell: MGSwipeTableCell!, tappedButtonAtIndex index: Int, direction: MGSwipeDirection, fromExpansion: Bool) -> Bool {
...
if (direction == MGSwipeDirection.RightToLeft && index == 2){
if let _= cell?.rightButtons[index]{
let cellData:rowData = myDataSource[index]
if cellData.isSaved {
cellData.buttonTitle1 = "Just saved"
cellData.isSaved = true
} else {
cellData.buttonTitle1 = "Save"
cellData.isSaved = false
}
myDataSource[index] = cellData
// datasource is modified so launch reload data to refresh layout and call cellForRow..
// There are other softly methods than reloadData to update tableView layout but I use it just for example..
self.tableView.reloadData()
}
}
...
}
I would like to know if it's possible to create a custom background for a textfield using swift, for example expecting 4 letters, the textfield has 4 square. thx
Do you mean like this?
// Background
txtField.backgroundColor = UIColor.greenColor()
// Placeholder
txtField.placeholder = "1"
// Corner radius
txtField.layer.cornerRadius = 8
// A Boolean indicating whether sublayers are clipped to the layer’s bounds
txtField.layer.masksToBounds = true
UPDATE
Here is a method that will randomize a number and then create textfields according to the number that has been generated. You don´t need the random functionality of course if you already have a number. The only thing you have to do is change for var i = 0; i < rand; i++ rand to your variable. The textFieldEditingChanged function is the event when the users tries to add a new character to the textField and there is a check to only allow one character in each textField.
let rand = Int(arc4random_uniform(10) + 2)
for var i = 0; i < rand; i++ {
let myField: UITextField = UITextField (frame:CGRectMake(CGFloat(i * 30), 50, 25, 25));
myField.text = String(i)
myField.backgroundColor = UIColor.redColor()
myField.addTarget(self, action: "textFieldEditingChanged:", forControlEvents: UIControlEvents.EditingChanged)
self.view.addSubview(myField)
}
If you only have a String and you want to populate each char in a textField, you could do like this:
let word = "Car"
for var i = 0; i < word.characters.count; i++ {
let myField: UITextField = UITextField (frame:CGRectMake(CGFloat(i * 30), 50, 25, 25));
myField.text = String(word[word.startIndex.advancedBy(i)])
myField.backgroundColor = UIColor.redColor()
myField.addTarget(self, action: "textFieldEditingChanged:", forControlEvents: UIControlEvents.EditingChanged)
self.view.addSubview(myField)
}
Click event for the textField
func textFieldEditingChanged(target: UITextField){
if (target.text?.characters.count > 1){
target.text = target.text?.substringToIndex(target.text!.endIndex.predecessor())
}
}
UPDATE
To change responder
Declare a variable var tagNumber = 0 and when you loop through in your for statement and create your textFields just add this row to myField.tag = i. In your textFieldEditingChanged function, add this code block:
if (target.tag < tagNumber){
let nextTag: NSInteger = target.tag + 1;
// Try to find next responder
if let nextResponder: UIResponder! =
target.superview!.viewWithTag(nextTag){
nextResponder.becomeFirstResponder()
}
}
I have found this answer How to check text field input at real time?
This is what I am looking for. However I am having trouble actually implementing this code. Also my current geographical location makes googling almost impossible.
I want to be able to change the background color of the next text field if the correct number is entered into the previous text field. textfieldTwo background color will change to green if the correct value is entered in textFieldOne. If the value is incorrect then nothing will happen. Please help me out. I have two text fields called textFieldOne and textFieldTwo and nothing else in the code.
Just pop this in your main view controller in an empty project (try using iphone 6 on the simulator)
import UIKit
class ViewController: UIViewController {
var txtField:UITextField!
var txtFieldTwo:UITextField!
var rightNumber = 10
override func viewDidLoad() {
super.viewDidLoad()
//txtFieldOne
var txtField = UITextField()
txtField.frame = CGRectMake(100, 100, 200, 40)
txtField.borderStyle = UITextBorderStyle.None
txtField.backgroundColor = UIColor.blueColor()
txtField.layer.cornerRadius = 5
self.view.addSubview(txtField)
//txtFieldTwo
var txtFieldTwo = UITextField()
txtFieldTwo.frame = CGRectMake(100, 150, 200, 40)
txtFieldTwo.borderStyle = UITextBorderStyle.None
txtFieldTwo.backgroundColor = UIColor.blueColor()
txtFieldTwo.layer.cornerRadius = 5
self.view.addSubview(txtFieldTwo)
txtField.addTarget(self, action: "checkForRightNumber", forControlEvents: UIControlEvents.AllEditingEvents)
self.txtField = txtField
self.txtFieldTwo = txtFieldTwo
}
func checkForRightNumber() {
let number:Int? = self.txtField.text.toInt()
if number == rightNumber {
self.txtFieldTwo.backgroundColor = UIColor.greenColor()
} else {
self.txtFieldTwo.backgroundColor = UIColor.blueColor()
}
}
}
EDIT: Adding a version with IBOutlets and IBActions
Note that in this example the IBAction is connected to txtFieldOne on Sent Events / Editing Changed
Also, make sure your Text Fields border colors are set to None. In the storyboard, the way to do this is to choose the left most option with the dashed border around it. That's so you can color the backgrounds. You can use layer.cornerRadius to set the roundness of the border's edges.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var txtField: UITextField!
#IBOutlet weak var txtFieldTwo: UITextField!
var rightNumber = 10
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func checkForRightNumber(sender: AnyObject) {
let number:Int? = self.txtField.text.toInt()
if number == rightNumber {
self.txtFieldTwo.backgroundColor = UIColor.greenColor()
} else {
self.txtFieldTwo.backgroundColor = UIColor.blueColor()
}
}
}