Giter Site home page Giter Site logo

Comments (9)

victorBaro avatar victorBaro commented on August 27, 2024

This is an example:
screenshot 2019-01-16 at 12 22 14

from menu.

victorBaro avatar victorBaro commented on August 27, 2024

I am not very proud of this code, but it works. I created a custom navigation bar and added this code:

    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        if let menuView = findMenuView(in: self) {
            let newPoint = convert(point, to: menuView)
            if let view = menuView.hitTest(newPoint, with: event) { return view }
        }
        return super.hitTest(point, with: event)
    }
    
    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        if let menuView = findMenuView(in: self) {
            let newPoint = convert(point, to: menuView)
            if menuView.point(inside: newPoint, with:event) { return true }
        }
        return super.point(inside: point, with: event)
    }
    
    private func findMenuView(in view: UIView) -> MenuView? {
        if let found = view as? MenuView { return found }
        
        for subview in view.subviews {
            if let menuView = findMenuView(in: subview) { return menuView }
        }
        return nil
    }

If anyone has a better way around, I would appreciate. I don't really like to have a custom navbar that knows about the menu view.

from menu.

simsaens avatar simsaens commented on August 27, 2024

Your app looks really nice

I think the custom hit testing is the way to go, but why not have your custom nav bar take a closure that returns the UIView its interested in hit testing? That way it doesn't need to know about the menu view.

var viewForHitException: () -> UIView? = { return nil }

Then in your hitTest(_:with:) and point(inside:with:) methods you could request the view from the closure which has been assigned by whatever should know about both the menu and the nav bar.

It's still the same thing but at least then your nav bar doesn't need to be coupled to the menu bar.

from menu.

victorBaro avatar victorBaro commented on August 27, 2024

Thank you for your quick reply. I will do that 👍

from menu.

victorBaro avatar victorBaro commented on August 27, 2024

And the app is Panels a comic reader for iOS. I have a couple of places where I want to include your menu :)

from menu.

aaronpearce avatar aaronpearce commented on August 27, 2024

Great solution! I've hit the same issue, but I'm using multiple MenuViews at once. I'm working off your concept above now to see if I can get it working with multiple.

from menu.

simsaens avatar simsaens commented on August 27, 2024

@aaronpearce I was going to suggest in my initial comment to use

var viewsForHitException: () -> [UIView] = { return [] }

As the closure style, then you'd probably want to return the first positive hitTest result?

from menu.

aaronpearce avatar aaronpearce commented on August 27, 2024

Made my solution into a basic UINavigationBar extension as I'm using it throughout my app so had to resort to associated objects to store the views for hit exception. A subclass could make it tidier. Hope it helps.

extension UINavigationBar {
    
    private struct AssociatedKeys {
        static var viewsForHitException = "menu_viewsForHitException"
    }
    
    typealias ViewsForHitExceptionClosure = () -> [UIView]
    var viewsForHitException: ViewsForHitExceptionClosure {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.viewsForHitException) as? ViewsForHitExceptionClosure ?? { [] }
        }
        
        set {
            objc_setAssociatedObject(self, &AssociatedKeys.viewsForHitException, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
    override open func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        for hitExpectionView in viewsForHitException() {
            let newPoint = convert(point, to: hitExpectionView)
            if hitExpectionView.hitTest(newPoint, with: event) != nil {
                return hitExpectionView
            }
        }
        return super.hitTest(point, with: event)
    }
    
    override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        for hitExpectionView in viewsForHitException() {
            let newPoint = convert(point, to: hitExpectionView)
            if hitExpectionView.point(inside: newPoint, with:event) {
                return true
            }
        }
        return super.point(inside: point, with: event)
    }
}

from menu.

AMJ-7 avatar AMJ-7 commented on August 27, 2024

Made my solution into a basic UINavigationBar extension as I'm using it throughout my app so had to resort to associated objects to store the views for hit exception. A subclass could make it tidier. Hope it helps.

extension UINavigationBar {
    
    private struct AssociatedKeys {
        static var viewsForHitException = "menu_viewsForHitException"
    }
    
    typealias ViewsForHitExceptionClosure = () -> [UIView]
    var viewsForHitException: ViewsForHitExceptionClosure {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.viewsForHitException) as? ViewsForHitExceptionClosure ?? { [] }
        }
        
        set {
            objc_setAssociatedObject(self, &AssociatedKeys.viewsForHitException, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
    override open func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        for hitExpectionView in viewsForHitException() {
            let newPoint = convert(point, to: hitExpectionView)
            if hitExpectionView.hitTest(newPoint, with: event) != nil {
                return hitExpectionView
            }
        }
        return super.hitTest(point, with: event)
    }
    
    override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        for hitExpectionView in viewsForHitException() {
            let newPoint = convert(point, to: hitExpectionView)
            if hitExpectionView.point(inside: newPoint, with:event) {
                return true
            }
        }
        return super.point(inside: point, with: event)
    }
}

how to use it pls .

from menu.

Related Issues (6)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.