0

My layout is currently like this:

View
-- View
-- Vertical ScrollView
------ View
--------- Horizontal Paginated ScrollView
--------- View
------------- Horizontal ScrollView -- not working properly

See this image for view hierarchy screenshot from xcode:

enter image description here

Using Swift.

I am adding subviews dynamically to this "Size Select Scroll View"

Two Issues:

  1. After adding views, there is no margin between the subviews. Each subview's coord. are like this: (10.0, 0.0, 44.0, 44.0), (54.0, 0.0, 44.0, 44.0), (98.0, 0.0, 44.0, 44.0), (142.0, 0.0, 44.0, 44.0) etc.

But the appearance is like this without the 10 points gap between each subview: https://i.sstatic.net/mCGRW.png

  1. Scrolling horizontally is a pain. It only works on maybe 1/4 height from top of the scrollview area and very difficult to scroll. How do i layout subviews so that this scrollview is properly scrollable?

Note: I am explicitly setting content size of size scrollview to more than required so that i can see the scrolling.

2 Answers 2

1

I found out the issue. According to the Apple Docs the touch events will be passed to a subview only if it lies entirely in its parent.

In my case, the scrollview was going out of bounds of its parent view ( Details View), because of which touch events were weird. I increased the parent view's size to fit the scrollview and it works fine now.

From the docs (https://developer.apple.com/library/content/qa/qa2013/qa1812.html):

The most common cause of this problem is because your view is located outside the bounds of its parent view. When your application receives a touch event, a hit-testing process is initiated to determine which view should receive the event. The process starts with the root of the view hierarchy, typically the application's window, and searches through the subviews in front to back order until it finds the frontmost view under the touch. That view becomes the hit-test view and receives the touch event. Each view involved in this process first tests if the event location is within its bounds. Only after the test is successful, does the view pass the event to the subviews for further hit-testing. So if your view is under the touch but located outside its parent view's bounds, the parent view will fail to test the event location and won't pass the touch event to your view.

Sign up to request clarification or add additional context in comments.

Comments

1

This is always a challenge in iOS.

There are various solutions which unfortunately depend on the exact situation.

Here's a drop-in solution which is often the right solution.

/*

So, PASS any touch to the NEXT view, BUT ALSO if any of OUR
subviews are buttons, etc, then THOSE should ALSO work normally. :/

*/

import UIKit

class Passthrough: UIView {

    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {

        return subviews.contains(where: {
            !$0.isHidden
            && $0.isUserInteractionEnabled
            && $0.point(inside: self.convert(point, to: $0), with: event)
        })
    }

}

(Of course, you can also just drop the call in to some class, eg

class SomeListOrWhatever: UICollectionView, .. {

    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        print("MIGHT AS WELL TRY THIS")
        return subviews.contains(where: {
            !$0.isHidden
            && $0.isUserInteractionEnabled
            && $0.point(inside: self.convert(point, to: $0), with: event)
        })
    }

Even if you "don't totally understand what the problem is", this is "one of" the solutions!

For example, this is (usually!) the precise solution to the exact issue quoted from the doco by @kishorer747

It's definitely a real nuisance in iOS.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.