UIButton is programmatically created.
At first, it is shown.
User taps it.
The code programmatically sets its .isHidden to true, but it stays shown.
When set true, next line is print that shows .isHidden is true. (see OUTPUT below)
But I still see it.
HERE IS CODE....................
DispatchQueue.main.async
{
connect_dropbox_UIButton = UIButton(frame: CGRect(x: tap_button_2nd_x,
y: tap_row_y,
width: tap_buttom_width,
height: tap_height ))
connect_dropbox_UIButton.setTitle( "DX", for: .normal )
connect_dropbox_UIButton.addTarget( self, action: #selector( connect_dropbox ), for: .touchUpInside)
connect_dropbox_UIButton.backgroundColor = UIColorFromRGB( rgbValue: 0x0080ff )
connect_dropbox_UIButton.isHidden = is_dropbox_connection( TRUE )
print("show_DX_tap: is_dropbox_connection", is_dropbox_connection() )
print("show_DX_tap: connect_dropbox_UIButton.isHidden", connect_dropbox_UIButton.isHidden ) // shows "true"
connect_dropbox_UIButton.isEnabled = TRUE
self.view.addSubview( connect_dropbox_UIButton )
}
func is_dropbox_connection( _ is_dump: Bool = false ) -> Bool
{
if DBG_UPLOAD || is_dump {
print("is_DROP_1_authorizedClient_successful", is_DROP_1_authorizedClient_successful )
print("is_DROP_2_authorizeFromControllerV2_successful", is_DROP_2_authorizeFromControllerV2_successful )
print("is_DropboxOAuthCompletion", is_DropboxOAuthCompletion )
}
// Abort if no dropbox access before session:
if !is_DROP_1_authorizedClient_successful // DX API access is ok
|| !is_DROP_2_authorizeFromControllerV2_successful // always set TRUE
|| !is_DropboxOAuthCompletion // call back sets TRUE or false
{
return false
}
else
{
return TRUE
}
}
HERE IS OUTPUT.....................
is_DROP_1_authorizedClient_successful true
is_DROP_2_authorizeFromControllerV2_successful true
is_DropboxOAuthCompletion true show_DX_tap: is_dropbox_connection
true show_DX_tap: connect_dropbox_UIButton.isHidden true
I copy pasted your code and changed TRUE to true, and the button was hidden for me.
However, based on the code snippets you posted, the user would never get the chance to interact with the button because you don't add it as a subview until after you already set .isHidden to true. If you are seeing a button, it is either a different button or you are adding and modifying this one somewhere else. I would double check where in your code that happens - the logic in these two code snippets seems to behave the way you intended it to.
Related
A view's height in my view controller needs to change as the user interacts with the application. Sometimes the view needs to be larger in height and other times it needs to be shorter depending on the number of options a user has.
I have implemented a method to change the height depending on the state of the view, and I call this method in viewDidLoad to set the initial state, and I recall the method whenever the state changes.
However, the only time the view actually updates the layout is from the call in viewDidLoad. All other calls of my method do not update the view.
func updateContainerViewHeight(constant: CGFloat) {
print("lets update")
baseView.heightAnchor.constraint(equalToConstant: constant).isActive = true
containerView.heightAnchor.constraint(equalToConstant: constant).isActive = true
self.view.setNeedsLayout()
UIView.animate(withDuration: 0.25) {
self.view.layoutIfNeeded()
}
}
FYI print("let's update") is printing in the console.
As here
baseView.heightAnchor.constraint(equalToConstant: constant).isActive = true
containerView.heightAnchor.constraint(equalToConstant: constant).isActive = true
every call adds new constraints which will cause conflicts , so create
1-
var baseCon,containCon:NSLayoutConstraint!
2-
baseCon = baseView.heightAnchor.constraint(equalToConstant: constant)
baseCon.isActive = true
containCon = containerView.heightAnchor.constraint(equalToConstant: constant)
containCo.isActive = true
3- Then play with constant
baseCon.constant = ////
I created a view programmatically, like a popup coming from the top with some text and images in there!
alert = UIView(frame: CGRect(x: 0, y: 0, width: self.frame.width , height: 0))
alert?.frame.origin.y = (textLable?.frame.height)!
alert?.frame.size.height = (textLable?.frame.height)!
alert?.backgroundColor = self.arrayOptions.colorBackground
and then I'm trying to add a UITapGestureRecognizer to that view like this inside a setup func that is called in the init.
let tap = UITapGestureRecognizer(target: self, action: #selector(self.teste))
tap.numberOfTapsRequired = 1
alert?.addGestureRecognizer(tap)
im adding that view like this in a UitableViewController:
self.popView = PopupView(frame: CGRect(x: 0 , y: 0 , width:self.view.frame.width, height: 0), with: PopUpOptions.error, originY: 0,description:"blablabla")
self.view.addSubview(self.popView!)
But when I tap on the view nothing happens, but when I tap repeatedly over and over this error occurs:
<_UISystemGestureGateGestureRecognizer: 0x174186f50>: Gesture: Failed
to receive system gesture state notification before next touch
But I cant seem to find an answer for this, could anyone help me pls!
Thank you!
here is the GitHub link https://github.com/Coimbraa/AlertsPopup_framework for my framework
Took a look at your GitHub repo - Couple notes...
I see a lot of "!" in your code. Each one of those is a potential crash. For example, I had to make a number of edits just to get it to run at all (I don't have the image assets the code is expecting).
In PopUpView.swift change the init() func to this (just added the clipsToBounds line):
override public init(frame: CGRect) {
super.init(frame: frame)
setup()
self.clipsToBounds = true
}
Now, when you call popView?.toggleStatus() you probably won't see anything.
Your PopupView "container" has a height of Zero. Without clipping its contents, you see the content, but you can't interact with it.
I changed your animation block in toggleStatus() to this:
UIView.animate(withDuration: 0.5, animations: {
if let sz = self.alert?.frame.size {
self.frame.size.height = sz.height
}
self.alert?.frame.origin.y = (self.startY)! + (self.status ? 0 : -((self.textLable?.frame.height)! + self.startY))
}) { (finished:Bool) in
// ...
and I could now tap into and edit the TextView, and tap elsewhere and get print("pressed") output to the debug console.
I did not dig further, so I don't know if/where you need to put additional code to reset the frame-height back to Zero (or maybe it gets hidden or removed, whatever).
Try this:
alert.isUserInteractionEnabled = true
Set this property to true for those views you want to tap on (where you add the tap gesture recognizer).
You are adding that Custom Alert View in Table View Controller.
First try what Tung Fam has suggested, if it doesn't work then,
Trying adding it on window like:
self.view.window.addSubview(self.popView!)
Also set the frame of the window to the popupView.
As I'm seeing you are setting target for TapGesture as self in
let tap = UITapGestureRecognizer(target: self, action: #selector(self.teste))
Here self is object of UIView (your alert view).
So according to this line your tapGesture listener must be implemented in alert? class. And you need to use custom protocol or custom delegate to get the action of tapGesture in other classes.
This is part of my code, in which I add a subview to an UIButton.
self.imageView?.hidden = true
guard self.subviews.contains(frequencyView) else {
print("show frequency view\(self.imageView?.hidden)")
self.addSubview(frequencyView)
print("show frequency view\(self.imageView?.hidden)")
self.imageView?.hidden = true
print("show frequency view\(self.imageView?.hidden)")
return
}
However I when I set the button's imageView.hidden = true before I addSubview. It'll automatically change the hidden state to false.
show frequency viewOptional(true)
show frequency viewOptional(false)
show frequency viewOptional(true)
Is there any method that can prevent it from happening? or do I have to change it back to true after that.
So the main screen of my app has a hamburger button which can be used to navigate to other parts of the app. That being said, there's a chance someone might get notifications in other parts of the app, so I'm trying to add an indicator, which is just a subclass of UILabel which shows up over the hamburger button. When the view first loads, it looks like this, which is fine:
Okay, so when the user opens the navigation drawer I animate the hamburger button and remove the notification by hiding it (self.badge.hidden = true), and it goes away fine, like this:
Now the problem I'm facing is that when the view is animated back in, the notification badge ends up in a really weird place, even though no frames change, and if I print out the frames, it's exactly where it should be programmatically, but it actuality it ends up looking really weird, as just the tiny bubble in the top left corner:
All I'm doing to add it back is in my delegate method for when the navigation drawer closes, I try self.badge.hidden = false. So obviously there's something weird going on here.
But what's even weirder, is that if I navigate to another view, say I press one of the buttons in the navigation drawer, and then go back to the home view, then the hiding works fine, and when I unhide the notification badge then it appears exactly where it should be! As I said, this only happens if I navigate away from the home screen and then back to it, but when the app first loads and I go to the navigation drawer, then the notification badge gets put in the wrong place and is also very tiny. I've tried a lot of things to try to get this to work. Originally I was reinitializing the badge view before I added it back using the same frame I did when the view loaded, but it still ended up the way it looks now. I also tried to set it to nil and remove it from the superView instead of just hiding it, but all of the different things I've tried have resulted in the same thing: only on the home screen before navigating elsewhere, the badge doesn't end up in the right place after closing the navigation drawer. I can post more code or answer any additional questions you might have, but please help me I can't figure this one out!
Here is my initialization code in viewDidAppear:
badge = SwiftBadge(frame: CGRectMake(15, -5, 15, 15))
menuButton.addSubview(badge!)
menuButton.bringSubviewToFront(badge!)
And creating my menuButton (which I do do in viewDidLoad)
menuButton = UIButton(frame: CGRectMake(0, 0, 20, 20))
menuButton.setBackgroundImage(UIImage(named: "Side menu.png"), forState: .Normal)
let addBarItem = UIBarButtonItem(customView: addButton)
let menuButtonItem = UIBarButtonItem(customView: menuButton)
self.navigationItem.setLeftBarButtonItem(menuButtonItem, animated: true)
EDIT 2:
Code for rotating the hamburger button
let animationDuration = self.revealViewController().toggleAnimationDuration
UIView.animateWithDuration(animationDuration, animations: { () -> Void in
if !self.menuButtonRotated {
//self.badge?.removeFromSuperview()
self.badge?.hidden = true
self.menuButton.transform = CGAffineTransformMakeRotation(CGFloat(M_PI_2))
self.menuButtonRotated = true
print("Menu frame after rotation: \(self.menuButton.frame)")
} else {
self.menuButton.transform = CGAffineTransformMakeRotation(CGFloat(0))
self.menuButtonRotated = false
self.badge?.hidden = false
}
}, completion: { (bool) -> Void in
if !self.menuButtonRotated {
//self.badge = SwiftBadge(frame: CGRectMake(250, 250, 100, 100))
print("New menu frame: \(self.menuButton.frame)")
print("New badge frame: \(self.badge!.frame)")
//self.view.addSubview(self.badge!)
//self.badge?.hidden = false
}
})
Commented out code is some other things I've tried.
Well after much debugging and hair pulling, I finally figured out what the fix was. For whatever reason it seems that my menuButton frame wasn't set as soon as the animation ended, so I had to change my animation code to below, hopefully this will help someone who comes looking later:
UIView.animateWithDuration(animationDuration, animations: { () -> Void in
if !self.menuButtonRotated {
self.badge?.hidden = true
self.badge?.removeFromSuperview()
self.badge = nil
self.menuButton.transform = CGAffineTransformMakeRotation(CGFloat(M_PI_2))
self.menuButtonRotated = true
print("Menu frame after rotation: \(self.menuButton.frame)")
} else {
self.menuButton.transform = CGAffineTransformMakeRotation(CGFloat(0))
self.menuButtonRotated = false
}
}, completion: { (bool) -> Void in
if !self.menuButtonRotated {
print("New menu frame: \(self.menuButton.frame)")
print("New badge frame: \(self.badge?.frame)")
let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(0.05 * Double(NSEC_PER_SEC)))
dispatch_after(delayTime, dispatch_get_main_queue()) {
self.badge = SwiftBadge(frame: CGRectMake(13, -7, 15, 15))
self.badge?.alpha = 0.95
self.menuButton.addSubview(self.badge!)
self.menuButton.layoutIfNeeded()
}
}
})
I am trying trying to make a UISlider be enabled/disabled on button click, however Xcode is telling me that "UISlider does not have a member..."; basically, it doesn't work. When the button is clicked, it multiplies a variable by -1. If the variable is negative, then the UISlider will be enabled. If the variable is positive, then the UISlider will be disabled. The slider is called "userHue" and "opaque" is the label's name. The label is covering the slider. This is my code:
var noomber = 1
#IBAction func transparent(sender: UIButton)
{
noomber = -(noomber)
if(noomber<0)
{
opaque.backgroundColor = UIColor(hue: 0, saturation: 0, brightness: 0, alpha: 0)
userHue.userInteractionEnabled = true
}
else
{
opaque.backgroundColor = UIColor.whiteColor()
userHue.userInteractionEnabled = false
}
}
I have searched for at least an hour and I still cannot find
any answer to my question. Thanks in advance.
Solved my own problem: I only created an "action" for the slider, not an "outlet". Hence I couldn't access any of the slider's properties.