I need to add clear button in table view section header. It is exactly same like the one in notification center. So when user clicks it, 'x' will change to 'Clear'. If s/he clicks it again, app will perform action. But any click outside this button, 'Clear' will be back to 'x'
How can I make this? Thanks in advance
Unfortunately this does not come out of the box. You have to create your own custom section header view. That custom header view contains a UILabel on the left side. On the right side you put a UIButton that has the title "X". When the user taps on the button, change its title to "Clear" and its state to .Selected. Only clear your table view section when the button is tapped and its state is .Selected:
func setupButton() {
let button = UIButton()
button.setTitle("X", forState: .Normal)
button.addTarget(self, action: Selector("didPressButton:"), forControlEvents: .TouchUpInside)
addSubview(button)
}
func didPressButton(button: UIButton) {
if button.selected {
// clear your table view section
}
button.setTitle("Clear", forState: .Normal)
button.selected = true
}
To put the button back in its unselected state add a background UIView to your section header view and add a UITapGestureRecognizer to it:
func setupBackground() {
let background = UIView()
let recognizer = UITapGestureRecognizer(target: self, action: Selector("didTapOutside:"))
background.addGestureRecognizer(recognizer)
insertSubview(background, belowSubview: button)
}
func didTapOutside(recognizer: UITapGestureRecognizer) {
button.selected = false
button.setTitle("X", forState: .Normal)
}
To use your custom section header in your table view you implement the following UITableViewDelegate method:
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
// create your custom section header and return it
}
Related
I wrote a UITableView extension that would allow the reordering of cells after holding the tableview.
So the tableView goes edit mode as expected but what I would like to do is to add a Done button in the navigation bar of a viewController, when the tableView is being edited and that would end the edit mode when tapped.
How can I show/hide this button in viewController according to if the tableView being edited or not in UITableView extension?
that is my extension:
import UIKit
extension UITableView {
func addLongPressToTableView() {
let longPress = UILongPressGestureRecognizer(target: self, action: #selector(onLongPressGesture(sender:)))
longPress.minimumPressDuration = 0.8 // optional
self.addGestureRecognizer(longPress)
}
#objc func onLongPressGesture(sender: UILongPressGestureRecognizer) {
if (sender.state == .began) {
self.isEditing = true
self.setEditing(true, animated: false)
UIImpactFeedbackGenerator(style: .light).impactOccurred()
}
}
}
// ViewController, hide/show editButtonItem (done button?)
// navigationItem.rightBarButtonItems = [addButton, editButtonItem]
The UITableViewDelegate provides support for coordinating editing. Use the following two delegate methods to respond to changes in the editing state.
func tableView(UITableView, willBeginEditingRowAt: IndexPath)
func tableView(UITableView, didEndEditingRowAt: IndexPath?)
I created a UIButton within a for-loop because the number of these button depend on a certain number in the database. However, I have to change the image of this button after it is clicked, which doesn't work.
What I have done is I tried holding an array of those buttons and trying to access the buttons like that, which I don't think is not working.
let buttonArray: [UIButton] = [UIButton]()
...extra code
for (index, num) in numberOfButtonsNeeded.enumerated() {
let button = UIButton()
button.tag = index
button.addTarget(self, action: #selector(self.tap(sender:)), for: .touchUpInside)
buttonArray.append(button)
}
...
#objc func tap(sender: UIButton) {
DispatchQueue.main.asnyc{
buttonArray[sender.tag].setImage(UIImage(named:"Somename"))
}
}
I can access the tap gesture but this button's image won't be reset. Is there a way I can access the button? I do not think this array works.
This is suspect:
#objc func tap(sender: UIButton) {
DispatchQueue.main.asnyc{
buttonArray[sender.tag].setImage(UIImage(named:"Somename"))
}
You are already on the main queue, and the sender is the button that was tapped. So you don't need the array.
#objc func tap(sender: UIButton) {
sender.setImage(UIImage(named:"Somename"))
}
I have been trying to fix an issue that I encountered with a tableviewcontroller.
The sections within the tableviewcontroller are views:
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let sectionLabel = UILabel()
sectionLabel.text = Catalog.sharedInstance.allSections[section - 1].name.localized(lang: defaults.string(forKey: "language")!)
sectionLabel.font = UIFont(name: "Centabel Book", size: 25)
sectionLabel.backgroundColor = UIColor.white
sectionLabel.clipsToBounds = true
return sectionLabel
}
If I try to add a button programatically to put it over the tableview
let actionButton = JJFloatingActionButton()
override func viewDidLoad() {
super.viewDidLoad()
// Configuration of the Floating Action Button
actionButton.buttonColor = .red
actionButton.addItem { item in
self.performSegue(withIdentifier: "goToSettings", sender: nil)
}
actionButton.display(inViewController: self)
actionButton.clipsToBounds = true
// This doesn't work. It is to bring the button to the front. Now it is hidden by the sections.
view.bringSubviewToFront(actionButton)
// Checks if the language setting is nil, which means it is the first time you run the application. If then... selects English as default.
if defaults.string(forKey: "language") == nil {
defaults.set("en", forKey: "language")
}
}
... I don't know why but the viewForHeaderInSection hides the button. You can check it in the picture below:
floating button hided by the headersection
I tried to use the method:
view.bringSubviewToFront(actionButton)
and also:
actionbutton.superview?.bringSubviewToFront(actionButton)
But none of this brings the button to the front.
I am using a floating action button from github called JJFloatingActionButton. But I tried to add a simple UIButton and I got the same error. This is the code that also gave me the same error inside viewDidLoad:
let button = UIButton(frame: CGRect(x: 100, y: 1000, width: 100, height: 50))
button.backgroundColor = .green
button.setTitle("Test Button", for: .normal)
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
self.view.addSubview(button)
Again the same error. You can check the picture:
adding a simple UIButton happens the same problem
May be you can help me with that.
Thanks in advance.
You could try to use a regular UIViewController (not UITableViewController) and add the UITableView by hand.
Like that you would have better control over the view hierarchy.
I'm new to Swift and I'm trying to change the button colour on tap. When the button is tapped, it should change colour and when released it should go back to the original button colour.
An example of this is the calculator. When you tap a button, it changes from light grey to dark grey and when the user removes their finger off the button, it goes back to the original light grey colour. How do I go about doing that?
So far, I've only got this..
#IBAction func changeButtonColourOnTouch(sender: UIButton) {
zeroButton.backgroundColor = UIColor.blueColor()
}
The above code changes the button colour to blue but stays blue.
The problem is, after releasing the button, you should return the color to the original state.
You can link direct from storyboard, in the action TouchUpInside (release) and TouchDown (press) , to change the button color to the correct state in each event.
Or you can add a Target in the button by code, linking to the functions, as the code bellow shows it.
zeroButton.addTarget(self, action: Selector("holdRelease:"), forControlEvents: UIControlEvents.TouchUpInside);
zeroButton.addTarget(self, action: Selector("HoldDown:"), forControlEvents: UIControlEvents.TouchDown)
//target functions
func HoldDown(sender:UIButton)
{
zeroButton.backgroundColor = UIColor.blueColor()
}
func holdRelease(sender:UIButton)
{
zeroButton.backgroundColor = UIColor.whiteColor()
}
Code adapted by the present in the link UIButton with hold down action and release action
The checked answer above works, but if the user holds down on the button, then drags out, the background color won't return to normal. It's a tiny UI bug, but a simple fix. This includes the code of the checked answer.
zeroButton.addTarget(self, action: #selector(holdRelease), for: .touchUpInside);
zeroButton.addTarget(self, action: #selector(heldDown), for: .touchDown)
zeroButton.addTarget(self, action: #selector(buttonHeldAndReleased), for: .touchDragExit)
//target functions
#objc func heldDown()
{
zeroButton.backgroundColor = .blue
}
#objc func holdRelease()
{
zeroButton.backgroundColor = .white
}
#objc func buttonHeldAndReleased(){
zeroButton.backgroundColor = .blue
}
you could also use a tap gesture and change the color of the button as the user is tapping on the button
you could see apple documentation regarding UIGestureRecognizer in here
it is a little bit advanced, but you will learn a lot from it.
You can also use setbackgroundImageForState to define color image as button background for all UIControlState you are interested in e.g. Normal, Highlighted, Disabled, Selected.
let cx = UIGraphicsGetCurrentContext()
let color = UIColor.redColor()
let state = UIControlState.Selected
UIGraphicsBeginImageContext(CGSize(width:1, height:1))
CGContextSetFillColorWithColor(cx, color.CGColor)
CGContextFillRect(cx, CGRect(x:0, y:0, width:1, height:1))
let colorImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
self.zeroButton.setBackgroundImage(colorImage, forState: state)
Now color changes automatically and you don't have to handle it manually.
If you want that for a programmatically defined button, just declare the button of type system during its initialisation:
let button = UIButton(type: .system)
It's a simple question,
I have a UIButton with a target action
addTarget(self, action: "buttonPressed", forControlEvents: UIControlEvents.TouchUpInside)
func buttonPressed()
{
self.selected = !self.selected
}
This button is the child of a parent UIView
containerView.addSubview(button)
I add a UITapGestureRecognizer to the container
let tapG = UITapGestureRecognizer(target: self, action: "toggleView:")
containerView.addGestureRecognizer(tapG)
in func toggleView(gest:UIGestureRecognizer) I check the status of my button.
The problem is that in toggleView(), the status of the button has not been set... YET!
EDIT
if I do
print(button.selected)
I only get the button value BEFORE the touch event, not the new one.
any idea?
Try to change
func toggleView(gest:UIGestureRecognizer)
to
func toggleView(gest:UITapGestureRecognizer)
Hope it helps!
I don't exactly get what you are trying to accomplish, If you want to perform certain action on button click and another action when tapped outside in containerView then you can do
-(void)toggleView:(UITapGestureRecognizer *) gest{
CGPoint tapLocation = [gest loactionInView:containerView];
if(CGRectContainsPoint(button.frame, tapLocation)){
// Tapped on Button
}
else{
// tapped outside in containerView
}
}
Note: As am not learning swift, i gave snippet in Objective-C. you should be able to translate it into swift easily :)