Skip to content

Commit e7fb2ec

Browse files
committed
Add possibility to start the XBottomSheet from certain height
#6
1 parent 87e99bc commit e7fb2ec

File tree

6 files changed

+172
-11
lines changed

6 files changed

+172
-11
lines changed

XBottomSheet.Samples/XBottomSheet.Touch/Main.storyboard

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2-
<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">
3-
<device id="retina4_7" orientation="portrait">
4-
<adaptation id="fullscreen"/>
5-
</device>
2+
<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">
3+
<device id="retina4_7" orientation="portrait" appearance="light"/>
64
<dependencies>
75
<deployment identifier="iOS"/>
8-
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
6+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15706"/>
97
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
108
</dependencies>
119
<scenes>
@@ -22,18 +20,25 @@
2220
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
2321
<subviews>
2422
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="FsS-3d-Mc5">
25-
<rect key="frame" x="164" y="318" width="46" height="30"/>
23+
<rect key="frame" x="164.5" y="318.5" width="46" height="30"/>
2624
<state key="normal" title="Button"/>
2725
</button>
26+
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="NJJ-MV-V6M" misplaced="YES">
27+
<rect key="frame" x="164" y="617" width="46" height="30"/>
28+
<state key="normal" title="Imagine tabs here"/>
29+
</button>
2830
</subviews>
2931
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
3032
<constraints>
33+
<constraint firstItem="NJJ-MV-V6M" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="HQT-JP-PQM"/>
3134
<constraint firstItem="FsS-3d-Mc5" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="MmL-ka-6r3"/>
3235
<constraint firstItem="FsS-3d-Mc5" firstAttribute="centerY" secondItem="8bC-Xf-vdC" secondAttribute="centerY" id="bx3-bi-Q7f"/>
36+
<constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="NJJ-MV-V6M" secondAttribute="bottom" constant="20" id="kLh-QH-gMN"/>
3337
</constraints>
3438
</view>
3539
<connections>
3640
<outlet property="btMain" destination="FsS-3d-Mc5" id="name-outlet-FsS-3d-Mc5"/>
41+
<outlet property="btTest" destination="NJJ-MV-V6M" id="name-outlet-NJJ-MV-V6M"/>
3742
</connections>
3843
</viewController>
3944
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>

XBottomSheet.Samples/XBottomSheet.Touch/ViewController.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ namespace XBottomSheet.Touch.Sample
88
public partial class ViewController : UIViewController
99
{
1010
BottomSheetViewController bottomSheetViewController;
11+
bool viewWasSet;
1112

1213
protected ViewController(IntPtr handle) : base(handle)
1314
{
@@ -23,8 +24,9 @@ public override void ViewDidLoad()
2324
private void SetupBottomSheet()
2425
{
2526
// Create BottomSheetViewController
27+
var heightWhereToStart = 150;
2628
var bottom = UIScreen.MainScreen.Bounds.Height - UIApplication.SharedApplication.StatusBarFrame.Height;
27-
bottomSheetViewController = new BottomSheetViewController(100, 300, bottom, true, BottomSheetState.Bottom);
29+
bottomSheetViewController = new BottomSheetViewController(100, 300, 600, heightWhereToStart, true, BottomSheetState.Bottom);
2830

2931
// Add BottomSheetViewController as a child view
3032
AddChildViewController(bottomSheetViewController);
@@ -38,6 +40,13 @@ private void SetupBottomSheet()
3840

3941
UITapGestureRecognizer tapGesture = new UITapGestureRecognizer(HandleAction);
4042
View.AddGestureRecognizer(tapGesture);
43+
44+
btTest.TouchUpInside += BtTest_TouchUpInside;
45+
}
46+
47+
private void BtTest_TouchUpInside(object sender, EventArgs e)
48+
{
49+
// Just to check if the button is actually clickable
4150
}
4251

4352
void HandleAction()
@@ -48,9 +57,13 @@ void HandleAction()
4857
void BtMain_TouchUpInside(object sender, EventArgs e)
4958
{
5059
bottomSheetViewController.Show();
51-
var customView = CustomView.Create();
52-
customView.Frame = View.Frame;
53-
bottomSheetViewController.SetCustomView(customView);
60+
if (!viewWasSet)
61+
{
62+
var customView = CustomView.Create();
63+
customView.Frame = View.Frame;
64+
bottomSheetViewController.SetCustomView(customView);
65+
viewWasSet = true;
66+
}
5467

5568
// Check what CurrentState of the BottomSheetViewController
5669
var checkState = bottomSheetViewController.CurrentState;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using CoreGraphics;
2+
using Foundation;
3+
using System;
4+
using UIKit;
5+
6+
namespace XBottomSheet.Touch
7+
{
8+
public partial class BottomSheetContentView : UIView
9+
{
10+
public BottomSheetContentView(IntPtr handle) : base(handle)
11+
{
12+
}
13+
14+
public static BottomSheetContentView Create()
15+
{
16+
var arr = NSBundle.MainBundle.LoadNib("BottomSheetContentView", null, null);
17+
var v = arr.GetItem<BottomSheetContentView>(0);
18+
return v;
19+
}
20+
21+
public void SetContentView(UIView customView)
22+
{
23+
customView.Frame = contentView.Frame;
24+
contentView.AddSubview(customView);
25+
}
26+
27+
public void AdjustContentFrame(CGRect frame, nfloat startHeight, nfloat height)
28+
{
29+
var x = contentView.Subviews[0];
30+
x.Frame = new CGRect(x.Frame.X, x.Frame.Y, x.Frame.Width, frame.Height - height - startHeight);
31+
}
32+
}
33+
}

XBottomSheet.Touch/Views/BottomSheetContentView.designer.cs

Lines changed: 29 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="15705" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
3+
<device id="retina4_7" orientation="portrait" appearance="light"/>
4+
<dependencies>
5+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15705"/>
6+
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
7+
</dependencies>
8+
<objects>
9+
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
10+
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
11+
<view contentMode="scaleToFill" id="1" customClass="BottomSheetContentView">
12+
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
13+
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
14+
<subviews>
15+
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Thm-hm-FcY" restorationIdentifier="contentView">
16+
<rect key="frame" x="0.0" y="0.0" width="375" height="100"/>
17+
<color key="backgroundColor" systemColor="systemGrayColor" colorSpace="custom" customColorSpace="sRGB" red="0.556862745098039" green="0.556862745098039" blue="0.576470588235294" alpha="1"/>
18+
<constraints>
19+
<constraint firstAttribute="height" constant="100" id="OTI-aa-5yA"/>
20+
</constraints>
21+
<accessibility key="accessibilityConfiguration" identifier="contentView">
22+
<bool key="isElement" value="YES"/>
23+
</accessibility>
24+
</view>
25+
</subviews>
26+
<constraints>
27+
<constraint firstItem="Thm-hm-FcY" firstAttribute="width" secondItem="1" secondAttribute="width" id="5OC-bV-euu"/>
28+
<constraint firstItem="Thm-hm-FcY" firstAttribute="leading" secondItem="1" secondAttribute="leading" id="DD8-CK-h6o"/>
29+
<constraint firstItem="Thm-hm-FcY" firstAttribute="top" secondItem="1" secondAttribute="top" id="g3o-rr-0CO"/>
30+
</constraints>
31+
<point key="canvasLocation" x="136.80000000000001" y="153.37331334332833"/>
32+
<connections>
33+
<outlet property="contentView" destination="Thm-hm-FcY" id="name-outlet-Thm-hm-FcY"/>
34+
</connections>
35+
</view>
36+
</objects>
37+
</document>

XBottomSheet.Touch/Views/BottomSheetViewController.cs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using System;
2+
using System.Diagnostics;
3+
using System.Linq;
24
using CoreGraphics;
35
using UIKit;
46

@@ -9,6 +11,7 @@ public partial class BottomSheetViewController : UIViewController
911
private readonly nfloat top;
1012
private readonly nfloat middle;
1113
private readonly nfloat bottom;
14+
private readonly nfloat startHeight;
1215
private readonly bool animatedAppearance;
1316
private readonly BottomSheetState defaultState;
1417

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

34+
/// <summary>
35+
/// 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.
36+
/// </summary>
37+
/// <param name="top">Top point for the control to expand to.</param>
38+
/// <param name="middle">Middle point where control will stop. This can be used as default state as well.</param>
39+
/// <param name="bottom">Point where control will stay as expanded at the bottom of the screen.</param>
40+
/// <param name="startHeight">Point from where control will appear.</param>
41+
/// <param name="animatedAppearance">Specify if control should appear animated.</param>
42+
/// <param name="defaultState">Specify which state should be default when control appears.</param>
43+
public BottomSheetViewController(nfloat top, nfloat middle, nfloat bottom, nfloat startHeight, bool animatedAppearance = true, BottomSheetState defaultState = BottomSheetState.Middle) : base("BottomSheetViewController", null)
44+
{
45+
this.top = top;
46+
this.middle = middle;
47+
this.bottom = bottom;
48+
this.startHeight = startHeight;
49+
this.animatedAppearance = animatedAppearance;
50+
this.defaultState = defaultState;
51+
}
52+
3153
/// <summary>
3254
/// 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.
3355
/// </summary>
@@ -121,7 +143,11 @@ public void Hide(bool resetState)
121143
/// <param name="customView">Custom UIView that will be shown instead of the default one.</param>
122144
public void SetCustomView(UIView customView)
123145
{
124-
View.AddSubview(customView);
146+
var contentView = BottomSheetContentView.Create();
147+
contentView.Frame = new CGRect(0, 0, View.Frame.Width, View.Frame.Height);
148+
contentView.SetContentView(customView);
149+
View.AddSubview(contentView);
150+
UpdateContentFrame(bottom);
125151
}
126152

127153
private void PanGesture(UIPanGestureRecognizer recognizer)
@@ -130,6 +156,11 @@ private void PanGesture(UIPanGestureRecognizer recognizer)
130156
var location = recognizer.LocationInView(View.Superview);
131157
var y = View.Frame.GetMinY();
132158

159+
var actualY = y + translation.Y;
160+
if (actualY > top)
161+
UpdateContentFrame(y + translation.Y);
162+
else
163+
UpdateContentFrame(top);
133164
var velocity = recognizer.VelocityInView(View);
134165
if ((y + translation.Y >= top) & (y + translation.Y <= middle))
135166
{
@@ -169,16 +200,28 @@ private void CreateViewFrame(BottomSheetState state)
169200
{
170201
View.Frame = new CGRect(0, top, View.Frame.Width, View.Frame.Height);
171202
currentState = BottomSheetState.Top;
203+
UpdateContentFrame(top);
172204
}
173205
else if (state == BottomSheetState.Middle)
174206
{
175207
View.Frame = new CGRect(0, middle, View.Frame.Width, View.Frame.Height);
176208
currentState = BottomSheetState.Middle;
209+
UpdateContentFrame(middle);
177210
}
178211
else if (state == BottomSheetState.Bottom)
179212
{
180213
View.Frame = new CGRect(0, bottom, View.Frame.Width, View.Frame.Height);
181214
currentState = BottomSheetState.Bottom;
215+
UpdateContentFrame(bottom);
216+
}
217+
}
218+
219+
private void UpdateContentFrame(nfloat height)
220+
{
221+
if (View.Subviews.Any())
222+
{
223+
var x = View.Subviews[0] as BottomSheetContentView;
224+
x.AdjustContentFrame(View.Frame, startHeight, height);
182225
}
183226
}
184227

@@ -188,6 +231,7 @@ private void CreateViewFrameForSingleState(nfloat endTapLocation)
188231
Hide(false);
189232
View.Frame = new CGRect(0, middle, View.Frame.Width, View.Frame.Height);
190233
currentState = BottomSheetState.Middle;
234+
UpdateContentFrame(middle);
191235
}
192236
}
193237
}

0 commit comments

Comments
 (0)