Skip to content

Commit

Permalink
Add possibility to start the XBottomSheet from certain height
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexStefan committed Mar 17, 2020
1 parent 87e99bc commit e7fb2ec
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 11 deletions.
17 changes: 11 additions & 6 deletions XBottomSheet.Samples/XBottomSheet.Touch/Main.storyboard
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15705" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15706"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
Expand All @@ -22,18 +20,25 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="FsS-3d-Mc5">
<rect key="frame" x="164" y="318" width="46" height="30"/>
<rect key="frame" x="164.5" y="318.5" width="46" height="30"/>
<state key="normal" title="Button"/>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="NJJ-MV-V6M" misplaced="YES">
<rect key="frame" x="164" y="617" width="46" height="30"/>
<state key="normal" title="Imagine tabs here"/>
</button>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="NJJ-MV-V6M" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="HQT-JP-PQM"/>
<constraint firstItem="FsS-3d-Mc5" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="MmL-ka-6r3"/>
<constraint firstItem="FsS-3d-Mc5" firstAttribute="centerY" secondItem="8bC-Xf-vdC" secondAttribute="centerY" id="bx3-bi-Q7f"/>
<constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="NJJ-MV-V6M" secondAttribute="bottom" constant="20" id="kLh-QH-gMN"/>
</constraints>
</view>
<connections>
<outlet property="btMain" destination="FsS-3d-Mc5" id="name-outlet-FsS-3d-Mc5"/>
<outlet property="btTest" destination="NJJ-MV-V6M" id="name-outlet-NJJ-MV-V6M"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
Expand Down
21 changes: 17 additions & 4 deletions XBottomSheet.Samples/XBottomSheet.Touch/ViewController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace XBottomSheet.Touch.Sample
public partial class ViewController : UIViewController
{
BottomSheetViewController bottomSheetViewController;
bool viewWasSet;

protected ViewController(IntPtr handle) : base(handle)
{
Expand All @@ -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);
Expand All @@ -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()
Expand All @@ -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;
Expand Down
33 changes: 33 additions & 0 deletions XBottomSheet.Touch/Views/BottomSheetContentView.cs
Original file line number Diff line number Diff line change
@@ -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<BottomSheetContentView>(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);
}
}
}
29 changes: 29 additions & 0 deletions XBottomSheet.Touch/Views/BottomSheetContentView.designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 37 additions & 0 deletions XBottomSheet.Touch/Views/BottomSheetContentView.xib
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="15705" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15705"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="1" customClass="BottomSheetContentView">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Thm-hm-FcY" restorationIdentifier="contentView">
<rect key="frame" x="0.0" y="0.0" width="375" height="100"/>
<color key="backgroundColor" systemColor="systemGrayColor" colorSpace="custom" customColorSpace="sRGB" red="0.556862745098039" green="0.556862745098039" blue="0.576470588235294" alpha="1"/>
<constraints>
<constraint firstAttribute="height" constant="100" id="OTI-aa-5yA"/>
</constraints>
<accessibility key="accessibilityConfiguration" identifier="contentView">
<bool key="isElement" value="YES"/>
</accessibility>
</view>
</subviews>
<constraints>
<constraint firstItem="Thm-hm-FcY" firstAttribute="width" secondItem="1" secondAttribute="width" id="5OC-bV-euu"/>
<constraint firstItem="Thm-hm-FcY" firstAttribute="leading" secondItem="1" secondAttribute="leading" id="DD8-CK-h6o"/>
<constraint firstItem="Thm-hm-FcY" firstAttribute="top" secondItem="1" secondAttribute="top" id="g3o-rr-0CO"/>
</constraints>
<point key="canvasLocation" x="136.80000000000001" y="153.37331334332833"/>
<connections>
<outlet property="contentView" destination="Thm-hm-FcY" id="name-outlet-Thm-hm-FcY"/>
</connections>
</view>
</objects>
</document>
46 changes: 45 additions & 1 deletion XBottomSheet.Touch/Views/BottomSheetViewController.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using System.Diagnostics;
using System.Linq;
using CoreGraphics;
using UIKit;

Expand All @@ -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;

Expand All @@ -28,6 +31,25 @@ public BottomSheetState CurrentState
/// </summary>
public nfloat Duration { get; set; } = -2;

/// <summary>
/// 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.
/// </summary>
/// <param name="top">Top point for the control to expand to.</param>
/// <param name="middle">Middle point where control will stop. This can be used as default state as well.</param>
/// <param name="bottom">Point where control will stay as expanded at the bottom of the screen.</param>
/// <param name="startHeight">Point from where control will appear.</param>
/// <param name="animatedAppearance">Specify if control should appear animated.</param>
/// <param name="defaultState">Specify which state should be default when control appears.</param>
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;
}

/// <summary>
/// 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.
/// </summary>
Expand Down Expand Up @@ -121,7 +143,11 @@ public void Hide(bool resetState)
/// <param name="customView">Custom UIView that will be shown instead of the default one.</param>
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)
Expand All @@ -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))
{
Expand Down Expand Up @@ -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);
}
}

Expand All @@ -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);
}
}
}

0 comments on commit e7fb2ec

Please sign in to comment.