Skip to content

Commit

Permalink
ios navigation fixes done, can be tested
Browse files Browse the repository at this point in the history
  • Loading branch information
Kashif-E committed Sep 28, 2024
1 parent 4d4ca47 commit 33e6a02
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,11 @@ import platform.UIKit.navigationController
*
* @param screen The screen to be pushed.
*/
actual fun Navigator.pushX(screen: Screen) {
actual fun Navigator.pushX(screen: Screen, ) {
val viewController = extendedComposeViewController(screen = screen)
viewController.hidesBottomBarWhenPushed = true

val navigationController = getNavigationController()
navigationController?.let { navController ->
navController.pushViewController(viewController, animated = true)
navController.interactivePopGestureRecognizer?.setEnabled(true)
navController.interactivePopGestureRecognizer?.delegate = viewController as? UIGestureRecognizerDelegateProtocol
} ?: run {
navigationController?.pushViewController(viewController, animated = true) ?: run {
NSLog("NavigationController is null")
}
}
Expand Down Expand Up @@ -88,3 +83,4 @@ actual fun BottomSheetNavigator.showX(screen: Screen) {
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.kashif.voyant.extensions


import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.ExperimentalComposeApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.uikit.OnFocusBehavior
Expand Down Expand Up @@ -76,17 +77,19 @@ fun debugTopViewController(base: UIViewController? = UIApplication.sharedApplica
*/
@OptIn(ExperimentalComposeApi::class, ExperimentalMaterialApi::class)
fun extendedComposeViewController(
modifier: Modifier = Modifier,
screen: Screen,
isOpaque: Boolean = true,
): UIViewController {
val uiViewController = ComposeUIViewController(configure = {
onFocusBehavior = OnFocusBehavior.DoNothing
opaque = isOpaque
}) {
BottomSheetNavigator {
Navigator(screen = screen)
MaterialTheme {
BottomSheetNavigator {
Navigator(screen = screen)
}
}

}

return UIViewControllerWrapper(uiViewController)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,99 +1,166 @@
package com.kashif.voyant.extensions


import kotlinx.cinterop.BetaInteropApi
import kotlinx.cinterop.CValue
import kotlinx.cinterop.ExperimentalForeignApi
import kotlinx.cinterop.ObjCAction
import kotlinx.cinterop.useContents
import platform.CoreGraphics.CGFloat
import platform.CoreGraphics.CGPoint
import platform.CoreGraphics.CGRect
import platform.CoreGraphics.CGRectMake
import platform.Foundation.NSLog
import platform.Foundation.NSSelectorFromString
import platform.UIKit.UIColor
import platform.UIKit.UIEvent
import platform.UIKit.UIGestureRecognizer
import platform.UIKit.UIGestureRecognizerDelegateProtocol
import platform.UIKit.UINavigationController
import platform.UIKit.UINavigationControllerDelegateProtocol
import platform.UIKit.UIPress
import platform.UIKit.UISwipeGestureRecognizer
import platform.UIKit.UISwipeGestureRecognizerDirectionLeft
import platform.UIKit.UISwipeGestureRecognizerDirectionRight
import platform.UIKit.UITouch
import platform.UIKit.UIView
import platform.UIKit.UIViewAutoresizingFlexibleHeight
import platform.UIKit.UIViewAutoresizingFlexibleWidth
import platform.UIKit.UIViewController
import platform.UIKit.addChildViewController
import platform.UIKit.didMoveToParentViewController
import platform.UIKit.navigationController
import platform.UIKit.navigationItem
import platform.UIKit.willMoveToParentViewController

/**
* A custom `UIViewController` that wraps another `UIViewController` and adds gesture recognizer functionality.
* Implements the `UIGestureRecognizerDelegateProtocol` to handle swipe gestures.
*
* @property controller The `UIViewController` instance that is being wrapped.
*/
class UIViewControllerWrapper(
private val controller: UIViewController,
) : UIViewController(null, null), UIGestureRecognizerDelegateProtocol,
UINavigationControllerDelegateProtocol {

/**
* Called when the view controller's view is loaded into memory.
* Sets up the view hierarchy by adding the wrapped controller's view as a subview
* and managing the parent-child relationship between the view controllers.
*/
@OptIn(ExperimentalForeignApi::class)
override fun loadView() {
super.loadView()

controller.willMoveToParentViewController(this)
controller.view.setFrame(view.frame)
controller.view.setFrame(view.bounds)
view.addSubview(controller.view)
addChildViewController(controller)
controller.didMoveToParentViewController(this)

createPaddingViews()
}



@OptIn(ExperimentalForeignApi::class)
private fun createPaddingViews() {
val padding: CGFloat = 20.0

val width = view.bounds.useContents { this.size.width }
val height = view.bounds.useContents { this.size.height }
val topPaddingView = UIView(CGRectMake(0.0, 0.0, width, padding)).apply {
backgroundColor = UIColor.clearColor
autoresizingMask = UIViewAutoresizingFlexibleWidth
}

val bottomPaddingView = UIView(
CGRectMake(
0.0,
height - padding,
width,
padding
)
).apply {
backgroundColor = UIColor.clearColor
autoresizingMask = UIViewAutoresizingFlexibleWidth
}

val leftPaddingView =
UIView(CGRectMake(0.0, padding, padding, height - 2 * padding)).apply {
backgroundColor = UIColor.clearColor
autoresizingMask = UIViewAutoresizingFlexibleHeight
}

val rightPaddingView = UIView(
CGRectMake(
width - padding,
padding,
padding,
height - 2 * padding
)
).apply {
backgroundColor = UIColor.clearColor
autoresizingMask = UIViewAutoresizingFlexibleHeight
}

view.addSubview(topPaddingView)
view.addSubview(bottomPaddingView)
view.addSubview(leftPaddingView)
view.addSubview(rightPaddingView)
}

/**
* Called after the view has been loaded.
* Sets the delegate for the interactive pop gesture recognizer
*/
override fun viewDidLoad() {
super.viewDidLoad()
navigationController?.interactivePopGestureRecognizer?.enabled= true
navigationController?.interactivePopGestureRecognizer?.delegate = this
controller.navigationController?.interactivePopGestureRecognizer?.delegate = this
}

/**
* Handles the swipe gestures detected by the gesture recognizers.
* Logs the direction of the swipe.
*
* @param sender The `UISwipeGestureRecognizer` that detected the swipe.
*/

override fun viewWillAppear(animated: Boolean) {
super.viewWillAppear(animated)
navigationController?.interactivePopGestureRecognizer?.delegate = this
navigationItem.hidesBackButton = true
}


@OptIn(BetaInteropApi::class)
@ObjCAction
fun handleSwipe(sender: UISwipeGestureRecognizer) {
NSLog("Swipe detected: ${sender.direction}")
}


/**
* Called when the view controller is about to be displayed.
* Enables the interactive pop gesture recognizer.
*
* @param navigationController The navigation controller that will display the view controller.
* @param willShowViewController The view controller that will be displayed.
* @param animated A flag indicating whether the transition will be animated.
*/

override fun navigationController(
navigationController: UINavigationController,
willShowViewController: UIViewController,
animated: Boolean
) {
navigationController.interactivePopGestureRecognizer?.setEnabled(true)
navigationController.interactivePopGestureRecognizer?.enabled = true
}


override fun gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer): Boolean {
println("gestureRecognizerShouldBegin")
return true
}

override fun gestureRecognizer(
gestureRecognizer: UIGestureRecognizer,
shouldRecognizeSimultaneouslyWithGestureRecognizer: UIGestureRecognizer
): Boolean {
return true
}
}

@OptIn(ExperimentalForeignApi::class)
class TransparentPassThroughView(frame: CValue<CGRect>) : UIView(frame = frame),
UIGestureRecognizerDelegateProtocol {

init {
backgroundColor = UIColor.clearColor
}

override fun hitTest(point: CValue<CGPoint>, withEvent: UIEvent?): UIView? {

val pointX = point.useContents { this.x }
val pointY = point.useContents { this.y }

}
if (pointX >= 0 && pointX <= bounds.useContents { this.size.width } && pointY >= 0 && pointY <= bounds.useContents { this.size.height }) {
return null
}

return super.hitTest(point, withEvent)
}

override fun gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer): Boolean {
NSLog("gestureRecognizerShouldBegin: true")
return true // Allow gesture recognition to begin
}

override fun gestureRecognizer(
gestureRecognizer: UIGestureRecognizer,
shouldRecognizeSimultaneouslyWithGestureRecognizer: UIGestureRecognizer
): Boolean {
return true
}
}

0 comments on commit 33e6a02

Please sign in to comment.