adds TwitterPagerTabStripViewController & example

This commit is contained in:
Santiago Fernandez 2016-01-22 15:23:54 -03:00
parent aec1610fcb
commit e7dedcd42c
8 changed files with 855 additions and 4 deletions

View File

@ -12,6 +12,7 @@
287D0A7E1C4B7B55004566D6 /* XLPagerTabStrip.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 287D0A7A1C4B7B26004566D6 /* XLPagerTabStrip.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
28F828D01C4B714D00330CF4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28F828CF1C4B714D00330CF4 /* AppDelegate.swift */; };
28F828DA1C4B714D00330CF4 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 28F828D81C4B714D00330CF4 /* LaunchScreen.storyboard */; };
CB2125DE1C52A80E002DAF42 /* TwitterExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB2125DD1C52A80E002DAF42 /* TwitterExampleViewController.swift */; };
CB3697BF1C5177B4001FC5F8 /* ButtonBarExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB3697BE1C5177B4001FC5F8 /* ButtonBarExampleViewController.swift */; };
CB71C6EB1C4EB964008EC806 /* SegmentedExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB71C6EA1C4EB964008EC806 /* SegmentedExampleViewController.swift */; };
CB71C6F31C4FDDCE008EC806 /* PostCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB71C6F21C4FDDCE008EC806 /* PostCell.swift */; };
@ -81,6 +82,7 @@
28F828DB1C4B714D00330CF4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Example/Info.plist; sourceTree = "<group>"; };
28F828E01C4B714D00330CF4 /* ExampleUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ExampleUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
28F828E61C4B714D00330CF4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; name = Info.plist; path = Example/ExampleUITests/Info.plist; sourceTree = "<group>"; };
CB2125DD1C52A80E002DAF42 /* TwitterExampleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TwitterExampleViewController.swift; path = Example/TwitterExampleViewController.swift; sourceTree = "<group>"; };
CB3697BE1C5177B4001FC5F8 /* ButtonBarExampleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ButtonBarExampleViewController.swift; path = Example/Example/ButtonBarExampleViewController.swift; sourceTree = SOURCE_ROOT; };
CB71C6EA1C4EB964008EC806 /* SegmentedExampleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SegmentedExampleViewController.swift; path = Example/SegmentedExampleViewController.swift; sourceTree = "<group>"; };
CB71C6F21C4FDDCE008EC806 /* PostCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PostCell.swift; path = Example/PostCell.swift; sourceTree = "<group>"; };
@ -178,6 +180,7 @@
CBA0A1FE1C50304500C5748C /* BarExampleViewController.swift */,
CBA0A2031C5033B400C5748C /* ReloadExampleViewController.swift */,
CBBD435E1C5274AE001A748E /* NavButtonBarExampleViewController.swift */,
CB2125DD1C52A80E002DAF42 /* TwitterExampleViewController.swift */,
);
name = Demo;
sourceTree = "<group>";
@ -325,6 +328,7 @@
CBA0A2041C5033B400C5748C /* ReloadExampleViewController.swift in Sources */,
CB3697BF1C5177B4001FC5F8 /* ButtonBarExampleViewController.swift in Sources */,
CBA0A1FF1C50304500C5748C /* BarExampleViewController.swift in Sources */,
CB2125DE1C52A80E002DAF42 /* TwitterExampleViewController.swift in Sources */,
CBBD435F1C5274AE001A748E /* NavButtonBarExampleViewController.swift in Sources */,
CB86ED8A1C4D712200DA463B /* ChildExampleViewController.swift in Sources */,
CB86ED8E1C4D7A1800DA463B /* TableChildExampleViewController.swift in Sources */,

View File

@ -0,0 +1,54 @@
//
// TwitterExampleViewController.swift
// Example
//
// Created by Santiago on 1/22/16.
//
//
import Foundation
import XLPagerTabStrip
public class TwitterExampleViewController: TwitterPagerTabStripViewController {
var isReload = false
public override func viewDidLoad() {
super.viewDidLoad()
pagerOptions = pagerOptions.union(.IsProgressiveIndicator)
pagerOptions = pagerOptions.union(.IsElasticIndicatorLimit)
}
public override func childViewControllersForPagerTabStripViewController(pagerTabStripController: PagerTabStripViewController) -> [UIViewController] {
let child_1 = TableChildExampleViewController(style: .Plain)
let child_2 = ChildExampleViewController()
let child_3 = TableChildExampleViewController(style: .Grouped)
let child_4 = ChildExampleViewController()
let child_5 = TableChildExampleViewController(style: .Plain)
let child_6 = ChildExampleViewController()
let child_7 = TableChildExampleViewController(style: .Grouped)
let child_8 = ChildExampleViewController()
guard isReload else {
return [child_1, child_2, child_3, child_4, child_5, child_6, child_7, child_8]
}
var childViewControllers = [child_1, child_2, child_3, child_4, child_6, child_7, child_8] as Array
let count = childViewControllers.count
for (index, _) in childViewControllers.enumerate(){
let nElements = count - index
let n = (Int(arc4random()) % nElements) + index
if n != index{
swap(&childViewControllers[index], &childViewControllers[n])
}
}
let nItems = 1 + (rand() % 8)
return Array(childViewControllers.prefix(Int(nItems)))
}
@IBAction func reloadTapped(sender: AnyObject) {
isReload = true
reloadPagerTabStripView()
}
}

View File

@ -232,6 +232,7 @@
<segue destination="g7J-zS-0bu" kind="relationship" relationship="viewControllers" id="WG0-Of-C4e"/>
<segue destination="jWp-2W-r7X" kind="relationship" relationship="viewControllers" id="uoj-hE-05b"/>
<segue destination="b3c-Kr-Yhe" kind="relationship" relationship="viewControllers" id="xMr-zV-ubn"/>
<segue destination="uPL-4b-W3j" kind="relationship" relationship="viewControllers" id="klw-Rc-meT"/>
</connections>
</tabBarController>
<placeholder placeholderIdentifier="IBFirstResponder" id="YsA-SS-Qae" userLabel="First Responder" sceneMemberID="firstResponder"/>
@ -366,17 +367,17 @@
<!--Twitter Example View Controller-->
<scene sceneID="Zfp-Dk-WxL">
<objects>
<viewController id="Vhq-do-uI2" customClass="TwitterExampleViewController" sceneMemberID="viewController">
<viewController id="Vhq-do-uI2" customClass="TwitterExampleViewController" customModule="Example" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="OfJ-gb-drI"/>
<viewControllerLayoutGuide type="bottom" id="64r-dM-ghd"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Eak-dg-otx">
<rect key="frame" x="0.0" y="64" width="600" height="536"/>
<rect key="frame" x="0.0" y="64" width="600" height="487"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="A96-PT-Aon">
<rect key="frame" x="0.0" y="0.0" width="600" height="536"/>
<rect key="frame" x="0.0" y="0.0" width="600" height="487"/>
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="calibratedRGB"/>
</scrollView>
</subviews>
@ -394,7 +395,7 @@
<barButtonItem key="rightBarButtonItem" systemItem="refresh" id="mhz-8g-Ux7">
<color key="tintColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<connections>
<action selector="reloadTapped:" destination="Vhq-do-uI2" id="C47-dn-jtz"/>
<action selector="reloadTapped:" destination="Vhq-do-uI2" id="fx6-UJ-VG1"/>
</connections>
</barButtonItem>
</navigationItem>

106
Sources/FXPageControl.h Executable file
View File

@ -0,0 +1,106 @@
//
// FXPageControl.h
//
// Version 1.4
//
// Created by Nick Lockwood on 07/01/2010.
// Copyright 2010 Charcoal Design
//
// Distributed under the permissive zlib License
// Get the latest version of FXPageControl from here:
//
// https://github.com/nicklockwood/FXPageControl
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wobjc-missing-property-synthesis"
#import <UIKit/UIKit.h>
#import <Availability.h>
#undef weak_delegate
#if __has_feature(objc_arc_weak)
#define weak_delegate weak
#else
#define weak_delegate unsafe_unretained
#endif
extern const CGPathRef FXPageControlDotShapeCircle;
extern const CGPathRef FXPageControlDotShapeSquare;
extern const CGPathRef FXPageControlDotShapeTriangle;
@protocol FXPageControlDelegate;
IB_DESIGNABLE @interface FXPageControl : UIControl
- (void)setUp;
- (CGSize)sizeForNumberOfPages:(NSInteger)pageCount;
- (void)updateCurrentPageDisplay;
@property (nonatomic, weak_delegate) IBOutlet id <FXPageControlDelegate> delegate;
@property (nonatomic, assign) IBInspectable NSInteger currentPage;
@property (nonatomic, assign) IBInspectable NSInteger numberOfPages;
@property (nonatomic, assign) IBInspectable BOOL defersCurrentPageDisplay;
@property (nonatomic, assign) IBInspectable BOOL hidesForSinglePage;
@property (nonatomic, assign, getter = isWrapEnabled) IBInspectable BOOL wrapEnabled;
@property (nonatomic, assign, getter = isVertical) IBInspectable BOOL vertical;
@property (nonatomic, strong) IBInspectable UIImage *dotImage;
@property (nonatomic, assign) IBInspectable CGPathRef dotShape;
@property (nonatomic, assign) IBInspectable CGFloat dotSize;
@property (nonatomic, strong) IBInspectable UIColor *dotColor;
@property (nonatomic, strong) IBInspectable UIColor *dotShadowColor;
@property (nonatomic, assign) IBInspectable CGFloat dotShadowBlur;
@property (nonatomic, assign) IBInspectable CGSize dotShadowOffset;
@property (nonatomic, strong) IBInspectable UIImage *selectedDotImage;
@property (nonatomic, assign) IBInspectable CGPathRef selectedDotShape;
@property (nonatomic, assign) IBInspectable CGFloat selectedDotSize;
@property (nonatomic, strong) IBInspectable UIColor *selectedDotColor;
@property (nonatomic, strong) IBInspectable UIColor *selectedDotShadowColor;
@property (nonatomic, assign) IBInspectable CGFloat selectedDotShadowBlur;
@property (nonatomic, assign) IBInspectable CGSize selectedDotShadowOffset;
@property (nonatomic, assign) IBInspectable CGFloat dotSpacing;
@end
@protocol FXPageControlDelegate <NSObject>
@optional
- (UIImage *)pageControl:(FXPageControl *)pageControl imageForDotAtIndex:(NSInteger)index;
- (CGPathRef)pageControl:(FXPageControl *)pageControl shapeForDotAtIndex:(NSInteger)index;
- (UIColor *)pageControl:(FXPageControl *)pageControl colorForDotAtIndex:(NSInteger)index;
- (UIImage *)pageControl:(FXPageControl *)pageControl selectedImageForDotAtIndex:(NSInteger)index;
- (CGPathRef)pageControl:(FXPageControl *)pageControl selectedShapeForDotAtIndex:(NSInteger)index;
- (UIColor *)pageControl:(FXPageControl *)pageControl selectedColorForDotAtIndex:(NSInteger)index;
@end
#pragma GCC diagnostic pop

433
Sources/FXPageControl.m Executable file
View File

@ -0,0 +1,433 @@
//
// FXPageControl.m
//
// Version 1.4
//
// Created by Nick Lockwood on 07/01/2010.
// Copyright 2010 Charcoal Design
//
// Distributed under the permissive zlib License
// Get the latest version of FXPageControl from here:
//
// https://github.com/nicklockwood/FXPageControl
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
#import "FXPageControl.h"
#pragma GCC diagnostic ignored "-Wgnu"
#pragma GCC diagnostic ignored "-Wreceiver-is-weak"
#pragma GCC diagnostic ignored "-Warc-repeated-use-of-weak"
#pragma GCC diagnostic ignored "-Wdirect-ivar-access"
#import <Availability.h>
#if !__has_feature(objc_arc)
#error This class requires automatic reference counting
#endif
const CGPathRef FXPageControlDotShapeCircle = (const CGPathRef)1;
const CGPathRef FXPageControlDotShapeSquare = (const CGPathRef)2;
const CGPathRef FXPageControlDotShapeTriangle = (const CGPathRef)3;
#define LAST_SHAPE FXPageControlDotShapeTriangle
@implementation NSObject (FXPageControl)
- (UIImage *)pageControl:(__unused FXPageControl *)pageControl imageForDotAtIndex:(__unused NSInteger)index { return nil; }
- (CGPathRef)pageControl:(__unused FXPageControl *)pageControl shapeForDotAtIndex:(__unused NSInteger)index { return NULL; }
- (UIColor *)pageControl:(__unused FXPageControl *)pageControl colorForDotAtIndex:(__unused NSInteger)index { return nil; }
- (UIImage *)pageControl:(__unused FXPageControl *)pageControl selectedImageForDotAtIndex:(__unused NSInteger)index { return nil; }
- (CGPathRef)pageControl:(__unused FXPageControl *)pageControl selectedShapeForDotAtIndex:(__unused NSInteger)index { return NULL; }
- (UIColor *)pageControl:(__unused FXPageControl *)pageControl selectedColorForDotAtIndex:(__unused NSInteger)index { return nil; }
@end
@implementation FXPageControl
- (void)setUp
{
//needs redrawing if bounds change
self.contentMode = UIViewContentModeRedraw;
//set defaults
_dotSpacing = 10.0f;
_dotSize = 6.0f;
_dotShadowOffset = CGSizeMake(0, 1);
_selectedDotShadowOffset = CGSizeMake(0, 1);
}
- (id)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame]))
{
[self setUp];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
if ((self = [super initWithCoder:aDecoder]))
{
[self setUp];
}
return self;
}
- (void)dealloc
{
if (_dotShape > LAST_SHAPE) CGPathRelease(_dotShape);
if (_selectedDotShape > LAST_SHAPE) CGPathRelease(_selectedDotShape);
}
- (CGSize)sizeForNumberOfPages:(__unused NSInteger)pageCount
{
CGFloat width = _dotSize + (_dotSize + _dotSpacing) * (_numberOfPages - 1);
return _vertical? CGSizeMake(_dotSize, width): CGSizeMake(width, _dotSize);
}
- (void)updateCurrentPageDisplay
{
[self setNeedsDisplay];
}
- (void)drawRect:(__unused CGRect)rect
{
if (_numberOfPages > 1 || !_hidesForSinglePage)
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGSize size = [self sizeForNumberOfPages:_numberOfPages];
if (_vertical)
{
CGContextTranslateCTM(context, self.frame.size.width / 2, (self.frame.size.height - size.height) / 2);
}
else
{
CGContextTranslateCTM(context, (self.frame.size.width - size.width) / 2, self.frame.size.height / 2);
}
for (int i = 0; i < _numberOfPages; i++)
{
UIImage *dotImage = nil;
UIColor *dotColor = nil;
CGPathRef dotShape = NULL;
CGFloat dotSize = 0;
UIColor *dotShadowColor = nil;
CGSize dotShadowOffset = CGSizeZero;
CGFloat dotShadowBlur = 0;
if (i == _currentPage)
{
[_selectedDotColor setFill];
dotImage = [_delegate pageControl:self selectedImageForDotAtIndex:i] ?: _selectedDotImage;
dotShape = [_delegate pageControl:self selectedShapeForDotAtIndex:i] ?: _selectedDotShape ?: _dotShape;
dotColor = [_delegate pageControl:self selectedColorForDotAtIndex:i] ?: _selectedDotColor ?: [UIColor blackColor];
dotShadowBlur = _selectedDotShadowBlur;
dotShadowColor = _selectedDotShadowColor;
dotShadowOffset = _selectedDotShadowOffset;
dotSize = _selectedDotSize ?: _dotSize;
}
else
{
[_dotColor setFill];
dotImage = [_delegate pageControl:self imageForDotAtIndex:i] ?: _dotImage;
dotShape = [_delegate pageControl:self shapeForDotAtIndex:i] ?: _dotShape;
dotColor = [_delegate pageControl:self colorForDotAtIndex:i] ?: _dotColor;
if (!dotColor)
{
//fall back to selected dot color with reduced alpha
dotColor = [_delegate pageControl:self selectedColorForDotAtIndex:i] ?: _selectedDotColor ?: [UIColor blackColor];
dotColor = [dotColor colorWithAlphaComponent:0.25f];
}
dotShadowBlur = _dotShadowBlur;
dotShadowColor = _dotShadowColor;
dotShadowOffset = _dotShadowOffset;
dotSize = _dotSize;
}
CGContextSaveGState(context);
CGFloat offset = (_dotSize + _dotSpacing) * i + _dotSize / 2;
CGContextTranslateCTM(context, _vertical? 0: offset, _vertical? offset: 0);
if (dotShadowColor && ![dotShadowColor isEqual:[UIColor clearColor]])
{
CGContextSetShadowWithColor(context, dotShadowOffset, dotShadowBlur, dotShadowColor.CGColor);
}
if (dotImage)
{
[dotImage drawInRect:CGRectMake(-dotImage.size.width / 2, -dotImage.size.height / 2, dotImage.size.width, dotImage.size.height)];
}
else
{
[dotColor setFill];
if (!dotShape || dotShape == FXPageControlDotShapeCircle)
{
CGContextFillEllipseInRect(context, CGRectMake(-dotSize / 2, -dotSize / 2, dotSize, dotSize));
}
else if (dotShape == FXPageControlDotShapeSquare)
{
CGContextFillRect(context, CGRectMake(-dotSize / 2, -dotSize / 2, dotSize, dotSize));
}
else if (dotShape == FXPageControlDotShapeTriangle)
{
CGContextBeginPath(context);
CGContextMoveToPoint(context, 0, -dotSize / 2);
CGContextAddLineToPoint(context, dotSize / 2, dotSize / 2);
CGContextAddLineToPoint(context, -dotSize / 2, dotSize / 2);
CGContextAddLineToPoint(context, 0, -dotSize / 2);
CGContextFillPath(context);
}
else
{
CGContextBeginPath(context);
CGContextAddPath(context, dotShape);
CGContextFillPath(context);
}
}
CGContextRestoreGState(context);
}
}
}
- (NSInteger)clampedPageValue:(NSInteger)page
{
if (_wrapEnabled)
{
return _numberOfPages? (page + _numberOfPages) % _numberOfPages: 0;
}
else
{
return MIN(MAX(0, page), _numberOfPages - 1);
}
}
- (void)setDotImage:(UIImage *)dotImage
{
if (_dotImage != dotImage)
{
_dotImage = dotImage;
[self setNeedsDisplay];
}
}
- (void)setDotShape:(CGPathRef)dotShape
{
if (_dotShape != dotShape)
{
if (_dotShape > LAST_SHAPE) CGPathRelease(_dotShape);
_dotShape = dotShape;
if (_dotShape > LAST_SHAPE) CGPathRetain(_dotShape);
[self setNeedsDisplay];
}
}
- (void)setDotSize:(CGFloat)dotSize
{
if (ABS(_dotSize - dotSize) > 0.001)
{
_dotSize = dotSize;
[self setNeedsDisplay];
}
}
- (void)setDotColor:(UIColor *)dotColor
{
if (_dotColor != dotColor)
{
_dotColor = dotColor;
[self setNeedsDisplay];
}
}
- (void)setDotShadowColor:(UIColor *)dotColor
{
if (_dotShadowColor != dotColor)
{
_dotShadowColor = dotColor;
[self setNeedsDisplay];
}
}
- (void)setDotShadowBlur:(CGFloat)dotShadowBlur
{
if (ABS(_dotShadowBlur - dotShadowBlur) > 0.001)
{
_dotShadowBlur = dotShadowBlur;
[self setNeedsDisplay];
}
}
- (void)setDotShadowOffset:(CGSize)dotShadowOffset
{
if (!CGSizeEqualToSize(_dotShadowOffset, dotShadowOffset))
{
_dotShadowOffset = dotShadowOffset;
[self setNeedsDisplay];
}
}
- (void)setSelectedDotImage:(UIImage *)dotImage
{
if (_selectedDotImage != dotImage)
{
_selectedDotImage = dotImage;
[self setNeedsDisplay];
}
}
- (void)setSelectedDotColor:(UIColor *)dotColor
{
if (_selectedDotColor != dotColor)
{
_selectedDotColor = dotColor;
[self setNeedsDisplay];
}
}
- (void)setSelectedDotShape:(CGPathRef)dotShape
{
if (_selectedDotShape != dotShape)
{
if (_selectedDotShape > LAST_SHAPE) CGPathRelease(_selectedDotShape);
_selectedDotShape = dotShape;
if (_selectedDotShape > LAST_SHAPE) CGPathRetain(_selectedDotShape);
[self setNeedsDisplay];
}
}
- (void)setSelectedDotSize:(CGFloat)dotSize
{
if (ABS(_selectedDotSize - dotSize) > 0.001)
{
_selectedDotSize = dotSize;
[self setNeedsDisplay];
}
}
- (void)setSelectedDotShadowColor:(UIColor *)dotColor
{
if (_selectedDotShadowColor != dotColor)
{
_selectedDotShadowColor = dotColor;
[self setNeedsDisplay];
}
}
- (void)setSelectedDotShadowBlur:(CGFloat)dotShadowBlur
{
if (ABS(_selectedDotShadowBlur - dotShadowBlur) > 0.001)
{
_selectedDotShadowBlur = dotShadowBlur;
[self setNeedsDisplay];
}
}
- (void)setSelectedDotShadowOffset:(CGSize)dotShadowOffset
{
if (!CGSizeEqualToSize(_selectedDotShadowOffset, dotShadowOffset))
{
_selectedDotShadowOffset = dotShadowOffset;
[self setNeedsDisplay];
}
}
- (void)setDotSpacing:(CGFloat)dotSpacing
{
if (ABS(_dotSpacing - dotSpacing) > 0.001)
{
_dotSpacing = dotSpacing;
[self setNeedsDisplay];
}
}
- (void)setDelegate:(id<FXPageControlDelegate>)delegate
{
if (_delegate != delegate)
{
_delegate = delegate;
[self setNeedsDisplay];
}
}
- (void)setCurrentPage:(NSInteger)page
{
_currentPage = [self clampedPageValue:page];
[self setNeedsDisplay];
}
- (void)setNumberOfPages:(NSInteger)pages
{
if (_numberOfPages != pages)
{
_numberOfPages = pages;
if (_currentPage >= pages)
{
_currentPage = pages - 1;
}
[self setNeedsDisplay];
}
}
- (void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint point = [touch locationInView:self];
BOOL forward = _vertical? (point.y > self.frame.size.height / 2): (point.x > self.frame.size.width / 2);
_currentPage = [self clampedPageValue:_currentPage + (forward? 1: -1)];
if (!_defersCurrentPageDisplay)
{
[self setNeedsDisplay];
}
[self sendActionsForControlEvents:UIControlEventValueChanged];
[super endTrackingWithTouch:touch withEvent:event];
}
- (CGSize)sizeThatFits:(__unused CGSize)size
{
CGSize dotSize = [self sizeForNumberOfPages:_numberOfPages];
if (_selectedDotSize)
{
CGFloat width = (_selectedDotSize - _dotSize);
CGFloat height = MAX(36, MAX(_dotSize, _selectedDotSize));
dotSize.width = _vertical? height: dotSize.width + width;
dotSize.height = _vertical? dotSize.height + width: height;
}
if ((_dotShadowColor && ![_dotShadowColor isEqual:[UIColor clearColor]]) ||
(_selectedDotShadowColor && ![_selectedDotShadowColor isEqual:[UIColor clearColor]]))
{
dotSize.width += MAX(_dotShadowOffset.width, _selectedDotShadowOffset.width) * 2;
dotSize.height += MAX(_dotShadowOffset.height, _selectedDotShadowOffset.height) * 2;
dotSize.width += MAX(_dotShadowBlur, _selectedDotShadowBlur) * 2;
dotSize.height += MAX(_dotShadowBlur, _selectedDotShadowBlur) * 2;
}
return dotSize;
}
- (CGSize)intrinsicContentSize
{
return [self sizeThatFits:self.bounds.size];
}
@end

View File

@ -0,0 +1,225 @@
// TwitterPagerTabStripViewController.swift
// XLPagerTabStrip ( https://github.com/xmartlabs/XLPagerTabStrip )
//
// Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )
//
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// 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.
import Foundation
public class TwitterPagerTabStripViewController: PagerTabStripViewController, PagerTabStripViewControllerDataSource, PagerTabStripViewControllerIsProgressiveDelegate {
lazy var navigationView: UIView = {
let navigationView = UIView()
navigationView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
return navigationView
}()
lazy var navigationScrollView: UIScrollView = { [unowned self] in
let navigationScrollView = UIScrollView(frame: CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), 44))
navigationScrollView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
navigationScrollView.bounces = true
navigationScrollView.scrollsToTop = false
navigationScrollView.delegate = self
navigationScrollView.showsVerticalScrollIndicator = false
navigationScrollView.showsHorizontalScrollIndicator = false
navigationScrollView.pagingEnabled = true
navigationScrollView.userInteractionEnabled = false
navigationScrollView.alwaysBounceHorizontal = true
navigationScrollView.alwaysBounceVertical = false
return navigationScrollView
}()
var navigationPageControl: FXPageControl = {
let navigationPageControl = FXPageControl()
navigationPageControl.backgroundColor = .clearColor()
navigationPageControl.dotSize = 3.8
navigationPageControl.dotSpacing = 4.0
navigationPageControl.dotColor = UIColor(white: 1, alpha: 0.4)
navigationPageControl.selectedDotColor = .whiteColor()
navigationPageControl.userInteractionEnabled = false
return navigationPageControl
}()
var navigationItemsViews = [UIView]()
var landscapeTitleFont = UIFont.systemFontOfSize(14)
var portraitTitleFont = UIFont.systemFontOfSize(18)
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
delegate = self
datasource = self
}
public override func viewDidLoad() {
super.viewDidLoad()
if navigationView.superview == nil {
navigationItem.titleView = navigationView
}
navigationView.addObserver(self, forKeyPath: "frame", options: [.New, .Old], context: nil)
navigationView.frame = CGRectMake(0, 0, CGRectGetWidth(navigationController!.navigationBar.frame), CGRectGetHeight(navigationController!.navigationBar.frame))
if navigationScrollView.superview == nil {
navigationView.addSubview(navigationScrollView)
}
if navigationPageControl.superview == nil {
navigationView.addSubview(navigationPageControl)
}
reloadNavigationViewItems()
}
public override func reloadPagerTabStripView() {
super.reloadPagerTabStripView()
guard isViewLoaded() else { return }
reloadNavigationViewItems()
setNavigationViewItemsPosition()
}
// MARK: - PagerTabStripViewControllerDelegate
public func pagerTabStripViewController(pagerTabStripViewController: PagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex: Int) throws {
}
public func pagerTabStripViewController(pagerTabStripViewController: PagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex: Int, withProgressPercentage progressPercentage: CGFloat, indexWasChanged: Bool) throws {
let distance = getDistanceValue()
var xOffset: CGFloat = 0
if fromIndex < toIndex {
xOffset = distance * CGFloat(fromIndex) + distance * progressPercentage
}
else if fromIndex > toIndex {
xOffset = distance * CGFloat(fromIndex) - distance * progressPercentage
}
else {
xOffset = distance * CGFloat(fromIndex)
}
navigationScrollView.contentOffset = CGPointMake(xOffset, 0)
setAlphaWithOffset(xOffset)
navigationPageControl.currentPage = currentIndex
}
public override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
guard object as! UIView == navigationView && keyPath! == "frame" && change![NSKeyValueChangeKindKey] as! UInt == NSKeyValueChange.Setting.rawValue else { return }
let oldRect = change![NSKeyValueChangeOldKey]!.CGRectValue
let newRect = change![NSKeyValueChangeOldKey]!.CGRectValue
guard !CGRectEqualToRect(oldRect, newRect) else { return }
navigationScrollView.frame = CGRectMake(0, 0, CGRectGetWidth(navigationView.frame), CGRectGetHeight(navigationScrollView.frame))
setNavigationViewItemsPosition()
}
deinit {
navigationView.removeObserver(self, forKeyPath: "frame")
}
// MARK: - Helpers
func reloadNavigationViewItems() {
for item in navigationItemsViews {
item.removeFromSuperview()
}
navigationItemsViews.removeAll()
for (index, item) in viewControllers.enumerate() {
let child = item as! PagerTabStripChildItem
let childHeader = child.childHeaderForPagerTabStripViewController(self)
let navTitleLabel = createNewLabelWithText(childHeader.title)
navTitleLabel.alpha = currentIndex == index ? 1 : 0
navTitleLabel.textColor = childHeader.color ?? .whiteColor()
navigationScrollView.addSubview(navTitleLabel)
navigationItemsViews.append(navTitleLabel)
}
}
private func setNavigationViewItemsPosition() {
setNavigationViewItemsPosition(true)
}
private func setNavigationViewItemsPosition(updateAlpha: Bool) {
let distance = getDistanceValue()
let isPortrait = UIDeviceOrientationIsPortrait(UIDevice.currentDevice().orientation)
let labelHeightSpace: CGFloat = isPortrait ? 34 : 25
for (index, view) in navigationItemsViews.enumerate() {
let label = view as! UILabel
if updateAlpha {
label.alpha = currentIndex == index ? 1 : 0
}
label.font = isPortrait ? portraitTitleFont : landscapeTitleFont
let viewSize = getLabelSize(label)
let originX = distance - viewSize.width/2 + CGFloat(index) * distance
let originY = (CGFloat(labelHeightSpace) - viewSize.height) / 2
label.frame = CGRectMake(originX, originY + 2, viewSize.width, viewSize.height)
label.tag = index
}
let xOffset = distance * CGFloat(currentIndex)
navigationScrollView.contentOffset = CGPointMake(xOffset, 0)
navigationPageControl.numberOfPages = navigationItemsViews.count
navigationPageControl.currentPage = currentIndex
let viewSize = navigationPageControl.sizeForNumberOfPages(navigationItemsViews.count)
let originX = distance - viewSize.width/2
navigationPageControl.frame = CGRectMake(originX, labelHeightSpace, viewSize.width, viewSize.height)
}
private func setAlphaWithOffset(xOffset: CGFloat) {
let distance = getDistanceValue()
for (index, view) in navigationItemsViews.enumerate() {
var alpha: CGFloat = 0
if xOffset < distance * CGFloat(index) {
alpha = (xOffset - distance * CGFloat(index - 1)) / distance
}
else {
alpha = 1 - ((xOffset - distance * CGFloat(index)) / distance)
}
view.alpha = alpha
}
}
private func createNewLabelWithText(text :String) -> UILabel {
let label = UILabel()
label.text = text
label.font = landscapeTitleFont
label.textColor = .whiteColor()
label.alpha = 0
return label
}
private func getLabelSize(label: UILabel) -> CGSize {
return (label.text! as NSString).sizeWithAttributes([NSFontAttributeName : label.font])
}
private func getDistanceValue() -> CGFloat {
let middle = navigationController?.navigationBar .convertPoint(navigationController!.navigationBar.center, toView: navigationView)
return middle!.x
}
public override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
setNavigationViewItemsPosition(false)
}
}

View File

@ -19,9 +19,12 @@
CB0986C81C5158A000DF7087 /* ButtonBarViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB0986C71C5158A000DF7087 /* ButtonBarViewCell.swift */; };
CB0986CA1C515D9A00DF7087 /* ButtonCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = CB0986C91C515D9A00DF7087 /* ButtonCell.xib */; };
CB71C6EE1C4EB988008EC806 /* SegmentedPagerTabStripViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB71C6ED1C4EB988008EC806 /* SegmentedPagerTabStripViewController.swift */; };
CB7D614C1C529B9500A957BA /* FXPageControl.h in Headers */ = {isa = PBXBuildFile; fileRef = CB7D614A1C529B9500A957BA /* FXPageControl.h */; settings = {ATTRIBUTES = (Public, ); }; };
CB7D614D1C529B9500A957BA /* FXPageControl.m in Sources */ = {isa = PBXBuildFile; fileRef = CB7D614B1C529B9500A957BA /* FXPageControl.m */; };
CB86ED6B1C4D6E6C00DA463B /* PagerTabStripViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB86ED6A1C4D6E6C00DA463B /* PagerTabStripViewController.swift */; };
CBA0A1FC1C502DA300C5748C /* BarPagerTabStripViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBA0A1FA1C502DA300C5748C /* BarPagerTabStripViewController.swift */; };
CBA0A1FD1C502DA300C5748C /* BarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBA0A1FB1C502DA300C5748C /* BarView.swift */; };
CBBD43621C527E80001A748E /* TwitterPagerTabStripViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBBD43611C527E80001A748E /* TwitterPagerTabStripViewController.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -51,9 +54,12 @@
CB0986C71C5158A000DF7087 /* ButtonBarViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ButtonBarViewCell.swift; sourceTree = "<group>"; };
CB0986C91C515D9A00DF7087 /* ButtonCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ButtonCell.xib; sourceTree = "<group>"; };
CB71C6ED1C4EB988008EC806 /* SegmentedPagerTabStripViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SegmentedPagerTabStripViewController.swift; sourceTree = "<group>"; };
CB7D614A1C529B9500A957BA /* FXPageControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FXPageControl.h; sourceTree = "<group>"; };
CB7D614B1C529B9500A957BA /* FXPageControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FXPageControl.m; sourceTree = "<group>"; };
CB86ED6A1C4D6E6C00DA463B /* PagerTabStripViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PagerTabStripViewController.swift; sourceTree = "<group>"; };
CBA0A1FA1C502DA300C5748C /* BarPagerTabStripViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BarPagerTabStripViewController.swift; sourceTree = "<group>"; };
CBA0A1FB1C502DA300C5748C /* BarView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BarView.swift; sourceTree = "<group>"; };
CBBD43611C527E80001A748E /* TwitterPagerTabStripViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TwitterPagerTabStripViewController.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -78,6 +84,7 @@
281BFDBE1C511B890090C26F /* Views */ = {
isa = PBXGroup;
children = (
CB7D614E1C529BB600A957BA /* FXPageControl */,
CB0986C91C515D9A00DF7087 /* ButtonCell.xib */,
CBA0A1FB1C502DA300C5748C /* BarView.swift */,
CB0986C51C51395E00DF7087 /* ButtonBarView.swift */,
@ -93,6 +100,7 @@
CB86ED6A1C4D6E6C00DA463B /* PagerTabStripViewController.swift */,
CB71C6ED1C4EB988008EC806 /* SegmentedPagerTabStripViewController.swift */,
CB0986C31C51391600DF7087 /* ButtonBarPagerTabStripViewController.swift */,
CBBD43611C527E80001A748E /* TwitterPagerTabStripViewController.swift */,
);
name = Controllers;
sourceTree = "<group>";
@ -149,6 +157,15 @@
path = Sources;
sourceTree = "<group>";
};
CB7D614E1C529BB600A957BA /* FXPageControl */ = {
isa = PBXGroup;
children = (
CB7D614A1C529B9500A957BA /* FXPageControl.h */,
CB7D614B1C529B9500A957BA /* FXPageControl.m */,
);
name = FXPageControl;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
@ -157,6 +174,7 @@
buildActionMask = 2147483647;
files = (
28F828811C494B2C00330CF4 /* XLPagerTabStrip.h in Headers */,
CB7D614C1C529B9500A957BA /* FXPageControl.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -258,7 +276,9 @@
buildActionMask = 2147483647;
files = (
CB0986C61C51395E00DF7087 /* ButtonBarView.swift in Sources */,
CBBD43621C527E80001A748E /* TwitterPagerTabStripViewController.swift in Sources */,
CBA0A1FD1C502DA300C5748C /* BarView.swift in Sources */,
CB7D614D1C529B9500A957BA /* FXPageControl.m in Sources */,
281BFDC31C511F120090C26F /* PagerTabStripOptions.swift in Sources */,
CBA0A1FC1C502DA300C5748C /* BarPagerTabStripViewController.swift in Sources */,
CB71C6EE1C4EB988008EC806 /* SegmentedPagerTabStripViewController.swift in Sources */,
@ -382,6 +402,7 @@
28F828921C494B2C00330CF4 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
@ -392,12 +413,16 @@
PRODUCT_BUNDLE_IDENTIFIER = com.xmartlabs.XLPagerTabStrip;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_INSTALL_OBJC_HEADER = YES;
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
28F828931C494B2C00330CF4 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
@ -408,6 +433,8 @@
PRODUCT_BUNDLE_IDENTIFIER = com.xmartlabs.XLPagerTabStrip;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_INSTALL_OBJC_HEADER = YES;
SWIFT_OBJC_BRIDGING_HEADER = "";
};
name = Release;
};

View File

@ -15,4 +15,5 @@ FOUNDATION_EXPORT const unsigned char XLPagerTabStripVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <XLPagerTabStrip/PublicHeader.h>
#import "FXPageControl.h"