Adds dynamic segment positioning type where cells size varies based on content

This commit is contained in:
Max Campolo 2016-12-18 16:39:12 -05:00
parent e46a86115d
commit 19a6e00996
18 changed files with 94 additions and 59 deletions

View File

@ -1,16 +1,16 @@
PODS:
- Segmentio (1.1.3)
- Segmentio (2.1.1)
DEPENDENCIES:
- Segmentio (from `../`)
EXTERNAL SOURCES:
Segmentio:
:path: "../"
:path: ../
SPEC CHECKSUMS:
Segmentio: f784171237bcbb4854f338aef8162e312f4ac5b8
Segmentio: fc7d724a2394d62367ac766b88b8e05d8edda012
PODFILE CHECKSUM: 761653fe0a6001fe4076ba25b04e279672ecc970
COCOAPODS: 1.1.0.rc.2
COCOAPODS: 1.1.0.rc.3

View File

@ -1,6 +1,6 @@
{
"name": "Segmentio",
"version": "1.1.3",
"version": "2.1.1",
"homepage": "https://github.com/Yalantis/Segmentio",
"summary": "Animated top/bottom segmented control written in Swift!",
"screenshots": "https://raw.githubusercontent.com/Yalantis/Segmentio/master/Assets/animation.gif",
@ -15,7 +15,7 @@
},
"source": {
"git": "https://github.com/Yalantis/Segmentio.git",
"tag": "1.1.3"
"tag": "2.1.1"
},
"source_files": "Segmentio/Source/**/*.swift",
"resources": "Segmentio/Source/Badge/Views/*.xib",

View File

@ -1,16 +1,16 @@
PODS:
- Segmentio (1.1.3)
- Segmentio (2.1.1)
DEPENDENCIES:
- Segmentio (from `../`)
EXTERNAL SOURCES:
Segmentio:
:path: "../"
:path: ../
SPEC CHECKSUMS:
Segmentio: f784171237bcbb4854f338aef8162e312f4ac5b8
Segmentio: fc7d724a2394d62367ac766b88b8e05d8edda012
PODFILE CHECKSUM: 761653fe0a6001fe4076ba25b04e279672ecc970
COCOAPODS: 1.1.0.rc.2
COCOAPODS: 1.1.0.rc.3

View File

@ -5,7 +5,7 @@ This application makes use of the following third party libraries:
The MIT License (MIT)
Copyright © 2015 Yalantis
Copyright © 2016 Yalantis
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -24,4 +24,5 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Generated by CocoaPods - https://cocoapods.org

View File

@ -16,7 +16,7 @@
<key>FooterText</key>
<string>The MIT License (MIT)
Copyright &#169; 2015 Yalantis
Copyright &#169; 2016 Yalantis
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -34,7 +34,8 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.</string>
THE SOFTWARE.
</string>
<key>License</key>
<string>MIT</string>
<key>Title</key>

View File

@ -23,12 +23,6 @@ case "${TARGETED_DEVICE_FAMILY}" in
;;
esac
realpath() {
DIRECTORY="$(cd "${1%/*}" && pwd)"
FILENAME="${1##*/}"
echo "$DIRECTORY/$FILENAME"
}
install_resource()
{
if [[ "$1" = /* ]] ; then
@ -70,7 +64,7 @@ EOM
xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm"
;;
*.xcassets)
ABSOLUTE_XCASSET_FILE=$(realpath "$RESOURCE_PATH")
ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH"
XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE")
;;
*)
@ -93,7 +87,7 @@ then
# Find all other xcassets (this unfortunately includes those of path pods and other targets).
OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
while read line; do
if [[ $line != "`realpath $PODS_ROOT`*" ]]; then
if [[ $line != "${PODS_ROOT}*" ]]; then
XCASSET_FILES+=("$line")
fi
done <<<"$OTHER_XCASSETS"

View File

@ -1,4 +1,6 @@
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif
FOUNDATION_EXPORT double Pods_Segmentio_ExampleVersionNumber;

View File

@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.1.3</string>
<string>2.1.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>

View File

@ -13,7 +13,7 @@
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.1.3</string>
<string>2.1.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>

View File

@ -1,4 +1,6 @@
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif
FOUNDATION_EXPORT double SegmentioVersionNumber;

View File

@ -49,7 +49,7 @@ struct SegmentioBuilder {
return SegmentioOptions(
backgroundColor: ColorPalette.white,
maxVisibleItems: 3,
segmentPosition: .fixed(maxVisibleItems: 3),
scrollEnabled: true,
indicatorOptions: segmentioIndicatorOptions(),
horizontalSeparatorOptions: segmentioHorizontalSeparatorOptions(),

View File

@ -1,5 +1,15 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
@ -36,6 +46,16 @@
"filename" : "Icon-60@3x.png",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",

View File

@ -11,7 +11,7 @@ import UIKit
class SegmentioCell: UICollectionViewCell {
let padding: CGFloat = 8
let segmentTitleLabelHeight: CGFloat = 22
static let segmentTitleLabelHeight: CGFloat = 22
var verticalSeparatorView: UIView?
var segmentTitleLabel: UILabel?

View File

@ -19,7 +19,7 @@ final class SegmentioCellWithImageAfterLabel: SegmentioCell {
return
}
let metrics = ["labelHeight": segmentTitleLabelHeight]
let metrics = ["labelHeight": SegmentioCell.segmentTitleLabelHeight]
let views = [
"imageContainerView": imageContainerView,
"containerView": containerView

View File

@ -19,7 +19,7 @@ class SegmentioCellWithImageBeforeLabel: SegmentioCell {
return
}
let metrics = ["labelHeight": segmentTitleLabelHeight]
let metrics = ["labelHeight": SegmentioCell.segmentTitleLabelHeight]
let views = [
"imageContainerView": imageContainerView,
"containerView": containerView

View File

@ -19,7 +19,7 @@ class SegmentioCellWithImageOverLabel: SegmentioCell {
return
}
let metrics = ["labelHeight": segmentTitleLabelHeight]
let metrics = ["labelHeight": SegmentioCell.segmentTitleLabelHeight]
let views = [
"imageContainerView": imageContainerView,
"containerView": containerView

View File

@ -19,7 +19,7 @@ class SegmentioCellWithImageUnderLabel: SegmentioCell {
return
}
let metrics = ["labelHeight": segmentTitleLabelHeight]
let metrics = ["labelHeight": SegmentioCell.segmentTitleLabelHeight]
let views = [
"imageContainerView": imageContainerView,
"containerView": containerView

View File

@ -49,6 +49,7 @@ open class Segmentio: UIView {
fileprivate var segmentioOptions = SegmentioOptions()
fileprivate var segmentioStyle = SegmentioStyle.imageOverLabel
fileprivate var isPerformingScrollAnimation = false
fileprivate var isCollectionViewScrolling = false
fileprivate var topSeparatorView: UIView?
fileprivate var bottomSeparatorView: UIView?
@ -324,6 +325,7 @@ open class Segmentio: UIView {
public func reloadSegmentio() {
segmentioCollectionView?.collectionViewLayout.invalidateLayout()
segmentioCollectionView?.reloadData()
guard selectedSegmentioIndex != -1 else { return }
scrollToItemAtContext()
moveShapeLayerAtContext()
}
@ -335,7 +337,7 @@ open class Segmentio: UIView {
let item = itemInSuperview(ratio: options.ratio)
let context = contextForItem(item)
let points = Points(context: context, item: item, atIndex: selectedSegmentioIndex, allItems: segmentioItems, pointY: indicatorPointY(), position: segmentioOptions.segmentPosition)
let points = Points(context: context, item: item, atIndex: selectedSegmentioIndex, allItems: segmentioItems, pointY: indicatorPointY(), position: segmentioOptions.segmentPosition, style: segmentioStyle)
moveShapeLayer(
indicatorLayer,
@ -349,7 +351,7 @@ open class Segmentio: UIView {
let item = itemInSuperview()
let context = contextForItem(item)
let points = Points(context: context, item: item, atIndex: selectedSegmentioIndex, allItems: segmentioItems, pointY: bounds.midY, position: segmentioOptions.segmentPosition)
let points = Points(context: context, item: item, atIndex: selectedSegmentioIndex, allItems: segmentioItems, pointY: bounds.midY, position: segmentioOptions.segmentPosition, style: segmentioStyle)
moveShapeLayer(
selectedLayer,
@ -366,30 +368,30 @@ open class Segmentio: UIView {
guard let numberOfSections = segmentioCollectionView?.numberOfSections else {
return
}
guard selectedSegmentioIndex != -1 else { return }
let item = itemInSuperview()
let context = contextForItem(item)
if context.isLastOrPrelastVisibleCell == true && selectedSegmentioIndex != -1 {
let newIndex = selectedSegmentioIndex + (context.isLastCell ? 0 : 1)
let newIndexPath = IndexPath(item: newIndex, section: numberOfSections - 1)
segmentioCollectionView?.scrollToItem(
at: newIndexPath,
at: UICollectionViewScrollPosition(),
animated: true
)
}
if context.isFirstOrSecondVisibleCell == true && selectedSegmentioIndex != -1 {
let newIndex = selectedSegmentioIndex - (context.isFirstIndex ? 1 : 0)
let newIndexPath = IndexPath(item: newIndex, section: numberOfSections - 1)
segmentioCollectionView?.scrollToItem(
at: newIndexPath,
at: UICollectionViewScrollPosition(),
animated: true
)
segmentioCollectionView?.scrollRectToVisible(centerRect(for: item), animated: true)
}
fileprivate func centerRect(for item: ItemInSuperview) -> CGRect {
let item = itemInSuperview()
var centerRect = item.cellFrameInSuperview
if (item.startX + segmentioCollectionView!.contentOffset.x) - (item.collectionViewWidth - centerRect.width) / 2 < 0 {
centerRect.origin.x = 0
var widthToAdd: CGFloat = (item.collectionViewWidth - centerRect.width)
centerRect.size.width += widthToAdd
} else if segmentioCollectionView!.contentSize.width - item.endX < (item.collectionViewWidth - centerRect.width) / 2 {
centerRect.origin.x = segmentioCollectionView!.contentSize.width - item.collectionViewWidth
centerRect.size.width = item.collectionViewWidth
} else {
centerRect.origin.x = item.startX - (item.collectionViewWidth - centerRect.width) / 2 + segmentioCollectionView!.contentOffset.x
centerRect.size.width = item.collectionViewWidth
}
return centerRect
}
// MARK: Move shape layer
@ -455,7 +457,7 @@ open class Segmentio: UIView {
var cellRect = CGRect.zero
var shapeLayerWidth: CGFloat = 0
if let collectionView = segmentioCollectionView {
if let collectionView = segmentioCollectionView, selectedSegmentioIndex != -1 {
collectionViewWidth = collectionView.frame.width
cellWidth = segmentWidth(for: IndexPath(row: selectedSegmentioIndex, section: 0))
var x: CGFloat = 0
@ -506,14 +508,23 @@ open class Segmentio: UIView {
}
var dynamicWidth: CGFloat = 0
for item in segmentioItems {
dynamicWidth += item.intrinsicWidth
dynamicWidth += Segmentio.intrinsicWidth(for: item, style: segmentioStyle)
}
width = dynamicWidth > collectionViewWidth ? segmentioItems[indexPath.row].intrinsicWidth : segmentioItems[indexPath.row].intrinsicWidth + ((collectionViewWidth - dynamicWidth) / CGFloat(segmentioItems.count))
let itemWidth = Segmentio.intrinsicWidth(for: segmentioItems[indexPath.row], style: segmentioStyle)
width = dynamicWidth > collectionViewWidth ? itemWidth : itemWidth + ((collectionViewWidth - dynamicWidth) / CGFloat(segmentioItems.count))
}
}
return width
}
fileprivate static func intrinsicWidth(for item: SegmentioItem, style: SegmentioStyle) -> CGFloat {
var itemWidth: CGFloat = item.intrinsicWidth
if style == .imageAfterLabel || style == .imageBeforeLabel {
itemWidth += SegmentioCell.segmentTitleLabelHeight
}
return itemWidth
}
// MARK: - Indicator point Y
fileprivate func indicatorPointY() -> CGFloat {
@ -634,12 +645,16 @@ extension Segmentio: UIScrollViewDelegate {
)
}
}
public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
isCollectionViewScrolling = false
}
}
extension Segmentio.Points {
init(context: Segmentio.Context, item: Segmentio.ItemInSuperview, atIndex index: Int, allItems: [SegmentioItem], pointY: CGFloat, position: SegmentioPosition) {
init(context: Segmentio.Context, item: Segmentio.ItemInSuperview, atIndex index: Int, allItems: [SegmentioItem], pointY: CGFloat, position: SegmentioPosition, style: SegmentioStyle) {
let cellWidth = item.cellFrameInSuperview.width
var startX = item.startX
@ -677,7 +692,7 @@ extension Segmentio.Points {
// We have to calculate the final position of the item
var dynamicWidth: CGFloat = 0
for item in allItems {
dynamicWidth += item.intrinsicWidth
dynamicWidth += Segmentio.intrinsicWidth(for: item, style: style)
}
if item.collectionViewWidth < dynamicWidth {
startX = 0
@ -687,9 +702,9 @@ extension Segmentio.Points {
var i = 0
for item in allItems {
if i < index {
spaceBefore += item.intrinsicWidth
spaceBefore += Segmentio.intrinsicWidth(for: item, style: style)
} else if i > index {
spaceAfter += item.intrinsicWidth
spaceAfter += Segmentio.intrinsicWidth(for: item, style: style)
}
i += 1
}