Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIButton action is not triggered after constraint layouts changed

I have got an UIButton on a storyboard ViewController. When I load data into the form and the layout is significantly changing the button does not recognise the touch action.

I have figured out that when button is visible on the scrollview right after it if filled with data, the touch action works.

If the data too long and the button is not visible at first, just when it is scrolled into the display, the touch action does not work.

I was checking if something is above the button, but nothing. I have tried to change the zPosition of the button, not solved the problem.

What can be the issue?

I have made custom classes from the UIScrollView and the UIButton to check how the touches event triggered. It is showing the same behaviour, which is obvious. If the button is visible right at the beginning, the UIButton's touchesBegan event is triggered. If the button moves down and not visible at the beginning, it is never triggered, but the scrollview's touchesBegan is called instead.

Depending on the size of the data I load into the page sometimes the button is visible at the beginning, but the form can be still scrolled a bit. In this case the button still work, so it seems that this behaviour is not depending on if the scrollview is scrolled before or not, just on the initial visibility of the button.

Is there any layout or display refresh function which should be called to set back the behaviour to the button?

My storyboard setup:

The code portion which ensures that the contentview is resized for the scroll if the filled data requires bigger space.

func fillFormWithData() {
    dispDescription.text = jSonData[0]["advdescription"]
    dispLongDescription.text = jSonData[0]["advlongdesc"]
    priceandcurrency.text = jSonData[0]["advprice"]! + " " + jSonData[0]["advpricecur"]!
    validitydate.text = jSonData[0]["advdate"]!
    contentview.layoutIfNeeded()
    let contentRect = CGRect(x: 0, y: 0, width: scrollview.frame.width, height: uzenetbutton.frame.origin.y+uzenetbutton.frame.height+50)

    contentview.frame.size.height = contentRect.size.height
    scrollview.contentSize = contentview.bounds.size
}

After data load contentview+scrollview jumps to the bottom

After scroll the content view is cut to the original screensize

Ok, so another update. I have coloured the contentview background to blue and the scrollview background to white. When I load the data and resize the layout constraints, the contentview is resizing as expected, however now the scrollview is going to the bottom. After I scroll the view it is resizing to the original size which fits the screen. Now the button is only recognised when I touch the are which is blue behind. With the white background it is not recognised anymore, so it seems that the scrollview is hiding the button.

like image 530
Endre Olah Avatar asked Aug 24 '18 11:08

Endre Olah


2 Answers

Let me get this clear the button is added in storyboard and it is a spritekit project?? If you are using zPosition?? Why don’t u connect the UIButton via the assistant editor as an IBAction then the action is always tied to the button.

You can also do it differently

Create an SKLabelNode and put it on the screen where you want to have the button and then set a name to it as myButton

override func touchesBegan(_ touches: Set<UITouch>, with event:
UIEvent?) {
 if let touch = touches.first {
    let location = touch.location(in: self)
    let tappedNodes = nodes(at: location)
      for node in tappedNodes {
        if node.name == "myButton" {
           // call your action here
        }
    }
  }
}

EDIT 1: You could also try auto resizing your scrollView.content this works also if you are adding any views via the app or programmatically

    private func resizeScrollView(){
    print("RESIZING THE SCROLLVIEW from \(scrollView.contentSize)")
    for view in scrollView.subviews {
        contentRect = contentRect.union(view.frame)
    }
    scrollView.contentSize = CGSize(width: contentRect.size.width, height: contentRect.size.height + 150)
    print("THE CONTENT SIZE AFTER RESIZING IS: \(scrollView.contentSize)")
}

EDIT 2: I think I found the issue with your project. You need to move the MessageButton(UzenetButton) above DispDescription label in the object inspector in that way it will always be above your message textView. At the moment the UzeneButton is at the very far back in your view hierarchy so if your textView is resizing whilst editing it covers the button that is why you cannot click on it.

like image 69
AD Progress Avatar answered Oct 07 '22 06:10

AD Progress


See @Endre Olah,

  1. To make situation more clear do one more thing, set clipToBound property of contentview to true.
  2. you will notice that after loading of data your button not fully visible, it means it is shifting out of bound of its parentView (ContentView)
  3. And that's why button is not taking your touch. However, if you carefully touch upper part of button it still do its job. Because upper part is still in bound of ContentView
  4. Solution : After loading of data you have to make sure that you increase height of ContentView such that button should never go out of bound of its parentView(ContentView).

FOR EXAMPLE

@IBOutlet var heightConstraintOfContentView : NSLayoutConstraint!

After loading of data

let contentRect = CGRect(x: 0, y: 0, width: scrollview.frame.width, height: uzenetbutton.frame.origin.y+uzenetbutton.frame.height+50)
heightConstraintOfContentView.constant = contentRect.size.height
contentView.layoutIfNeeded()
like image 29
krishan kumar Avatar answered Oct 07 '22 07:10

krishan kumar