From e7fb2ec906a90a50b2138b811b93a68c6b2b0387 Mon Sep 17 00:00:00 2001 From: Alexandru Stefan Date: Tue, 17 Mar 2020 18:12:30 +0100 Subject: [PATCH] Add possibility to start the XBottomSheet from certain height #6 --- .../XBottomSheet.Touch/Main.storyboard | 17 ++++--- .../XBottomSheet.Touch/ViewController.cs | 21 +++++++-- .../Views/BottomSheetContentView.cs | 33 +++++++++++++ .../Views/BottomSheetContentView.designer.cs | 29 ++++++++++++ .../Views/BottomSheetContentView.xib | 37 +++++++++++++++ .../Views/BottomSheetViewController.cs | 46 ++++++++++++++++++- 6 files changed, 172 insertions(+), 11 deletions(-) create mode 100644 XBottomSheet.Touch/Views/BottomSheetContentView.cs create mode 100644 XBottomSheet.Touch/Views/BottomSheetContentView.designer.cs create mode 100644 XBottomSheet.Touch/Views/BottomSheetContentView.xib diff --git a/XBottomSheet.Samples/XBottomSheet.Touch/Main.storyboard b/XBottomSheet.Samples/XBottomSheet.Touch/Main.storyboard index 81e08c7..b3bffb9 100644 --- a/XBottomSheet.Samples/XBottomSheet.Touch/Main.storyboard +++ b/XBottomSheet.Samples/XBottomSheet.Touch/Main.storyboard @@ -1,11 +1,9 @@ - - - - + + - + @@ -22,18 +20,25 @@ + + + + diff --git a/XBottomSheet.Samples/XBottomSheet.Touch/ViewController.cs b/XBottomSheet.Samples/XBottomSheet.Touch/ViewController.cs index c57a2ce..6e3dfef 100644 --- a/XBottomSheet.Samples/XBottomSheet.Touch/ViewController.cs +++ b/XBottomSheet.Samples/XBottomSheet.Touch/ViewController.cs @@ -8,6 +8,7 @@ namespace XBottomSheet.Touch.Sample public partial class ViewController : UIViewController { BottomSheetViewController bottomSheetViewController; + bool viewWasSet; protected ViewController(IntPtr handle) : base(handle) { @@ -23,8 +24,9 @@ public override void ViewDidLoad() private void SetupBottomSheet() { // Create BottomSheetViewController + var heightWhereToStart = 150; var bottom = UIScreen.MainScreen.Bounds.Height - UIApplication.SharedApplication.StatusBarFrame.Height; - bottomSheetViewController = new BottomSheetViewController(100, 300, bottom, true, BottomSheetState.Bottom); + bottomSheetViewController = new BottomSheetViewController(100, 300, 600, heightWhereToStart, true, BottomSheetState.Bottom); // Add BottomSheetViewController as a child view AddChildViewController(bottomSheetViewController); @@ -38,6 +40,13 @@ private void SetupBottomSheet() UITapGestureRecognizer tapGesture = new UITapGestureRecognizer(HandleAction); View.AddGestureRecognizer(tapGesture); + + btTest.TouchUpInside += BtTest_TouchUpInside; + } + + private void BtTest_TouchUpInside(object sender, EventArgs e) + { + // Just to check if the button is actually clickable } void HandleAction() @@ -48,9 +57,13 @@ void HandleAction() void BtMain_TouchUpInside(object sender, EventArgs e) { bottomSheetViewController.Show(); - var customView = CustomView.Create(); - customView.Frame = View.Frame; - bottomSheetViewController.SetCustomView(customView); + if (!viewWasSet) + { + var customView = CustomView.Create(); + customView.Frame = View.Frame; + bottomSheetViewController.SetCustomView(customView); + viewWasSet = true; + } // Check what CurrentState of the BottomSheetViewController var checkState = bottomSheetViewController.CurrentState; diff --git a/XBottomSheet.Touch/Views/BottomSheetContentView.cs b/XBottomSheet.Touch/Views/BottomSheetContentView.cs new file mode 100644 index 0000000..a2ce123 --- /dev/null +++ b/XBottomSheet.Touch/Views/BottomSheetContentView.cs @@ -0,0 +1,33 @@ +using CoreGraphics; +using Foundation; +using System; +using UIKit; + +namespace XBottomSheet.Touch +{ + public partial class BottomSheetContentView : UIView + { + public BottomSheetContentView(IntPtr handle) : base(handle) + { + } + + public static BottomSheetContentView Create() + { + var arr = NSBundle.MainBundle.LoadNib("BottomSheetContentView", null, null); + var v = arr.GetItem(0); + return v; + } + + public void SetContentView(UIView customView) + { + customView.Frame = contentView.Frame; + contentView.AddSubview(customView); + } + + public void AdjustContentFrame(CGRect frame, nfloat startHeight, nfloat height) + { + var x = contentView.Subviews[0]; + x.Frame = new CGRect(x.Frame.X, x.Frame.Y, x.Frame.Width, frame.Height - height - startHeight); + } + } +} \ No newline at end of file diff --git a/XBottomSheet.Touch/Views/BottomSheetContentView.designer.cs b/XBottomSheet.Touch/Views/BottomSheetContentView.designer.cs new file mode 100644 index 0000000..b20b2ee --- /dev/null +++ b/XBottomSheet.Touch/Views/BottomSheetContentView.designer.cs @@ -0,0 +1,29 @@ +// WARNING +// +// This file has been generated automatically by Visual Studio from the outlets and +// actions declared in your storyboard file. +// Manual changes to this file will not be maintained. +// +using Foundation; +using System; +using System.CodeDom.Compiler; +using UIKit; + +namespace XBottomSheet.Touch +{ + [Register ("BottomSheetContentView")] + partial class BottomSheetContentView + { + [Outlet] + [GeneratedCode ("iOS Designer", "1.0")] + UIKit.UIView contentView { get; set; } + + void ReleaseDesignerOutlets () + { + if (contentView != null) { + contentView.Dispose (); + contentView = null; + } + } + } +} \ No newline at end of file diff --git a/XBottomSheet.Touch/Views/BottomSheetContentView.xib b/XBottomSheet.Touch/Views/BottomSheetContentView.xib new file mode 100644 index 0000000..fefc97d --- /dev/null +++ b/XBottomSheet.Touch/Views/BottomSheetContentView.xib @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/XBottomSheet.Touch/Views/BottomSheetViewController.cs b/XBottomSheet.Touch/Views/BottomSheetViewController.cs index 6418ee7..8be43e5 100644 --- a/XBottomSheet.Touch/Views/BottomSheetViewController.cs +++ b/XBottomSheet.Touch/Views/BottomSheetViewController.cs @@ -1,4 +1,6 @@ using System; +using System.Diagnostics; +using System.Linq; using CoreGraphics; using UIKit; @@ -9,6 +11,7 @@ public partial class BottomSheetViewController : UIViewController private readonly nfloat top; private readonly nfloat middle; private readonly nfloat bottom; + private readonly nfloat startHeight; private readonly bool animatedAppearance; private readonly BottomSheetState defaultState; @@ -28,6 +31,25 @@ public BottomSheetState CurrentState /// public nfloat Duration { get; set; } = -2; + /// + /// Create a new UIViewController that will behave as a BottomSheet control. As it will have the bottom stop point, there won't be autohide available. In order to have autohide, use the constructor without bottom parrameter. + /// + /// Top point for the control to expand to. + /// Middle point where control will stop. This can be used as default state as well. + /// Point where control will stay as expanded at the bottom of the screen. + /// Point from where control will appear. + /// Specify if control should appear animated. + /// Specify which state should be default when control appears. + public BottomSheetViewController(nfloat top, nfloat middle, nfloat bottom, nfloat startHeight, bool animatedAppearance = true, BottomSheetState defaultState = BottomSheetState.Middle) : base("BottomSheetViewController", null) + { + this.top = top; + this.middle = middle; + this.bottom = bottom; + this.startHeight = startHeight; + this.animatedAppearance = animatedAppearance; + this.defaultState = defaultState; + } + /// /// Create a new UIViewController that will behave as a BottomSheet control. As it will have the bottom stop point, there won't be autohide available. In order to have autohide, use the constructor without bottom parrameter. /// @@ -121,7 +143,11 @@ public void Hide(bool resetState) /// Custom UIView that will be shown instead of the default one. public void SetCustomView(UIView customView) { - View.AddSubview(customView); + var contentView = BottomSheetContentView.Create(); + contentView.Frame = new CGRect(0, 0, View.Frame.Width, View.Frame.Height); + contentView.SetContentView(customView); + View.AddSubview(contentView); + UpdateContentFrame(bottom); } private void PanGesture(UIPanGestureRecognizer recognizer) @@ -130,6 +156,11 @@ private void PanGesture(UIPanGestureRecognizer recognizer) var location = recognizer.LocationInView(View.Superview); var y = View.Frame.GetMinY(); + var actualY = y + translation.Y; + if (actualY > top) + UpdateContentFrame(y + translation.Y); + else + UpdateContentFrame(top); var velocity = recognizer.VelocityInView(View); if ((y + translation.Y >= top) & (y + translation.Y <= middle)) { @@ -169,16 +200,28 @@ private void CreateViewFrame(BottomSheetState state) { View.Frame = new CGRect(0, top, View.Frame.Width, View.Frame.Height); currentState = BottomSheetState.Top; + UpdateContentFrame(top); } else if (state == BottomSheetState.Middle) { View.Frame = new CGRect(0, middle, View.Frame.Width, View.Frame.Height); currentState = BottomSheetState.Middle; + UpdateContentFrame(middle); } else if (state == BottomSheetState.Bottom) { View.Frame = new CGRect(0, bottom, View.Frame.Width, View.Frame.Height); currentState = BottomSheetState.Bottom; + UpdateContentFrame(bottom); + } + } + + private void UpdateContentFrame(nfloat height) + { + if (View.Subviews.Any()) + { + var x = View.Subviews[0] as BottomSheetContentView; + x.AdjustContentFrame(View.Frame, startHeight, height); } } @@ -188,6 +231,7 @@ private void CreateViewFrameForSingleState(nfloat endTapLocation) Hide(false); View.Frame = new CGRect(0, middle, View.Frame.Width, View.Frame.Height); currentState = BottomSheetState.Middle; + UpdateContentFrame(middle); } } } \ No newline at end of file