Skip to content
This repository was archived by the owner on Oct 12, 2023. It is now read-only.

Commit abac0fd

Browse files
author
Mitsuyoshi Yamazaki
committed
Make upperContentView expandable and shrinkable
1 parent bdf0ed0 commit abac0fd

12 files changed

+53
-84
lines changed

ScrollableTabControllerDemo/Assets.xcassets/Button.imageset/Contents.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
},
1111
{
1212
"idiom" : "universal",
13-
"filename" : "Group 13@3x.png",
13+
"filename" : "Rectangle 17 Copy@3x.png",
1414
"scale" : "3x"
1515
}
1616
],
Loading

ScrollableTabControllerDemo/Assets.xcassets/CoverImage.imageset/Contents.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
},
1111
{
1212
"idiom" : "universal",
13-
"filename" : "cover@3x.png",
13+
"filename" : "night@3x.png",
1414
"scale" : "3x"
1515
}
1616
],
Loading

ScrollableTabControllerDemo/Assets.xcassets/Icon.imageset/Contents.json

Lines changed: 0 additions & 21 deletions
This file was deleted.
Binary file not shown.

ScrollableTabControllerDemo/Base.lproj/Main.storyboard

Lines changed: 24 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -302,72 +302,62 @@
302302
<viewControllerLayoutGuide type="bottom" id="oIZ-ET-Mfc"/>
303303
</layoutGuides>
304304
<view key="view" contentMode="scaleToFill" id="6C0-T8-iKZ" customClass="TouchTransparentView" customModule="ScrollableTabController">
305-
<rect key="frame" x="0.0" y="0.0" width="375" height="306"/>
305+
<rect key="frame" x="0.0" y="0.0" width="375" height="266"/>
306306
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
307307
<subviews>
308308
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="PlaceholderText" translatesAutoresizingMaskIntoConstraints="NO" id="oK0-vS-19c">
309-
<rect key="frame" x="0.0" y="172" width="375" height="134"/>
309+
<rect key="frame" x="0.0" y="132" width="375" height="134"/>
310310
<constraints>
311311
<constraint firstAttribute="width" secondItem="oK0-vS-19c" secondAttribute="height" multiplier="375:134" id="Byr-ru-HYc"/>
312312
</constraints>
313313
</imageView>
314314
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="CoverImage" translatesAutoresizingMaskIntoConstraints="NO" id="QKZ-51-tv9">
315-
<rect key="frame" x="0.0" y="0.0" width="375" height="125"/>
315+
<rect key="frame" x="0.0" y="0.0" width="375" height="124"/>
316316
<constraints>
317317
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="64" id="Nys-lq-XgK"/>
318-
<constraint firstAttribute="height" relation="greaterThanOrEqual" priority="800" constant="125" id="chn-qF-jwq"/>
318+
<constraint firstAttribute="height" relation="greaterThanOrEqual" priority="910" constant="125" id="chn-qF-jwq"/>
319319
</constraints>
320320
</imageView>
321-
<view userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="yNL-6a-pT5">
322-
<rect key="frame" x="0.0" y="0.0" width="375" height="125"/>
321+
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="yNL-6a-pT5" userLabel="Mask View" customClass="TouchTransparentView" customModule="ScrollableTabController">
322+
<rect key="frame" x="0.0" y="0.0" width="375" height="124"/>
323323
<subviews>
324-
<visualEffectView opaque="NO" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="aBp-hx-yGq">
325-
<rect key="frame" x="0.0" y="0.0" width="375" height="64"/>
326-
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="F3B-Pf-V5F">
327-
<rect key="frame" x="0.0" y="0.0" width="375" height="64"/>
324+
<visualEffectView opaque="NO" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="bGy-k3-8Sa">
325+
<rect key="frame" x="0.0" y="0.0" width="375" height="124"/>
326+
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="hL9-lg-hul">
327+
<rect key="frame" x="0.0" y="0.0" width="375" height="124"/>
328328
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
329329
</view>
330-
<constraints>
331-
<constraint firstAttribute="height" constant="64" id="5Ch-ZH-HtS"/>
332-
</constraints>
333330
<blurEffect style="dark"/>
334331
</visualEffectView>
335-
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="vzI-tI-DDu">
336-
<rect key="frame" x="337" y="27" width="30" height="30"/>
332+
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="vzI-tI-DDu">
333+
<rect key="frame" x="335" y="30" width="24" height="24"/>
337334
<constraints>
338-
<constraint firstAttribute="width" constant="30" id="F0r-D0-uxF"/>
335+
<constraint firstAttribute="width" constant="24" id="F0r-D0-uxF"/>
339336
<constraint firstAttribute="width" secondItem="vzI-tI-DDu" secondAttribute="height" multiplier="1:1" id="THK-A2-Zsn"/>
340337
</constraints>
338+
<color key="tintColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
341339
<state key="normal" image="Button"/>
342340
</button>
343341
</subviews>
344342
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.14999999999999999" colorSpace="calibratedRGB"/>
345343
<constraints>
346-
<constraint firstItem="vzI-tI-DDu" firstAttribute="centerY" secondItem="aBp-hx-yGq" secondAttribute="centerY" constant="10" id="5IJ-R4-t67"/>
347-
<constraint firstItem="aBp-hx-yGq" firstAttribute="leading" secondItem="yNL-6a-pT5" secondAttribute="leading" id="Mtr-fk-vHf"/>
348-
<constraint firstAttribute="trailing" secondItem="vzI-tI-DDu" secondAttribute="trailing" constant="8" id="iQV-ku-zV3"/>
349-
<constraint firstAttribute="trailing" secondItem="aBp-hx-yGq" secondAttribute="trailing" id="k4E-yS-asj"/>
350-
<constraint firstItem="aBp-hx-yGq" firstAttribute="top" secondItem="yNL-6a-pT5" secondAttribute="top" id="kI8-EH-Agy"/>
344+
<constraint firstItem="bGy-k3-8Sa" firstAttribute="top" secondItem="yNL-6a-pT5" secondAttribute="top" id="7KM-cz-Sbq"/>
345+
<constraint firstAttribute="bottom" secondItem="bGy-k3-8Sa" secondAttribute="bottom" id="FOe-Mg-sM7"/>
346+
<constraint firstItem="vzI-tI-DDu" firstAttribute="top" secondItem="yNL-6a-pT5" secondAttribute="top" constant="30" id="QNI-fP-wdn"/>
347+
<constraint firstAttribute="trailing" secondItem="bGy-k3-8Sa" secondAttribute="trailing" id="cZk-C3-3zZ"/>
348+
<constraint firstItem="bGy-k3-8Sa" firstAttribute="leading" secondItem="yNL-6a-pT5" secondAttribute="leading" id="hCa-lC-u9n"/>
349+
<constraint firstAttribute="trailing" secondItem="vzI-tI-DDu" secondAttribute="trailing" constant="16" id="iQV-ku-zV3"/>
351350
</constraints>
352351
</view>
353-
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Icon" translatesAutoresizingMaskIntoConstraints="NO" id="Bb7-Qw-p5l">
354-
<rect key="frame" x="8" y="97" width="75" height="75"/>
355-
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
356-
<constraints>
357-
<constraint firstAttribute="width" constant="75" id="VqX-84-vYW"/>
358-
<constraint firstAttribute="width" secondItem="Bb7-Qw-p5l" secondAttribute="height" id="gu1-AH-hqM"/>
359-
</constraints>
360-
</imageView>
361352
</subviews>
362353
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
363354
<constraints>
364355
<constraint firstItem="yNL-6a-pT5" firstAttribute="top" secondItem="QKZ-51-tv9" secondAttribute="top" id="1rL-SJ-O34"/>
365-
<constraint firstItem="oK0-vS-19c" firstAttribute="top" secondItem="Bb7-Qw-p5l" secondAttribute="bottom" id="2h9-8N-nME"/>
366-
<constraint firstItem="Bb7-Qw-p5l" firstAttribute="leading" secondItem="6C0-T8-iKZ" secondAttribute="leading" constant="8" id="3Il-Ii-oos"/>
367356
<constraint firstAttribute="trailing" secondItem="QKZ-51-tv9" secondAttribute="trailing" id="3O6-gp-gdg"/>
368357
<constraint firstItem="yNL-6a-pT5" firstAttribute="trailing" secondItem="QKZ-51-tv9" secondAttribute="trailing" id="5S6-fR-n8G"/>
369-
<constraint firstItem="Bb7-Qw-p5l" firstAttribute="top" secondItem="QKZ-51-tv9" secondAttribute="bottom" constant="-28" id="Hm0-Wp-K6S"/>
370358
<constraint firstAttribute="trailing" secondItem="oK0-vS-19c" secondAttribute="trailing" id="KwG-PG-46Y"/>
359+
<constraint firstItem="oK0-vS-19c" firstAttribute="top" secondItem="QKZ-51-tv9" secondAttribute="bottom" priority="920" constant="8" id="L5T-w2-v9N"/>
360+
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="QKZ-51-tv9" secondAttribute="bottom" id="cV2-4V-bKf"/>
371361
<constraint firstItem="yNL-6a-pT5" firstAttribute="leading" secondItem="QKZ-51-tv9" secondAttribute="leading" id="dcx-9G-6Dt"/>
372362
<constraint firstItem="yNL-6a-pT5" firstAttribute="bottom" secondItem="QKZ-51-tv9" secondAttribute="bottom" id="gm4-3J-gzc"/>
373363
<constraint firstItem="oIZ-ET-Mfc" firstAttribute="top" secondItem="oK0-vS-19c" secondAttribute="bottom" id="mDd-HU-Zgk"/>
@@ -377,10 +367,10 @@
377367
</constraints>
378368
</view>
379369
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
380-
<size key="freeformSize" width="375" height="306"/>
370+
<size key="freeformSize" width="375" height="266"/>
381371
<connections>
372+
<outlet property="blurEffectView" destination="bGy-k3-8Sa" id="tup-TS-vtv"/>
382373
<outlet property="coverImageView" destination="QKZ-51-tv9" id="5ig-1c-2j6"/>
383-
<outlet property="iconImageView" destination="Bb7-Qw-p5l" id="eXK-Q8-oEn"/>
384374
</connections>
385375
</viewController>
386376
<placeholder placeholderIdentifier="IBFirstResponder" id="h0U-ZZ-BQp" userLabel="First Responder" sceneMemberID="firstResponder"/>
@@ -391,7 +381,6 @@
391381
<resources>
392382
<image name="Button" width="33" height="33"/>
393383
<image name="CoverImage" width="375" height="125"/>
394-
<image name="Icon" width="75" height="75"/>
395384
<image name="PlaceholderText" width="750" height="268"/>
396385
</resources>
397386
</document>

ScrollableTabControllerDemo/ProfileViewController.swift

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,7 @@ import ScrollableTabController
1313
class ProfileViewController: UIViewController {
1414

1515
@IBOutlet private weak var coverImageView: UIImageView!
16-
@IBOutlet private weak var iconImageView: UIImageView! {
17-
didSet {
18-
iconImageView.layer.borderWidth = 4.0
19-
iconImageView.layer.borderColor = UIColor.white.cgColor
20-
iconImageView.layer.cornerRadius = iconImageView.bounds.size.width / 2.0
21-
}
22-
}
23-
@IBOutlet private weak var screenNameLabel: UILabel!
16+
@IBOutlet private weak var blurEffectView: UIVisualEffectView!
2417

2518
// MARK: - Lifecycle
2619
override var preferredStatusBarStyle: UIStatusBarStyle {
@@ -35,10 +28,14 @@ class ProfileViewController: UIViewController {
3528
super.viewWillAppear(animated)
3629
navigationController?.setNavigationBarHidden(true, animated: true)
3730
}
38-
}
39-
40-
extension ProfileViewController: ShrinkableContent {
41-
var minimumHeight: CGFloat? {
42-
return 64.0
31+
32+
override func viewDidLayoutSubviews() {
33+
super.viewDidLayoutSubviews()
34+
35+
let defaultHeight: CGFloat = 266.0
36+
let minimumHeight: CGFloat = 64.0
37+
let transparency = min((view.frame.height - minimumHeight) / (defaultHeight - minimumHeight), 1.0)
38+
39+
blurEffectView?.alpha = CGFloat(1.0) - transparency
4340
}
4441
}

Source/ScrollableTabController.swift

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,6 @@
88

99
import UIKit
1010

11-
public protocol ShrinkableContent {
12-
var minimumHeight: CGFloat? { get }
13-
}
14-
extension ShrinkableContent {
15-
var minimumHeight: CGFloat? {
16-
return nil
17-
}
18-
}
19-
2011
public protocol Scrollable {
2112
var scrollView: UIScrollView! { get }
2213
}
@@ -174,8 +165,13 @@ public final class ScrollableTabController: UIViewController {
174165
}
175166

176167
@IBOutlet private weak var tabView: UIView!
177-
@IBOutlet private weak var tabViewTopConstraint: NSLayoutConstraint!
178168
@IBOutlet private weak var tabContentView: UIView!
169+
@IBOutlet private weak var tabViewTopConstraint: NSLayoutConstraint! {
170+
didSet {
171+
let temp = didLayoutUpperContent
172+
didLayoutUpperContent = temp
173+
}
174+
}
179175

180176
private var topScrollableContentViewController: Scrollable? {
181177
guard let scrollable = selectedViewController as? Scrollable else {
@@ -201,7 +197,15 @@ public final class ScrollableTabController: UIViewController {
201197
}
202198
private var isUpperViewSizeFixed = false
203199
private var shouldIgnoreOffsetChange = false
204-
private var didLayoutUpperContent = false
200+
private var didLayoutUpperContent = false {
201+
didSet {
202+
if didLayoutUpperContent {
203+
tabViewTopConstraint?.priority = 950
204+
} else {
205+
tabViewTopConstraint?.priority = 900
206+
}
207+
}
208+
}
205209

206210
// MARK: - Lifecycle
207211
public override var preferredStatusBarStyle: UIStatusBarStyle {
@@ -381,7 +385,7 @@ public final class ScrollableTabController: UIViewController {
381385
private func observeScrollViewOffset(_ offsetY: CGFloat) {
382386

383387
let offset = -(tabViewHeight + offsetY)
384-
let maxValue = (upperContentViewController as? ShrinkableContent)?.minimumHeight ?? CGFloat(0.0)
388+
let maxValue = CGFloat(0.0)
385389
let constant = max(offset, maxValue)
386390

387391
guard constant != tabViewTopConstraint.constant else {

Source/ScrollableTabController.xib

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070
<constraint firstItem="XgL-wa-MXe" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" priority="900" id="VHt-h1-wIf"/>
7171
<constraint firstItem="DwG-43-7sk" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="Vcs-uo-rq5"/>
7272
<constraint firstItem="XgL-wa-MXe" firstAttribute="top" secondItem="3UM-PZ-OGQ" secondAttribute="bottom" id="eHm-tr-TPa"/>
73-
<constraint firstItem="3UM-PZ-OGQ" firstAttribute="top" relation="lessThanOrEqual" secondItem="iN0-l3-epB" secondAttribute="top" id="jt7-PS-LcE"/>
73+
<constraint firstItem="3UM-PZ-OGQ" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="jt7-PS-LcE"/>
7474
<constraint firstItem="DwG-43-7sk" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="sgR-CD-iOf"/>
7575
<constraint firstItem="3UM-PZ-OGQ" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="wtt-bh-HE6"/>
7676
<constraint firstItem="XgL-wa-MXe" firstAttribute="top" relation="greaterThanOrEqual" secondItem="3UM-PZ-OGQ" secondAttribute="bottom" id="y7x-xN-elp"/>

0 commit comments

Comments
 (0)