UIButton action is not triggered after constraint layouts changed

给你一囗甜甜゛ 提交于 2020-01-03 08:41:27

问题


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?

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
}

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.


回答1:


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.




回答2:


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()



回答3:


I use following steps when I need to use scrollview with dynamic content:

1) Firstly add a scrollView with top, bottom, trailing and leading is 0 to super view.

2) Add a view to scrollView and view's trailing, leading bottom and top space to scrollView can be set to 0 (or you can add margin optionally).

3) Now, you should add UI elements like buttons, labels with appropriate top, bottom, trailing and leading margins to each other.

4) Lastly, add equal height and equal width constraint to view with Safe Area:

and change equal height priority of view to 250:

It should solve your problem with UIScrollView.




回答4:


Finally, I have found the solution in another chain, once it became clear that the scrollview's contentview is resizing on scroll event to the original size. (Not clear why this is like this, but that is the fact.)

So I had to add a height constraint to the contentview in the storyboard and create an outlet to it and adjust this constraint when the content size is changing, like this:

@IBOutlet weak var ContentViewHeight: NSLayoutConstraint!

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.bounds = contentRect
    scrollview.contentSize = contentRect.size

    ----------- This is the key line to the success ----------
    ContentViewHeight.constant = contentRect.size.height
    ----------------------------------------------------------
}

After this is added, it works perfectly.



来源:https://stackoverflow.com/questions/52003086/uibutton-action-is-not-triggered-after-constraint-layouts-changed

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!