removed standalone logic from core tab controller

This commit is contained in:
Pfeil, Scott Robert 2019-01-10 15:10:33 -05:00
parent 98fa47aaae
commit 72f5ba18ec
16 changed files with 1576 additions and 52 deletions

View File

@ -98,9 +98,9 @@
D29DF2B321E7B76D003B2FB9 /* MFLoadingSpinner.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF2B121E7B76C003B2FB9 /* MFLoadingSpinner.h */; };
D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF2B221E7B76D003B2FB9 /* MFLoadingSpinner.m */; };
D29DF2BC21E7BEA4003B2FB9 /* TopTabbar.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF2B821E7BEA4003B2FB9 /* TopTabbar.h */; settings = {ATTRIBUTES = (Public, ); }; };
D29DF2BD21E7BEA4003B2FB9 /* MFTabBarPageControlViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF2B921E7BEA4003B2FB9 /* MFTabBarPageControlViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
D29DF2BD21E7BEA4003B2FB9 /* MVMCoreUITabBarPageControlViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF2B921E7BEA4003B2FB9 /* MVMCoreUITabBarPageControlViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
D29DF2BE21E7BEA4003B2FB9 /* TopTabbar.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF2BA21E7BEA4003B2FB9 /* TopTabbar.m */; };
D29DF2BF21E7BEA4003B2FB9 /* MFTabBarPageControlViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF2BB21E7BEA4003B2FB9 /* MFTabBarPageControlViewController.m */; };
D29DF2BF21E7BEA4003B2FB9 /* MVMCoreUITabBarPageControlViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF2BB21E7BEA4003B2FB9 /* MVMCoreUITabBarPageControlViewController.m */; };
D29DF2C421E7BF57003B2FB9 /* MFTabBarSwipeAnimator.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF2C021E7BF56003B2FB9 /* MFTabBarSwipeAnimator.h */; };
D29DF2C521E7BF57003B2FB9 /* MFTabBarSwipeAnimator.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF2C121E7BF57003B2FB9 /* MFTabBarSwipeAnimator.m */; };
D29DF2C621E7BF57003B2FB9 /* MFTabBarInteractor.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF2C221E7BF57003B2FB9 /* MFTabBarInteractor.h */; };
@ -214,9 +214,9 @@
D29DF2B121E7B76C003B2FB9 /* MFLoadingSpinner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFLoadingSpinner.h; sourceTree = "<group>"; };
D29DF2B221E7B76D003B2FB9 /* MFLoadingSpinner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFLoadingSpinner.m; sourceTree = "<group>"; };
D29DF2B821E7BEA4003B2FB9 /* TopTabbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TopTabbar.h; sourceTree = "<group>"; };
D29DF2B921E7BEA4003B2FB9 /* MFTabBarPageControlViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFTabBarPageControlViewController.h; sourceTree = "<group>"; };
D29DF2B921E7BEA4003B2FB9 /* MVMCoreUITabBarPageControlViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUITabBarPageControlViewController.h; sourceTree = "<group>"; };
D29DF2BA21E7BEA4003B2FB9 /* TopTabbar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TopTabbar.m; sourceTree = "<group>"; };
D29DF2BB21E7BEA4003B2FB9 /* MFTabBarPageControlViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFTabBarPageControlViewController.m; sourceTree = "<group>"; };
D29DF2BB21E7BEA4003B2FB9 /* MVMCoreUITabBarPageControlViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUITabBarPageControlViewController.m; sourceTree = "<group>"; };
D29DF2C021E7BF56003B2FB9 /* MFTabBarSwipeAnimator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFTabBarSwipeAnimator.h; sourceTree = "<group>"; };
D29DF2C121E7BF57003B2FB9 /* MFTabBarSwipeAnimator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFTabBarSwipeAnimator.m; sourceTree = "<group>"; };
D29DF2C221E7BF57003B2FB9 /* MFTabBarInteractor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFTabBarInteractor.h; sourceTree = "<group>"; };
@ -524,8 +524,8 @@
D29DF2C321E7BF57003B2FB9 /* MFTabBarInteractor.m */,
D29DF2B821E7BEA4003B2FB9 /* TopTabbar.h */,
D29DF2BA21E7BEA4003B2FB9 /* TopTabbar.m */,
D29DF2B921E7BEA4003B2FB9 /* MFTabBarPageControlViewController.h */,
D29DF2BB21E7BEA4003B2FB9 /* MFTabBarPageControlViewController.m */,
D29DF2B921E7BEA4003B2FB9 /* MVMCoreUITabBarPageControlViewController.h */,
D29DF2BB21E7BEA4003B2FB9 /* MVMCoreUITabBarPageControlViewController.m */,
);
path = TabBarController;
sourceTree = "<group>";
@ -578,7 +578,7 @@
D29DF2C421E7BF57003B2FB9 /* MFTabBarSwipeAnimator.h in Headers */,
D29DF2CA21E7BFC8003B2FB9 /* MFSizeThreshold.h in Headers */,
D29DF28021E7AA51003B2FB9 /* MVMCoreDetailViewProtocol.h in Headers */,
D29DF2BD21E7BEA4003B2FB9 /* MFTabBarPageControlViewController.h in Headers */,
D29DF2BD21E7BEA4003B2FB9 /* MVMCoreUITabBarPageControlViewController.h in Headers */,
D29DF12D21E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.h in Headers */,
D29DF24E21E6A177003B2FB9 /* MFDigitTextField.h in Headers */,
D29DF17421E69E1F003B2FB9 /* MFCustomButton.h in Headers */,
@ -686,7 +686,7 @@
D29DF18321E69E54003B2FB9 /* SeparatorView.m in Sources */,
D29DF17A21E69E1F003B2FB9 /* MFCustomButton.m in Sources */,
D29DF26121E6A985003B2FB9 /* MFLoadImageView.m in Sources */,
D29DF2BF21E7BEA4003B2FB9 /* MFTabBarPageControlViewController.m in Sources */,
D29DF2BF21E7BEA4003B2FB9 /* MVMCoreUITabBarPageControlViewController.m in Sources */,
D29DF28321E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.m in Sources */,
D29DF28A21E7AC2B003B2FB9 /* MFLabel.m in Sources */,
D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */,

View File

@ -0,0 +1,17 @@
//
// ButtonDelegateProtocol.h
// mobilefirst
//
// Created by Scott Pfeil on 2/25/16.
// Copyright © 2016 Verizon Wireless. All rights reserved.
//
#import "MFButtonProtocol.h"
@protocol ButtonDelegateProtocol <NSObject>
@optional
// Called when the entered text becomes valid based on the validation block
- (BOOL)button:(nonnull NSObject <MFButtonProtocol> *)button shouldPerformActionWithMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData;
@end

View File

@ -0,0 +1,12 @@
//
// MFButtonProtocol.h
// mobilefirst
//
// Created by Yang, Tianhang (Chris) on 2/14/18.
// Copyright © 2018 Verizon Wireless. All rights reserved.
//
@protocol MFButtonProtocol <NSObject>
@end

View File

@ -0,0 +1,115 @@
//
// PrimaryButton.h
// myverizon
//
// Created by Scott Pfeil on 12/2/15.
// Copyright © 2015 Verizon Wireless. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "MFCustomButton.h"
#import "MFTextField.h"
#import "MFView.h"
typedef enum : NSUInteger {
PrimaryButtonTypeRed,
PrimaryButtonTypeGray,
PrimaryButtonTypeWhiteRed,
PrimaryButtonTypeGrayRed,
// 2.0
PrimaryButtonTypeBlack,
PrimaryButtonTypeWhite,
} PrimaryButtonType;
static CGFloat const PrimaryButtonHeight = 42.0;
static CGFloat const PrimaryButtonSmallHeight = 30.0;
@interface PrimaryButton : MFCustomButton <MFTextFieldDelegate, UITextFieldDelegate, MVMCoreViewProtocol>
@property (nonatomic, readonly, assign) PrimaryButtonType primaryButtonType; //use reset function to set
@property (nullable, copy, nonatomic) BOOL(^extraValidationBlock)(void);
// Set as no to make button filled, set as yes to make button bordered.
@property (nonatomic) BOOL bordered;
// set YES to skip highlight method, for customer color button
@property (nonatomic) BOOL skipHighlighted;
// The main creation functions, changed to black button for 2.0 for default
+ (nullable instancetype)primaryButton:(BOOL)enabled;
+ (nullable instancetype)primarySmallButton:(BOOL)enabled;
+ (nullable instancetype)primaryTinyButton:(BOOL)enabled;
+ (nullable instancetype)primaryButton;
+ (nullable instancetype)primarySmallButton;
+ (nullable instancetype)primaryWhiteButton:(BOOL)small;
// legacy color functions.
+ (nullable instancetype)primaryRedButton;
+ (nullable instancetype)primaryGrayButtonSmall:(BOOL)small;
+ (nullable instancetype)primaryRedSmallButton;
+ (nullable instancetype)primaryGraySmallRedButton;
+ (nullable instancetype)primaryWhiteSmallRedButton;
#pragma mark - For Subclassing
// Creates and pins the height of the button, nothing more.
+ (nullable instancetype)getButton;
// Pins the height initially.
- (void)pinHeight;
#pragma mark - Setting
// For setting after creation.
- (void)setAsSmallButton:(BOOL)smallButton enabled:(BOOL)enabled bordered:(BOOL)bordered;
// Changes the size of the button. Currently only small,regular and tiny.
- (void)setAsSmallButton:(BOOL)smallButton;
// Changes the size of the button to Tiny
- (void)setAsTiny:(BOOL)tinyButton;
// Sets the button to red.
- (void)setAsRed;
// Sets the button to gray.
- (void)setAsGray;
// Sets the button to dark gray/ for white button disabled
- (void)setAsDarkGray;
// Sets the button with white background color with red border (used in ISPU)
- (void)setAsWhite;
- (void)setAsAllWhite;
- (void)setAsInactiveGray;
// Pins the width after title/text setup.
// Note: use this after setting up button title
- (void)pinWidth;
// Add edgeinset into button, redo constraints
- (void)pinEdgeInsetHeight:(CGFloat)heightInset Width:(CGFloat)widthInset;
// properly reset the button appearence
- (void)resetButtonType:(PrimaryButtonType)type small:(BOOL)isSmall bordered:(BOOL)bordered;
- (void)resetButtonType:(PrimaryButtonType)type tiny:(BOOL)isTiny bordered:(BOOL)bordered;
#pragma mark - Handling Validations
// Sets the enabled property depending on the validity checks
- (void)setEnabledByValidity;
// Will handle enabling and disabling itself based on if all the textfields passed in are valid or not. This will set the textfields validation block to accept any entered value (except no entry).
- (void)handleEnablingWithTextFieldsDefaultValidations:(nullable NSArray <MFTextField *>*)textFields;
// Same as above but will not use default validations. You will have to set validation blocks yourself prior.
- (void)handleEnablingWithTextFields:(nullable NSArray <MFTextField *>*)textFields;
@end

View File

@ -0,0 +1,73 @@
//
// NSLayoutConstraint+MVMCoreUIConvenience.h
// myverizon
//
// Created by Chris Yang on 1/15/16.
// Copyright © 2016 Verizon Wireless. All rights reserved.
//
#import <UIKit/UIKit.h>
//************************************************************************
//*
//* IMPORTANT::make sure add subView to superView before call the methods
//*
//************************************************************************
// constraint constants
extern NSString * _Nonnull const ConstraintTop;
extern NSString * _Nonnull const ConstraintBot;
extern NSString * _Nonnull const ConstraintLeading;
extern NSString * _Nonnull const ConstraintTrailing;
extern NSString * _Nonnull const ConstraintCenterX;
extern NSString * _Nonnull const ConstraintCenterY;
extern NSString * _Nonnull const ConstraintHeight;
extern NSString * _Nonnull const ConstraintWidth;
@interface NSLayoutConstraint (MVMCoreUIConvenience)
//this will pin subview to superview
+ (nullable NSDictionary *)constraintPinSubviewToSuperview:(nullable UIView *)subview;
+ (nullable NSDictionary *)constraintPinSubview:(nullable UIView *)subview pinTop:(BOOL)pinTop pinBottom:(BOOL)pinBottom pinLeft:(BOOL)pinLeft pinRight:(BOOL)pinRight;
+ (nullable NSDictionary *)constraintPinSubview:(nullable UIView *)subview pinTop:(BOOL)pinTop topConstant:(CGFloat)topConstant pinBottom:(BOOL)pinBottom bottomConstant:(CGFloat)bottomConstant pinLeft:(BOOL)pinLeft leftConstant:(CGFloat)leftConstant pinRight:(BOOL)pinRight rightConstant:(CGFloat)rightConstant;
// Pin subview with 1 side
+ (nullable NSDictionary *)constraintPinTopSubview:(nonnull UIView *)subview topConstant:(CGFloat)topConstant;
+ (nullable NSDictionary *)constraintPinBottomSubview:(nonnull UIView *)subview bottomConstant:(CGFloat)bottomConstant;
+ (nullable NSDictionary *)constraintPinLeftSubview:(nonnull UIView *)subview leftConstant:(CGFloat)leftConstant;
+ (nullable NSDictionary *)constraintPinRightSubview:(nonnull UIView *)subview rightConstant:(CGFloat)rightConstant;
//pin the subview to the horizontal and vertical center of super view
+ (nullable NSDictionary *)constraintPinSubviewToCenterOfSuperview:(nullable UIView *)subview;
+ (nullable NSDictionary *)constraintPinSubview:(nullable UIView *)subview pinCenterX:(BOOL)pinCenterX pinCenterY:(BOOL)pinCenterY;
+ (nullable NSDictionary *)constraintPinSubview:(nullable UIView *)subview pinCenterX:(BOOL)pinCenterX centerXConstant:(CGFloat)centerXConstant pinCenterY:(BOOL)pinCenterY centerYConstant:(CGFloat)centerYConstant;
//set height and width constraint for a view
+ (nullable NSDictionary *)constraintPinView:(nonnull UIView*)view heightConstraint:(BOOL)pinHeight heightConstant:(CGFloat)heightConstant widthConstraint:(BOOL)pinWidth widthConstant:(CGFloat)widthConstant;
// pins 2 views in same hierarchy
+(nullable NSLayoutConstraint *)constraintPinFirstView :(nonnull UIView*)firstView toSecondView :(nonnull UIView*)secondView withConstant :(CGFloat)constant directionVertical :(BOOL)directionVertical;
+(nullable NSDictionary *)constraintAlignView :(nonnull UIView *)firstView toSecondView :(nonnull UIView *)secondView alignX :(BOOL)alignX alignY :(BOOL)alignY;
#pragma mark - Scaling constraints
// These functions will pin a view to its super view with space that is a ratio of the anchor (by default the super view's width if nothing is passed in). (So if the space is 24 and the super's width is 320 in the design, then the ratio should be 24/320 and this will be multiplied by the super's current width, so that the constraint always linearly scales).
+ (nullable NSDictionary *)scalingConstraintPinSubview:(nullable UIView *)subview pinTop:(BOOL)pinTop topConstant:(CGFloat)topConstant pinBottom:(BOOL)pinBottom bottomConstant:(CGFloat)bottomConstant pinLeft:(BOOL)pinLeft leftConstant:(CGFloat)leftConstant pinRight:(BOOL)pinRight rightConstant:(CGFloat)rightConstant baseConstant:(CGFloat)baseConstant;
+ (nullable NSDictionary *)scalingConstraintPinSubview:(nullable UIView *)subview pinTop:(BOOL)pinTop topConstant:(CGFloat)topConstant pinBottom:(BOOL)pinBottom bottomConstant:(CGFloat)bottomConstant pinLeft:(BOOL)pinLeft leftConstant:(CGFloat)leftConstant pinRight:(BOOL)pinRight rightConstant:(CGFloat)rightConstant baseConstant:(CGFloat)baseConstant anchor:(nullable NSLayoutDimension *)anchor;
// More Direct helpers
+ (nonnull NSLayoutConstraint *)scalingPinViewLeftToSuper:(nonnull UIView *)view ratio:(CGFloat)ratio anchor:(nullable NSLayoutDimension *)anchor;
+ (nonnull NSLayoutConstraint *)scalingPinViewRightToSuper:(nonnull UIView *)view ratio:(CGFloat)ratio anchor:(nullable NSLayoutDimension *)anchor;
+ (nonnull NSLayoutConstraint *)scalingPinViewTopToSuper:(nonnull UIView *)view ratio:(CGFloat)ratio anchor:(nullable NSLayoutDimension *)anchor;
+ (nonnull NSLayoutConstraint *)scalingPinViewBottomToSuper:(nonnull UIView *)view ratio:(CGFloat)ratio anchor:(nullable NSLayoutDimension *)anchor;
// Pins one view to another. Smart enough to handle pinning a view to its super or a view to another view with the same super. Pass in the direction and relationship for the pinning. Ratio works the same as the above functions. Can optionally also pass in an anchor if you do not wish to use the super's width as an anchor.
+ (nonnull NSLayoutConstraint *)scalingConstraintPinView:(nonnull UIView *)view toView:(nonnull UIView *)toView layoutAxis:(UILayoutConstraintAxis)layoutAxis relation:(NSLayoutRelation)relation ratio:(CGFloat)ratio anchor:(nullable NSLayoutDimension *)anchor;
@end

View File

@ -0,0 +1,254 @@
//
// NSLayoutConstraint+MVMCoreUIConvenience.m
// myverizon
//
// Created by Chris Yang on 1/15/16.
// Copyright © 2016 Verizon Wireless. All rights reserved.
//
#import "NSLayoutConstraint+MVMCoreUIConvenience.h"
//constraint constants
NSString *const ConstraintTop = @"top";
NSString *const ConstraintBot = @"bot";
NSString *const ConstraintLeading = @"leading";
NSString *const ConstraintTrailing = @"trailing";
NSString *const ConstraintCenterX = @"centerX";
NSString *const ConstraintCenterY = @"centerY";
NSString *const ConstraintHeight = @"height";
NSString *const ConstraintWidth = @"width";
@implementation NSLayoutConstraint (MVMCoreUIConvenience)
+ (NSDictionary *)constraintPinSubviewToSuperview:(UIView *)subview {
return [NSLayoutConstraint constraintPinSubview:subview pinTop:YES pinBottom:YES pinLeft:YES pinRight:YES];
}
+ (nullable NSDictionary *)constraintPinTopSubview:(nonnull UIView *)subview topConstant:(CGFloat)topConstant {
return [NSLayoutConstraint constraintPinSubview:subview pinTop:true topConstant:topConstant pinBottom:false bottomConstant:0 pinLeft:false leftConstant:0 pinRight:false rightConstant:0];
}
+ (nullable NSDictionary *)constraintPinBottomSubview:(nonnull UIView *)subview bottomConstant:(CGFloat)bottomConstant {
return [NSLayoutConstraint constraintPinSubview:subview pinTop:false topConstant:0 pinBottom:true bottomConstant:bottomConstant pinLeft:false leftConstant:0 pinRight:false rightConstant:0];
}
+ (nullable NSDictionary *)constraintPinLeftSubview:(nonnull UIView *)subview leftConstant:(CGFloat)leftConstant {
return [NSLayoutConstraint constraintPinSubview:subview pinTop:false topConstant:0 pinBottom:false bottomConstant:0 pinLeft:true leftConstant:leftConstant pinRight:false rightConstant:0];
}
+ (nullable NSDictionary *)constraintPinRightSubview:(nonnull UIView *)subview rightConstant:(CGFloat)rightConstant {
return [NSLayoutConstraint constraintPinSubview:subview pinTop:false topConstant:0 pinBottom:false bottomConstant:0 pinLeft:false leftConstant:0 pinRight:true rightConstant:rightConstant];
}
+ (NSDictionary *)constraintPinSubview:(UIView *)subview pinTop:(BOOL)pinTop pinBottom:(BOOL)pinBottom pinLeft:(BOOL)pinLeft pinRight:(BOOL)pinRight {
return [NSLayoutConstraint constraintPinSubview:subview pinTop:pinTop topConstant:0 pinBottom:pinBottom bottomConstant:0 pinLeft:pinLeft leftConstant:0 pinRight:pinRight rightConstant:0];
}
+ (NSDictionary *)constraintPinSubview:(UIView *)subview pinTop:(BOOL)pinTop topConstant:(CGFloat)topConstant pinBottom:(BOOL)pinBottom bottomConstant:(CGFloat)bottomConstant pinLeft:(BOOL)pinLeft leftConstant:(CGFloat)leftConstant pinRight:(BOOL)pinRight rightConstant:(CGFloat)rightConstant {
UIView *superview = subview.superview;
NSMutableDictionary *constraintDic = [[NSMutableDictionary alloc] init];
if (pinTop) {
NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeTop multiplier:1 constant:topConstant];
top.priority = 999;
top.active = YES;
[constraintDic setObject:top forKey:ConstraintTop];
}
if (pinBottom) {
NSLayoutConstraint *bottom = [NSLayoutConstraint constraintWithItem:superview attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:subview attribute:NSLayoutAttributeBottom multiplier:1 constant:bottomConstant];
bottom.priority = 999;
bottom.active = YES;
[constraintDic setObject:bottom forKey:ConstraintBot];
}
if (pinLeft) {
NSLayoutConstraint *leading = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeLeading multiplier:1 constant:leftConstant];
leading.priority = 999;
leading.active = YES;
[constraintDic setObject:leading forKey:ConstraintLeading];
}
if (pinRight) {
NSLayoutConstraint *trailing = [NSLayoutConstraint constraintWithItem:superview attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:subview attribute:NSLayoutAttributeTrailing multiplier:1 constant:rightConstant];
trailing.priority = 999;
trailing.active = YES;
[constraintDic setObject:trailing forKey:ConstraintTrailing];
}
return constraintDic;
}
+ (NSDictionary *)constraintPinSubviewToCenterOfSuperview:(UIView *)subview {
return [NSLayoutConstraint constraintPinSubview:subview pinCenterX:YES pinCenterY:YES];
}
+ (NSDictionary *)constraintPinSubview:(UIView *)subview pinCenterX:(BOOL)pinCenterX pinCenterY:(BOOL)pinCenterY {
return [NSLayoutConstraint constraintPinSubview:subview pinCenterX:pinCenterX centerXConstant:0 pinCenterY:pinCenterY centerYConstant:0];
}
+ (NSDictionary *)constraintPinSubview:(UIView *)subview pinCenterX:(BOOL)pinCenterX centerXConstant:(CGFloat)centerXConstant pinCenterY:(BOOL)pinCenterY centerYConstant:(CGFloat)centerYConstant {
UIView *superview = subview.superview;
NSMutableDictionary *constraintDic = [[NSMutableDictionary alloc]init];
if (pinCenterX) {
NSLayoutConstraint *centerX = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeCenterX multiplier:1 constant:centerXConstant];
centerX.priority = 999;
centerX.active = YES;
[constraintDic setObject:centerX forKey:ConstraintCenterX];
}
if (pinCenterY) {
NSLayoutConstraint *centerY = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:centerYConstant];
centerY.priority = 999;
centerY.active = YES;
[constraintDic setObject:centerY forKey:ConstraintCenterY];
}
return constraintDic;
}
+ (nullable NSDictionary *)constraintPinView:(nonnull UIView *)view heightConstraint:(BOOL)pinHeight heightConstant:(CGFloat)heightConstant widthConstraint:(BOOL)pinWidth widthConstant:(CGFloat)widthConstant {
NSMutableDictionary *constraintDic = [[NSMutableDictionary alloc] init];
if (pinHeight) {
NSLayoutConstraint *height = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:heightConstant];
height.priority = 999;
height.active = YES;
[constraintDic setObject:height forKey:ConstraintHeight];
}
if (pinWidth) {
NSLayoutConstraint *width = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:widthConstant];
width.priority = 999;
width.active = YES;
[constraintDic setObject:width forKey:ConstraintWidth];
}
return constraintDic;
}
+ (NSLayoutConstraint *)constraintPinFirstView:(nonnull UIView *)firstView toSecondView:(nonnull UIView *)secondView withConstant:(CGFloat)constant directionVertical:(BOOL)directionVertical {
//@Chris: Added the commont braces as to avoid crash when a negative constant comes in -Arun
NSString *pinString;
if (directionVertical) {
pinString = [NSString stringWithFormat:@"V:[firstView]-(%f)-[secondView]",constant];
} else {
pinString = [NSString stringWithFormat:@"H:[firstView]-(%f)-[secondView]",constant];
}
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:pinString options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(firstView, secondView)];
NSLayoutConstraint *constraint = constraints[0];
constraint.priority = 999;
[NSLayoutConstraint activateConstraints:constraints];
return constraint;
}
+ (nullable NSDictionary *)constraintAlignView:(nonnull UIView *)firstView toSecondView:(nonnull UIView *)secondView alignX:(BOOL)alignX alignY:(BOOL)alignY {
NSMutableDictionary *constraintsDictionary = [[NSMutableDictionary alloc] init];
if (alignX) {
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:firstView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:secondView attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0];
[firstView.superview addConstraint:constraint];
[constraintsDictionary setObject:constraint forKey:ConstraintCenterX];
}
if (alignY) {
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:firstView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:secondView attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0];
[firstView.superview addConstraint:constraint];
[constraintsDictionary setObject:constraint forKey:ConstraintCenterY];
}
return constraintsDictionary;
}
#pragma mark - Scaling constraints
+ (nullable NSDictionary *)scalingConstraintPinSubview:(nullable UIView *)subview pinTop:(BOOL)pinTop topConstant:(CGFloat)topConstant pinBottom:(BOOL)pinBottom bottomConstant:(CGFloat)bottomConstant pinLeft:(BOOL)pinLeft leftConstant:(CGFloat)leftConstant pinRight:(BOOL)pinRight rightConstant:(CGFloat)rightConstant baseConstant:(CGFloat)baseConstant {
return [self scalingConstraintPinSubview:subview pinTop:pinTop topConstant:topConstant pinBottom:pinBottom bottomConstant:bottomConstant pinLeft:pinLeft leftConstant:leftConstant pinRight:pinRight rightConstant:rightConstant baseConstant:baseConstant anchor:nil];
}
+ (nullable NSDictionary *)scalingConstraintPinSubview:(nullable UIView *)subview pinTop:(BOOL)pinTop topConstant:(CGFloat)topConstant pinBottom:(BOOL)pinBottom bottomConstant:(CGFloat)bottomConstant pinLeft:(BOOL)pinLeft leftConstant:(CGFloat)leftConstant pinRight:(BOOL)pinRight rightConstant:(CGFloat)rightConstant baseConstant:(CGFloat)baseConstant anchor:(nullable NSLayoutDimension *)anchor {
NSMutableDictionary *constraints = [[NSMutableDictionary alloc] init];
if (pinTop){
[constraints setObject:[self scalingPinViewTopToSuper:subview ratio:topConstant/baseConstant anchor:anchor] forKey:ConstraintTop];
}
if (pinBottom){
[constraints setObject:[self scalingPinViewBottomToSuper:subview ratio:bottomConstant/baseConstant anchor:anchor] forKey:ConstraintBot];
}
if (pinLeft) {
[constraints setObject:[self scalingPinViewLeftToSuper:subview ratio:leftConstant/baseConstant anchor:anchor] forKey:ConstraintLeading];
}
if (pinRight){
[constraints setObject:[self scalingPinViewRightToSuper:subview ratio:rightConstant/baseConstant anchor:anchor] forKey:ConstraintTrailing];
}
return constraints;
}
+ (nonnull NSLayoutConstraint *)scalingPinViewLeftToSuper:(nonnull UIView *)view ratio:(CGFloat)ratio anchor:(nullable NSLayoutDimension *)anchor {
NSLayoutConstraint *constraint = [self scalingConstraintPinView:view.superview toView:view layoutAxis:UILayoutConstraintAxisHorizontal relation:NSLayoutRelationEqual ratio:ratio anchor:anchor];
constraint.active = YES;
return constraint;
}
+ (nonnull NSLayoutConstraint *)scalingPinViewRightToSuper:(nonnull UIView *)view ratio:(CGFloat)ratio anchor:(nullable NSLayoutDimension *)anchor {
NSLayoutConstraint *constraint = [self scalingConstraintPinView:view toView:view.superview layoutAxis:UILayoutConstraintAxisHorizontal relation:NSLayoutRelationEqual ratio:ratio anchor:anchor];
constraint.active = YES;
return constraint;
}
+ (nonnull NSLayoutConstraint *)scalingPinViewTopToSuper:(nonnull UIView *)view ratio:(CGFloat)ratio anchor:(nullable NSLayoutDimension *)anchor {
NSLayoutConstraint *constraint = [self scalingConstraintPinView:view.superview toView:view layoutAxis:UILayoutConstraintAxisVertical relation:NSLayoutRelationEqual ratio:ratio anchor:anchor];
constraint.active = YES;
return constraint;
}
+ (nonnull NSLayoutConstraint *)scalingPinViewBottomToSuper:(nonnull UIView *)view ratio:(CGFloat)ratio anchor:(nullable NSLayoutDimension *)anchor {
NSLayoutConstraint *constraint = [self scalingConstraintPinView:view toView:view.superview layoutAxis:UILayoutConstraintAxisVertical relation:NSLayoutRelationEqual ratio:ratio anchor:anchor];
constraint.active = YES;
return constraint;
}
+ (nonnull NSLayoutConstraint *)scalingConstraintPinView:(nonnull UIView *)view toView:(nonnull UIView *)toView layoutAxis:(UILayoutConstraintAxis)layoutAxis relation:(NSLayoutRelation)relation ratio:(CGFloat)ratio anchor:(nullable NSLayoutDimension *)anchor {
NSLayoutDimension *dimension = nil;
NSLayoutDimension *defaultAnchor = nil;
if (layoutAxis == UILayoutConstraintAxisHorizontal) {
if (view == toView.superview) {
// Superview left edge to the subview left.
dimension = [view.leftAnchor anchorWithOffsetToAnchor:toView.leftAnchor];
defaultAnchor = view.widthAnchor;
} else if (toView == view.superview) {
// subview right edge to the superview right.
dimension = [view.rightAnchor anchorWithOffsetToAnchor:toView.rightAnchor];
defaultAnchor = toView.widthAnchor;
} else {
// view a to view b.
dimension = [view.rightAnchor anchorWithOffsetToAnchor:toView.leftAnchor];
defaultAnchor = view.superview.widthAnchor;
}
} else {
if (view == toView.superview) {
// Superview top edge to the subview top.
dimension = [view.topAnchor anchorWithOffsetToAnchor:toView.topAnchor];
defaultAnchor = view.widthAnchor;
} else if (toView == view.superview) {
// subview bottom edge to the superview bottom.
dimension = [view.bottomAnchor anchorWithOffsetToAnchor:toView.bottomAnchor];
defaultAnchor = toView.widthAnchor;
} else {
// view a to view b.
dimension = [view.bottomAnchor anchorWithOffsetToAnchor:toView.topAnchor];
defaultAnchor = view.superview.widthAnchor;
}
}
// If no passed in anchor, use the default.
if (!anchor) {
anchor = defaultAnchor;
}
NSLayoutConstraint *constraint;
switch (relation) {
case NSLayoutRelationLessThanOrEqual:
constraint = [dimension constraintLessThanOrEqualToAnchor:anchor multiplier:ratio];
break;
case NSLayoutRelationGreaterThanOrEqual:
constraint = [dimension constraintGreaterThanOrEqualToAnchor:anchor multiplier:ratio];
break;
default:
constraint = [dimension constraintEqualToAnchor:anchor multiplier:ratio];
break;
}
return constraint;
}
@end

View File

@ -0,0 +1,432 @@
//
// UIColor+MVMCoreUIConvenience.m
// mobilefirst
//
// Created by Chris Yang on 2/21/16.
// Copyright © 2016 Verizon Wireless. All rights reserved.
//
#import "UIColor+MVMCoreUIConvenience.h"
#import <MVMCore/MVMCoreDispatchUtility.h>
@implementation UIColor (MVMCoreUIConvenience)
#pragma mark - 2.0
+ (nonnull UIColor *)mfNegativeOrangeColor {
return [UIColor mfPumpkinColor];
}
+ (nonnull UIColor *)mfSwitchOnTintColor {
return [UIColor mfShamrock];
}
+ (nonnull UIColor *)mfSwitchOffTintColor {
return [UIColor mfColor8bitsWithRed:0 green:0 blue:0 alpha:1.0];
}
+ (nonnull UIColor *)mfSilver {
return [UIColor mfColor8bitsWithRed:216 green:218 blue:218 alpha:1.0];
}
+ (nonnull UIColor *)mfSilverTwo {
return [UIColor mfColor8bitsWithRed:217 green:219 blue:219 alpha:1.0];
}
+ (nonnull UIColor *)mfBattleshipGrey {
return [UIColor mfColor8bitsWithRed:116 green:118 blue:118 alpha:1.0];
}
+ (nonnull UIColor *)mfLightSilver {
return [UIColor mfColor8bitsWithRed:243 green:243 blue:243 alpha:1.0];
}
+ (nonnull UIColor *)mfDarkSilver {
return [UIColor mfColor8bitsWithRed:198 green:197 blue:197 alpha:1.0];
}
+ (nonnull UIColor *)mfPrimaryButtonHighlightBlackColor {
return [UIColor mfColor8bitsWithRed:51 green:51 blue:51 alpha:1.0];
}
+ (nonnull UIColor *)mfPrimaryWhiteButtonDisableColor {
return [UIColor mfColor8bitsWithRed:51 green:51 blue:51 alpha:1.0];
}
+ (nonnull UIColor *)mfTomatoRed {
return [UIColor mfColor8bitsWithRed:213 green:43 blue:30 alpha:1.0];
}
+ (nonnull UIColor *)mfPumpkinColor {
return [UIColor mfColor8bitsWithRed:204 green:77 blue:15 alpha:1.0];
}
+ (nonnull UIColor *)mfShamrock {
return [UIColor mfColor8bitsWithRed:0 green:134 blue:49 alpha:1.0];
}
+ (nonnull UIColor *)mfCerulean {
return [UIColor mfColor8bitsWithRed:0 green:122 blue:184 alpha:1.0];
}
+ (nonnull UIColor *)mfLightBlackColor {
return [UIColor mfColor8bitsWithRed:95 green:95 blue:95 alpha:1.0];
}
+ (nonnull UIColor *)mfWhiteTwo {
return [UIColor mfColor8bitsWithRed:246 green:246 blue:246 alpha:1.0];
}
#pragma mark - legacy
+ (nonnull UIColor *)mfRedColor {
return [UIColor colorWithRed:.804 green:.016 blue:.043 alpha:1.0];
}
+ (nonnull UIColor *)mfDarkerRedColor {
return [UIColor colorWithRed:.6 green:.012 blue:.031 alpha:1.0];
}
+ (nonnull UIColor *)mfBackgroundGray1 {
return [UIColor colorWithRed:.894 green:.898 blue:.89 alpha:1.0];
}
+ (nonnull UIColor *)mfBackgroundGray {
return [UIColor colorWithRed:.965 green:.965 blue:.965 alpha:1.0];
}
+ (nonnull UIColor *)mfTextDarkerGray {
return [UIColor mfColor8bitsWithRed:51 green:51 blue:51 alpha:1.f];
}
+ (nonnull UIColor *)mfTextLightGray {
return [UIColor mfColor8bitsWithRed:102 green:102 blue:102 alpha:1.0];
}
+ (nonnull UIColor *)mfSupportTitleColor {
return [UIColor mfColor8bitsWithRed:155 green:155 blue:155 alpha:1.0];
}
+ (nonnull UIColor *)mfSupportTextColor {
return [UIColor mfColor8bitsWithRed:255 green:255 blue:255 alpha:1.0];
}
+ (nonnull UIColor *)mfColorForCardText {
return [UIColor mfColor8bitsWithRed:156 green:125 blue:75 alpha:1.0];
}
+ (nonnull UIColor *)mfLightGrayColor {
return [UIColor mfColor8bitsWithRed:116 green:118 blue:118 alpha:1.0];
}
+ (nonnull UIColor *)mfLighterGrayColor {
return [UIColor colorWithRed:.8 green:.8 blue:.8 alpha:1.0];
}
+ (nonnull UIColor *)mfGrayColor {
return [UIColor colorWithRed:.29 green:.29 blue:.29 alpha:1.0];
}
+ (nonnull UIColor *)mfWarmGray {
return [UIColor colorWithRed:.462 green:.462 blue:.462 alpha:1.0];
}
+ (nonnull UIColor *)mfCharcoalColor {
return [UIColor colorWithRed:.2 green:.2 blue:.2 alpha:1.0];
}
+ (nonnull UIColor *)mfSupportSearchXGreyColor {
return [UIColor colorWithRed:.584 green:.584 blue:.584 alpha:1.0];
}
+ (nonnull UIColor *)mfMainMenuCellColor {
return [UIColor colorWithRed:.133 green:.133 blue:.133 alpha:1.0];
}
+ (nonnull UIColor *)mfMainMenuSeparatorColor {
return [UIColor colorWithRed:229 green:229 blue:227 alpha:1.0];
}
+ (nonnull UIColor *)mfTextButtonColor {
return [UIColor colorWithRed:0 green:0 blue:0 alpha:1.0];
}
+ (nonnull UIColor *)mfTextButtonColorHighlighted {
return [UIColor colorWithRed:0 green:.278 blue:.557 alpha:1.0];
}
+ (nonnull UIColor *)mfTealColor {
return [UIColor colorWithRed:.51 green:.808 blue:.675 alpha:1.0];
}
+ (nonnull UIColor *)mfSkyColor {
return [UIColor colorWithRed:.671 green:.878 blue:.976 alpha:1.0];
}
+ (nonnull UIColor *)mfGoldColor {
return [UIColor colorWithRed:.973 green:.827 blue:.384 alpha:1.0];
}
+ (nonnull UIColor *)mfLakeBlueColor {
return [UIColor colorWithRed:0.015 green:0.498 blue:0.827 alpha:1];
}
+ (nonnull UIColor *)mfSalmonColor {
return [UIColor colorWithRed:.976 green:.698 blue:.584 alpha:1.0];
}
+ (nonnull UIColor *)mfGreenColor {
return [UIColor colorWithRed:.914 green:.973 blue:.914 alpha:1.0];
}
+ (nonnull UIColor *)mfBlueColor {
return [UIColor colorWithRed:.91 green:.965 blue:.996 alpha:1.0];
}
+ (nonnull UIColor *)mfGrayLoadingSpinnerColor {
return [UIColor colorWithRed:0.847 green:0.847f blue:0.847 alpha:1.0f];
}
+ (nonnull UIColor *)mfYellowColor {
return [UIColor colorWithRed:.996 green:1 blue:.894 alpha:1.0];
}
+ (nonnull UIColor *)mfYellowLightMustard {
return [UIColor colorWithRed:0.965 green:0.831 blue:0.365 alpha:1.0];
}
+ (nonnull UIColor *)mfYellowLightMustardTwo {
return [UIColor colorWithRed:248/255.f green:211/255.f blue:98/255.f alpha:1.0];
}
+ (nonnull UIColor *)mfOrangeColor {
return [UIColor mfGetColorForHex:@"#ed7000"];
}
+ (nonnull UIColor *)mfRobinsEggBlue {
return [UIColor mfColor8bitsWithRed:171 green:224 blue:249 alpha:1.0];
}
+ (nonnull UIColor *)mfPaleTealColor{
return [UIColor mfColor8bitsWithRed:130 green:206 blue:172 alpha:1.0];
}
+ (nonnull UIColor *)mfBrightSkyBlue{
return [UIColor mfColor8bitsWithRed:0 green:189 blue:255 alpha:1.0];
}
+ (nonnull UIColor *)mfGrayish {
return [UIColor mfColor8bitsWithRed:175 green:175 blue:175 alpha:1.0];
}
+ (nonnull UIColor *)mfBlushRed {
return [UIColor mfColor8bitsWithRed:247 green:181 blue:148 alpha:1.0];
}
+ (nonnull UIColor *)mfGrayishBrown {
return [UIColor mfColor8bitsWithRed:75 green:75 blue:75 alpha:1.0];
}
+ (nonnull UIColor *)mfBubbleBackgroundGray {
return [UIColor mfColor8bitsWithRed:75 green:75 blue:75 alpha:1.0];
}
+ (nonnull UIColor *)mfSupportSearchBarTextColor {
return [UIColor mfColor8bitsWithRed:101 green:101 blue:101 alpha:1.0];
}
+ (nonnull UIColor *)mfSupportHeaderTextLightGrayColor {
return [UIColor mfColor8bitsWithRed:164 green:164 blue:164 alpha:1.0];
}
+ (nonnull UIColor *)mfBlack {
return [UIColor mfColor8bitsWithRed:34 green:34 blue:34 alpha:1.0];
}
+ (nonnull UIColor *)mfSupportBackgroundColor {
return [UIColor mfColor8bitsWithRed:50 green:50 blue:50 alpha:1.0];
}
+ (nonnull UIColor *)mfSeafoamBlue {
return [UIColor mfColor8bitsWithRed:105 green:178 blue:213 alpha:1.0];
}
+ (nonnull UIColor *)mfLightSalmon {
return [UIColor mfColor8bitsWithRed:249 green:178 blue:149 alpha:1.0];
}
+ (nonnull UIColor *)mfBrownishGrey {
return [UIColor mfColor8bitsWithRed:102 green:102 blue:102 alpha:1.0];
}
+ (nonnull UIColor *)mfPaleGrey {
return [UIColor mfColor8bitsWithRed:245 green:245 blue:246 alpha:1.0];
}
+ (nonnull UIColor *)mfToolBarGrayColor {
return [UIColor mfColor8bitsWithRed:233 green:234 blue:235 alpha:1.0];
}
+ (nonnull UIColor *)mfPinkishGray {
return [UIColor mfColor8bitsWithRed:204 green:204 blue:204 alpha:1.0];
}
+ (nonnull UIColor *)mfLiliac {
return [UIColor mfColor8bitsWithRed:197 green:150 blue:250 alpha:1.0];
}
+ (nonnull UIColor *)mfPowderPink {
return [UIColor mfColor8bitsWithRed:250 green:175 blue:227 alpha:1.0];
}
+ (nonnull UIColor *)mfLightGrey {
return [UIColor mfColor8bitsWithRed:229 green:229 blue:227 alpha:1.0];
}
+ (nonnull UIColor *)mfWhiteThree {
return [UIColor mfColor8bitsWithRed:214 green:214 blue:214 alpha:1.0];
}
+ (nonnull UIColor *)mfSeafoamBlue2 {
return [UIColor mfColor8bitsWithRed:147 green:191 blue:248 alpha:1.0];
}
+ (nonnull UIColor *)mfLoyaltySpecialOffer {
return [UIColor colorWithRed:.992 green:.733 blue:.294 alpha:1.0];
}
+ (nonnull UIColor *)mfSlateBlue {
return [UIColor mfColor8bitsWithRed:0 green:125 blue:255 alpha:1.0];
}
+ (nullable UIColor *)mfGetColorForString:(nullable NSString *)string {
static NSDictionary *stringColorMapping;
static dispatch_once_t once;
dispatch_once(&once, ^{
stringColorMapping = @{@"PrimaryRed":[UIColor mfRedColor],
@"black":[UIColor blackColor],
@"red":[UIColor mfRedColor],
@"greyish":[UIColor mfLightGrayColor],
@"robinsEggBlue" : [UIColor mfRobinsEggBlue],
@"lightSalmon" : [UIColor mfLightSalmon],
@"seafoamBlue" : [UIColor mfSeafoamBlue],
@"light_salmon" : [UIColor mfLightSalmon],
@"seafoam_blue" : [UIColor mfSeafoamBlue2],
@"robins_egg_blue" : [UIColor mfRobinsEggBlue],
@"pinkish_grey": [UIColor mfPinkishGray],
@"pale_teal":[UIColor mfPaleTealColor],
@"liliac":[UIColor mfLiliac],
@"powder_pink":[UIColor mfPowderPink],
@"lightGrey":[UIColor mfLightGrey],
@"lightMustard":[UIColor mfYellowLightMustard],
@"whiteThree":[UIColor mfWhiteThree],
@"lightest_gray":[UIColor mfSupportTitleColor],
@"slate_blue":[UIColor mfSlateBlue],
@"pumpkin":[UIColor mfPumpkinColor],
@"cerulean":[UIColor mfCerulean]
};
});
UIColor *color = nil;
if (string && string.length > 0) {
color = [stringColorMapping objectForKey:string];
if (!color){
color = [UIColor blackColor];
}
} else {
color = [UIColor blackColor];
}
return color;
}
+ (nonnull UIColor *)mfGetColorForHex:(nonnull NSString *) hexString {
unsigned int hexint = 0;
// Create scanner
NSScanner *scanner = [NSScanner scannerWithString:hexString];
// Tell scanner to skip the # character
[scanner setCharactersToBeSkipped:[NSCharacterSet
characterSetWithCharactersInString:@"#"]];
[scanner scanHexInt:&hexint];
UIColor *color = [UIColor colorWithRed:((CGFloat) ((hexint & 0xFF0000) >> 16))/255
green:((CGFloat) ((hexint & 0xFF00) >> 8))/255
blue:((CGFloat) (hexint & 0xFF))/255
alpha:1];
return color;
}
// Needs to be 8 digit hash
+ (nonnull UIColor *)mfGetColorForHexWithTransparency:(nonnull NSString *)hexString {
unsigned int hexint = 0;
// Create scanner
NSScanner *scanner = [NSScanner scannerWithString:hexString];
// Tell scanner to skip the # character
[scanner setCharactersToBeSkipped:[NSCharacterSet
characterSetWithCharactersInString:@"#"]];
[scanner scanHexInt:&hexint];
UIColor *color = [UIColor colorWithRed:((CGFloat) ((hexint & 0xFF000000) >> 16))/255
green:((CGFloat) ((hexint & 0xFF0000) >> 8))/255
blue:((CGFloat) (hexint & 0xFF00))/255
alpha:((CGFloat) (hexint & 0xFF))/255];
return color;
}
+ (UIColor *)mfColor8bitsWithRed:(NSInteger)red green:(NSInteger)green blue:(NSInteger)blue alpha:(CGFloat)alpha {
return [UIColor colorWithRed:red/255.0f green:green/255.0 blue:blue/255.f alpha:1.0];
}
+ (nonnull UIColor *)mfGradientColor:(UIColor *)color {
CGFloat h,s,b,a;
if ([color getHue:&h saturation:&s brightness:&b alpha:&a]) {
return [UIColor colorWithHue:h
saturation:MAX(s - 0.17 , 0.0)
brightness:MIN(b - 0.03, 1.0)
alpha:a];
}
return [UIColor whiteColor];
}
+ (void)mfSetBackgroundColorForNavigationBar:(nonnull UIColor *)color navigationBar:(nonnull UINavigationBar *)navigationBar transparent:(BOOL)transparent {
[MVMCoreDispatchUtility performBlockOnMainThread:^{
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
view.backgroundColor = color;
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
if (transparent) {
[navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
[navigationBar setTranslucent:NO];
} else {
[navigationBar setBackgroundImage:image forBarMetrics:UIBarMetricsDefault];
}
}];
}
#pragma mark - Hex String
+ (nullable NSString *)hexStringForColor:(nonnull UIColor*)color {
const CGFloat *components = CGColorGetComponents(color.CGColor);
if (CGColorGetNumberOfComponents(color.CGColor)>=3) {
CGFloat r = components[0];
CGFloat g = components[1];
CGFloat b = components[2];
return [NSString stringWithFormat:@"%02X%02X%02X", (int)(r * 255), (int)(g * 255), (int)(b * 255)];
} else {
return nil;
}
}
@end

View File

@ -1,5 +1,5 @@
//
// MFTabBarPageControlViewController.h
// MVMCoreUITabBarPageControlViewController.h
// mobilefirst
//
// Created by Scott Pfeil on 2/11/16.
@ -12,7 +12,7 @@
@class MVMCoreLoadObject;
@interface MFTabBarPageControlViewController : MFViewController <TopTabbarDataSource,TopTabbarDelegate,MVMCoreViewManagerProtocol>
@interface MVMCoreUITabBarPageControlViewController : MFViewController <TopTabbarDataSource,TopTabbarDelegate,MVMCoreViewManagerProtocol>
@property (nullable, weak, nonatomic) TopTabbar *tabBar;
@property (nonnull, strong, nonatomic, readonly) MFViewController *viewController;
@ -47,4 +47,11 @@
// For showing and hiding the top tab bar.
- (void)show:(BOOL)show animated:(BOOL)animated;
// Override to add tracking when a tab is selected.
- (void)trackSelectTab;
// Overide to pass custom parameters or additional data for a new tab load.
- (nullable NSDictionary *)getAdditionalDataForNewTabLoad:(nullable NSDictionary *)actionMap;
- (nonnull MVMCoreRequestParameters *)getRequestParametersForNewTabLoad:(nonnull MVMCoreRequestParameters *)requestParameters actionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData;
@end

View File

@ -1,12 +1,12 @@
//
// MFTabBarPageControlViewController.m
// MVMCoreUITabBarPageControlViewController.m
// mobilefirst
//
// Created by Scott Pfeil on 2/11/16.
// Copyright © 2016 Verizon Wireless. All rights reserved.
//
#import "MFTabBarPageControlViewController.h"
#import "MVMCoreUITabBarPageControlViewController.h"
#import <MVMCore/MVMCoreActionHandler.h>
#import <MVMCore/MVMCoreNavigationHandler.h>
#import <MVMCore/MVMCoreSessionTimeHandler.h>
@ -21,7 +21,7 @@
#import "MFTabBarSwipeAnimator.h"
#import "MFTabBarInteractor.h"
@interface MFTabBarPageControlViewController ()<MFSwipeNavigationProtocol>
@interface MVMCoreUITabBarPageControlViewController ()<MFSwipeNavigationProtocol>
@property (nullable, weak, nonatomic) UINavigationController *tabNavigationController;
@property (nullable, strong, nonatomic) NSArray *tabsInfo;
@ -38,7 +38,7 @@
@property (nonatomic) NSInteger selectedIndex;
@property (nonatomic) NSInteger previousIndex;
// Enable swipe gestures for viewControllers in MFTabBarPageControlViewController
// Enable swipe gestures for viewControllers in MVMCoreUITabBarPageControlViewController
@property (nonatomic) BOOL shouldEnableSwipeGestures;
// Controls user panning for swipe gesture.
@ -49,7 +49,7 @@
@end
@implementation MFTabBarPageControlViewController
@implementation MVMCoreUITabBarPageControlViewController
- (nullable instancetype)initWithViewController:(nonnull MFViewController *)viewController loadObject:(nullable MVMCoreLoadObject *)loadObject tabsInfo:(nonnull NSArray *)tabsInfo {
if (self = [super init]) {
@ -353,8 +353,6 @@
}
- (void)trackSelectTab {
NSDictionary *action_map = [self infoForSelectedTab];
[[MFAdobeTracker sharedTracker] trackActionData:[self getActionTrackDataDictionaryForActionInformation:action_map additionalData:self.loadObject.dataForPage]];
}
#pragma mark - top tab bar
@ -383,7 +381,6 @@
self.selectedIndex = index;
// Check if we can load an existing viewcontroller or we need to load a new one.
NSDictionary *action_map = [self infoForSelectedTab];
UIViewController *viewController = [self.viewControllers objectAtIndex:index ofType:[UIViewController class]];
if (viewController) {
@ -395,52 +392,34 @@
// track user action if we have a screen already loaded once the page is displayed in displayedViewController.
self.needToTrackTabSelect = YES;
} else {
//add device category for gridwall
NSMutableDictionary *additionalDatas = [[NSMutableDictionary alloc]initWithDictionary:self.loadObject.dataForPage];
additionalDatas[KeyDeviceCategoriesToShow] = [action_map stringForKey:KeyDeviceCategoriesToShow];
[additionalDatas setObject:@YES forKey:@"tabBarPressed"];
[[MVMCoreActionHandler sharedActionHandler] handleActionWithDictionary:action_map additionalData:additionalDatas delegate:self];
// Load new screen on tab.
NSDictionary *actionMap = [self infoForSelectedTab];
NSMutableDictionary *additionalData = [@{@"tabBarPressed":@YES} mutableCopy];
NSDictionary *customAdditionalData = [self getAdditionalDataForNewTabLoad:actionMap];
if (customAdditionalData) {
[additionalData addEntriesFromDictionary:customAdditionalData];
}
[[MVMCoreActionHandler sharedActionHandler] handleActionWithDictionary:actionMap additionalData:additionalData delegate:self];
}
}
return NO;
}
- (NSDictionary *)getActionTrackDataDictionaryForActionInformation:(NSDictionary *)actionInformation additionalData:(NSDictionary *)additionalData {
NSString *pageValue = self.pageType;
NSString *actionValue = [actionInformation stringForKey:KeyTitle];
NSMutableDictionary *actionData = [[NSMutableDictionary alloc] init];
if (pageValue) {
actionData[KeyAdobeTrackerPageName] = pageValue;
}
actionData[KeyAdobeTrackerLinkName] = [NSString stringWithFormat:@"%@", actionValue];
actionData[KeyAdobeTrackerActionPrefix] = KeyAdobeTrackerPrefixSubNav;
return actionData;
- (nullable NSDictionary *)getAdditionalDataForNewTabLoad:(nullable NSDictionary *)actionMap {
return nil;
}
- (nonnull MVMCoreRequestParameters *)getRequestParametersForNewTabLoad:(nonnull MVMCoreRequestParameters *)requestParameters actionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData {
return requestParameters;
}
- (void)handleOpenPageForRequestParameters:(MVMCoreRequestParameters *)requestParameters actionInformation:(NSDictionary *)actionInformation additionalData:(NSDictionary *)additionalData {
if ([additionalData boolForKey:@"tabBarPressed"]) {
// When we load gridwalls, we never want to load from cache because we're using the same
// modules for loading smartphones and tablets.
if ([requestParameters.pageType isEqualToString:PageTypeGridwall] ||
[requestParameters.pageType isEqualToString:PageTypeFeedGridwall ] || [requestParameters.pageType isEqualToString:PageTypeWorkshops] || [requestParameters.pageType isEqualToString:PageTypeAppointment] || [requestParameters.pageType isEqualToString:PageTypeAccessoryGridwall]) {
requestParameters.neverLoadFromCache = YES;
} else if ([requestParameters.pageType isEqualToString:PageTypeIntlMessageCompIntegration] && ![[NSUserDefaults standardUserDefaults] boolForKey:PageTypeIntlLandingHex]) {
[requestParameters addRequestParameters:@{@"displayInterceptPage": StringY}];
}
requestParameters.navigationController = self.tabNavigationController;
requestParameters.loadStyle = MFLoadStyleReplaceCurrent;
requestParameters.tabWasPressed = YES;
// to add aditional data passed from other controllers
// like selectedMdn in device flow(Manage/Controls)
if (additionalData) {
[requestParameters addRequestParameters:additionalData];
}
[super handleOpenPageForRequestParameters:requestParameters actionInformation:actionInformation additionalData:additionalData];
[super handleOpenPageForRequestParameters:[self getRequestParametersForNewTabLoad:requestParameters actionInformation:actionInformation additionalData:additionalData] actionInformation:actionInformation additionalData:additionalData];
} else {
[self.viewController handleOpenPageForRequestParameters:requestParameters actionInformation:actionInformation additionalData:additionalData];
}

View File

@ -40,7 +40,7 @@ FOUNDATION_EXPORT const unsigned char MVMCoreUIVersionString[];
#import <MVMCoreUI/MVMCoreUISplitViewController.h>
#import <MVMCoreUI/MVMCoreUIPanelButtonProtocol.h>
#import <MVMCoreUI/TopTabbar.h>
#import <MVMCoreUI/MFTabBarPageControlViewController.h>
#import <MVMCoreUI/MVMCoreUITabBarPageControlViewController.h>
#pragma mark - Atoms
#pragma mark Views

View File

@ -0,0 +1,36 @@
//
// FLAnimatedImageView.h
// Flipboard
//
// Created by Raphael Schaad on 7/8/13.
// Copyright (c) 2013-2015 Flipboard. All rights reserved.
//
#import <UIKit/UIKit.h>
@class FLAnimatedImage;
@protocol FLAnimatedImageViewDebugDelegate;
//
// An `FLAnimatedImageView` can take an `FLAnimatedImage` and plays it automatically when in view hierarchy and stops when removed.
// The animation can also be controlled with the `UIImageView` methods `-start/stop/isAnimating`.
// It is a fully compatible `UIImageView` subclass and can be used as a drop-in component to work with existing code paths expecting to display a `UIImage`.
// Under the hood it uses a `CADisplayLink` for playback, which can be inspected with `currentFrame` & `currentFrameIndex`.
//
@interface FLAnimatedImageView : UIImageView
// Setting `[UIImageView.image]` to a non-`nil` value clears out existing `animatedImage`.
// And vice versa, setting `animatedImage` will initially populate the `[UIImageView.image]` to its `posterImage` and then start animating and hold `currentFrame`.
@property (nonatomic, strong) FLAnimatedImage *animatedImage;
@property (nonatomic, copy) void(^loopCompletionBlock)(NSUInteger loopCountRemaining);
@property (nonatomic, strong, readonly) UIImage *currentFrame;
@property (nonatomic, assign, readonly) NSUInteger currentFrameIndex;
// The animation runloop mode. Enables playback during scrolling by allowing timer events (i.e. animation) with NSRunLoopCommonModes.
// To keep scrolling smooth on single-core devices such as iPhone 3GS/4 and iPod Touch 4th gen, the default run loop mode is NSDefaultRunLoopMode. Otherwise, the default is NSDefaultRunLoopMode.
@property (nonatomic, copy) NSString *runLoopMode;
@end

View File

@ -0,0 +1,436 @@
//
// FLAnimatedImageView.h
// Flipboard
//
// Created by Raphael Schaad on 7/8/13.
// Copyright (c) 2013-2015 Flipboard. All rights reserved.
//
#import "FLAnimatedImageView.h"
#import "FLAnimatedImage.h"
#if defined(DEBUG) && DEBUG
@protocol FLAnimatedImageViewDebugDelegate <NSObject>
@optional
- (void)debug_animatedImageView:(FLAnimatedImageView *)animatedImageView waitingForFrame:(NSUInteger)index duration:(NSTimeInterval)duration;
@end
#endif
@interface FLAnimatedImageView ()
// Override of public `readonly` properties as private `readwrite`
@property (nonatomic, strong, readwrite) UIImage *currentFrame;
@property (nonatomic, assign, readwrite) NSUInteger currentFrameIndex;
@property (nonatomic, assign) NSUInteger loopCountdown;
@property (nonatomic, assign) NSTimeInterval accumulator;
@property (nonatomic, strong) CADisplayLink *displayLink;
@property (nonatomic, assign) BOOL shouldAnimate; // Before checking this value, call `-updateShouldAnimate` whenever the animated image or visibility (window, superview, hidden, alpha) has changed.
@property (nonatomic, assign) BOOL needsDisplayWhenImageBecomesAvailable;
#if defined(DEBUG) && DEBUG
@property (nonatomic, weak) id<FLAnimatedImageViewDebugDelegate> debug_delegate;
#endif
@end
@implementation FLAnimatedImageView
@synthesize runLoopMode = _runLoopMode;
#pragma mark - Initializers
// -initWithImage: isn't documented as a designated initializer of UIImageView, but it actually seems to be.
// Using -initWithImage: doesn't call any of the other designated initializers.
- (instancetype)initWithImage:(UIImage *)image
{
self = [super initWithImage:image];
if (self) {
[self commonInit];
}
return self;
}
// -initWithImage:highlightedImage: also isn't documented as a designated initializer of UIImageView, but it doesn't call any other designated initializers.
- (instancetype)initWithImage:(UIImage *)image highlightedImage:(UIImage *)highlightedImage
{
self = [super initWithImage:image highlightedImage:highlightedImage];
if (self) {
[self commonInit];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self commonInit];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
[self commonInit];
}
return self;
}
- (void)commonInit
{
self.runLoopMode = [[self class] defaultRunLoopMode];
}
#pragma mark - Accessors
#pragma mark Public
- (void)setAnimatedImage:(FLAnimatedImage *)animatedImage
{
if (![_animatedImage isEqual:animatedImage]) {
if (animatedImage) {
// Clear out the image.
super.image = nil;
// Ensure disabled highlighting; it's not supported (see `-setHighlighted:`).
super.highlighted = NO;
// UIImageView seems to bypass some accessors when calculating its intrinsic content size, so this ensures its intrinsic content size comes from the animated image.
[self invalidateIntrinsicContentSize];
} else {
// Stop animating before the animated image gets cleared out.
[self stopAnimating];
}
_animatedImage = animatedImage;
self.currentFrame = animatedImage.posterImage;
self.currentFrameIndex = 0;
if (animatedImage.loopCount > 0) {
self.loopCountdown = animatedImage.loopCount;
} else {
self.loopCountdown = NSUIntegerMax;
}
self.accumulator = 0.0;
// Start animating after the new animated image has been set.
[self updateShouldAnimate];
if (self.shouldAnimate) {
[self startAnimating];
}
[self.layer setNeedsDisplay];
}
}
#pragma mark - Life Cycle
- (void)dealloc
{
// Removes the display link from all run loop modes.
[_displayLink invalidate];
}
#pragma mark - UIView Method Overrides
#pragma mark Observing View-Related Changes
- (void)didMoveToSuperview
{
[super didMoveToSuperview];
[self updateShouldAnimate];
if (self.shouldAnimate) {
[self startAnimating];
} else {
[self stopAnimating];
}
}
- (void)didMoveToWindow
{
[super didMoveToWindow];
[self updateShouldAnimate];
if (self.shouldAnimate) {
[self startAnimating];
} else {
[self stopAnimating];
}
}
- (void)setAlpha:(CGFloat)alpha
{
[super setAlpha:alpha];
[self updateShouldAnimate];
if (self.shouldAnimate) {
[self startAnimating];
} else {
[self stopAnimating];
}
}
- (void)setHidden:(BOOL)hidden
{
[super setHidden:hidden];
[self updateShouldAnimate];
if (self.shouldAnimate) {
[self startAnimating];
} else {
[self stopAnimating];
}
}
#pragma mark Auto Layout
- (CGSize)intrinsicContentSize
{
// Default to let UIImageView handle the sizing of its image, and anything else it might consider.
CGSize intrinsicContentSize = [super intrinsicContentSize];
// If we have have an animated image, use its image size.
// UIImageView's intrinsic content size seems to be the size of its image. The obvious approach, simply calling `-invalidateIntrinsicContentSize` when setting an animated image, results in UIImageView steadfastly returning `{UIViewNoIntrinsicMetric, UIViewNoIntrinsicMetric}` for its intrinsicContentSize.
// (Perhaps UIImageView bypasses its `-image` getter in its implementation of `-intrinsicContentSize`, as `-image` is not called after calling `-invalidateIntrinsicContentSize`.)
if (self.animatedImage) {
intrinsicContentSize = self.image.size;
}
return intrinsicContentSize;
}
#pragma mark - UIImageView Method Overrides
#pragma mark Image Data
- (UIImage *)image
{
UIImage *image = nil;
if (self.animatedImage) {
// Initially set to the poster image.
image = self.currentFrame;
} else {
image = super.image;
}
return image;
}
- (void)setImage:(UIImage *)image
{
if (image) {
// Clear out the animated image and implicitly pause animation playback.
self.animatedImage = nil;
}
super.image = image;
}
#pragma mark Animating Images
- (NSTimeInterval)frameDelayGreatestCommonDivisor
{
// Presision is set to half of the `kFLAnimatedImageDelayTimeIntervalMinimum` in order to minimize frame dropping.
const NSTimeInterval kGreatestCommonDivisorPrecision = 2.0 / kFLAnimatedImageDelayTimeIntervalMinimum;
NSArray *delays = self.animatedImage.delayTimesForIndexes.allValues;
// Scales the frame delays by `kGreatestCommonDivisorPrecision`
// then converts it to an UInteger for in order to calculate the GCD.
NSUInteger scaledGCD = lrint([delays.firstObject floatValue] * kGreatestCommonDivisorPrecision);
for (NSNumber *value in delays) {
scaledGCD = gcd(lrint([value floatValue] * kGreatestCommonDivisorPrecision), scaledGCD);
}
// Reverse to scale to get the value back into seconds.
return scaledGCD / kGreatestCommonDivisorPrecision;
}
static NSUInteger gcd(NSUInteger a, NSUInteger b)
{
// http://en.wikipedia.org/wiki/Greatest_common_divisor
if (a < b) {
return gcd(b, a);
} else if (a == b) {
return b;
}
while (true) {
NSUInteger remainder = a % b;
if (remainder == 0) {
return b;
}
a = b;
b = remainder;
}
}
- (void)startAnimating
{
if (self.animatedImage) {
// Lazily create the display link.
if (!self.displayLink) {
// It is important to note the use of a weak proxy here to avoid a retain cycle. `-displayLinkWithTarget:selector:`
// will retain its target until it is invalidated. We use a weak proxy so that the image view will get deallocated
// independent of the display link's lifetime. Upon image view deallocation, we invalidate the display
// link which will lead to the deallocation of both the display link and the weak proxy.
FLWeakProxy *weakProxy = [FLWeakProxy weakProxyForObject:self];
self.displayLink = [CADisplayLink displayLinkWithTarget:weakProxy selector:@selector(displayDidRefresh:)];
[self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:self.runLoopMode];
}
// Note: The display link's `.frameInterval` value of 1 (default) means getting callbacks at the refresh rate of the display (~60Hz).
// Setting it to 2 divides the frame rate by 2 and hence calls back at every other display refresh.
const NSTimeInterval kDisplayRefreshRate = 60.0; // 60Hz
self.displayLink.frameInterval = MAX([self frameDelayGreatestCommonDivisor] * kDisplayRefreshRate, 1);
self.displayLink.paused = NO;
} else {
[super startAnimating];
}
}
- (void)setRunLoopMode:(NSString *)runLoopMode
{
if (![@[NSDefaultRunLoopMode, NSRunLoopCommonModes] containsObject:runLoopMode]) {
NSAssert(NO, @"Invalid run loop mode: %@", runLoopMode);
_runLoopMode = [[self class] defaultRunLoopMode];
} else {
_runLoopMode = runLoopMode;
}
}
- (void)stopAnimating
{
if (self.animatedImage) {
self.displayLink.paused = YES;
} else {
[super stopAnimating];
}
}
- (BOOL)isAnimating
{
BOOL isAnimating = NO;
if (self.animatedImage) {
isAnimating = self.displayLink && !self.displayLink.isPaused;
} else {
isAnimating = [super isAnimating];
}
return isAnimating;
}
#pragma mark Highlighted Image Unsupport
- (void)setHighlighted:(BOOL)highlighted
{
// Highlighted image is unsupported for animated images, but implementing it breaks the image view when embedded in a UICollectionViewCell.
if (!self.animatedImage) {
[super setHighlighted:highlighted];
}
}
#pragma mark - Private Methods
#pragma mark Animation
// Don't repeatedly check our window & superview in `-displayDidRefresh:` for performance reasons.
// Just update our cached value whenever the animated image or visibility (window, superview, hidden, alpha) is changed.
- (void)updateShouldAnimate
{
BOOL isVisible = self.window && self.superview && ![self isHidden] && self.alpha > 0.0;
self.shouldAnimate = self.animatedImage && isVisible;
}
- (void)displayDidRefresh:(CADisplayLink *)displayLink
{
// If for some reason a wild call makes it through when we shouldn't be animating, bail.
// Early return!
if (!self.shouldAnimate) {
FLLog(FLLogLevelWarn, @"Trying to animate image when we shouldn't: %@", self);
return;
}
NSNumber *delayTimeNumber = [self.animatedImage.delayTimesForIndexes objectForKey:@(self.currentFrameIndex)];
// If we don't have a frame delay (e.g. corrupt frame), don't update the view but skip the playhead to the next frame (in else-block).
if (delayTimeNumber) {
NSTimeInterval delayTime = [delayTimeNumber floatValue];
// If we have a nil image (e.g. waiting for frame), don't update the view nor playhead.
UIImage *image = [self.animatedImage imageLazilyCachedAtIndex:self.currentFrameIndex];
if (image) {
FLLog(FLLogLevelVerbose, @"Showing frame %lu for animated image: %@", (unsigned long)self.currentFrameIndex, self.animatedImage);
self.currentFrame = image;
if (self.needsDisplayWhenImageBecomesAvailable) {
[self.layer setNeedsDisplay];
self.needsDisplayWhenImageBecomesAvailable = NO;
}
self.accumulator += displayLink.duration * displayLink.frameInterval;
// While-loop first inspired by & good Karma to: https://github.com/ondalabs/OLImageView/blob/master/OLImageView.m
while (self.accumulator >= delayTime) {
self.accumulator -= delayTime;
self.currentFrameIndex++;
if (self.currentFrameIndex >= self.animatedImage.frameCount) {
// If we've looped the number of times that this animated image describes, stop looping.
self.loopCountdown--;
if (self.loopCompletionBlock) {
self.loopCompletionBlock(self.loopCountdown);
}
if (self.loopCountdown == 0) {
[self stopAnimating];
return;
}
self.currentFrameIndex = 0;
}
// Calling `-setNeedsDisplay` will just paint the current frame, not the new frame that we may have moved to.
// Instead, set `needsDisplayWhenImageBecomesAvailable` to `YES` -- this will paint the new image once loaded.
self.needsDisplayWhenImageBecomesAvailable = YES;
}
} else {
FLLog(FLLogLevelDebug, @"Waiting for frame %lu for animated image: %@", (unsigned long)self.currentFrameIndex, self.animatedImage);
#if defined(DEBUG) && DEBUG
if ([self.debug_delegate respondsToSelector:@selector(debug_animatedImageView:waitingForFrame:duration:)]) {
[self.debug_delegate debug_animatedImageView:self waitingForFrame:self.currentFrameIndex duration:(NSTimeInterval)displayLink.duration * displayLink.frameInterval];
}
#endif
}
} else {
self.currentFrameIndex++;
}
}
+ (NSString *)defaultRunLoopMode
{
// Key off `activeProcessorCount` (as opposed to `processorCount`) since the system could shut down cores in certain situations.
return [NSProcessInfo processInfo].activeProcessorCount > 1 ? NSRunLoopCommonModes : NSDefaultRunLoopMode;
}
#pragma mark - CALayerDelegate (Informal)
#pragma mark Providing the Layer's Content
- (void)displayLayer:(CALayer *)layer
{
layer.contents = (__bridge id)self.image.CGImage;
}
@end

View File

@ -0,0 +1,36 @@
//
// MVMCoreUITopAlertBaseView.h
// mobilefirst
//
// Created by Scott Pfeil on 9/6/16.
// Copyright © 2016 Verizon Wireless. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <MVMCore/MVMCoreTopAlertAnimationDelegateProtocol.h>
#import <MVMCoreUI/MFView.h>
@class MVMCoreTopAlertObject;
@class MFCustomButton;
@interface MVMCoreUITopAlertBaseView : MFView
// Adds a top alert action.
+ (void)addActionToButton:(nonnull MFCustomButton *)button actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData;
// Returns a top alert styled label.
+ (nonnull UILabel *)topAlertLabel;
// Returns a string for the passed in messages.
+ (nullable NSAttributedString *)getStringForMessage:(nullable NSString *)message subMessage:(nullable NSString *)subMessage color:(nullable UIColor *)color;
// Adds a close button.
- (nonnull MFCustomButton *)addCloseButtonWithAnimationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate;
// Sets the background color based on the type
- (void)setColorForType:(nullable NSString *)type;
// Handles making various parts accessible.
- (void)handleAccessibility;
@end

View File

@ -0,0 +1,54 @@
//
// MVMCoreUITopAlertExpandableView.h
// mobilefirst
//
// Created by Scott Pfeil on 8/18/16.
// Copyright © 2016 Verizon Wireless. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "MVMCoreUITopAlertBaseView.h"
#import <MVMCore/MVMCoreTopAlertAnimationDelegateProtocol.h>
@class PrimaryButton;
@class MVMCoreUITopAlertShortView;
@class MVMCoreUITopAlertMainView;
@class MVMCoreTopAlertObject;
@interface MVMCoreUITopAlertExpandableView : MVMCoreUITopAlertBaseView
@property (nullable, weak, nonatomic) MVMCoreUITopAlertShortView *shortView;
@property (nullable, weak, nonatomic) MVMCoreUITopAlertMainView *buttonView;
// Setting this will hide the short view when the notification is collapsed.
@property (nonatomic) BOOL onlyShowTopMessageWhenCollapsed;
// A flag for if the top alert expandable view should collapse automatically after being expanded
@property (nonatomic) BOOL collapseAutomaticallyAfterExpanded;
// Standard
- (nullable instancetype)initWithTopAlertObject:(nonnull MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate viewToLayout:(nonnull UIView *)viewTolayout;
// Used primarily for when button presses will expand or collapse. (Short view button will need to be set manually)
- (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message buttonTitle:(nullable NSString *)buttonTitle animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate viewToLayout:(nonnull UIView *)viewTolayout;
- (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate viewToLayout:(nonnull UIView *)viewTolayout;
// Used when button uses standard action map.
- (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate viewToLayout:(nonnull UIView *)viewTolayout;
// Convenience change functions
- (void)setTopMessage:(nullable NSString *)topMessage;
- (void)setTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData;
- (void)setTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler;
// Setters for making buttons expand and collapse the cell.
- (void)setButtonPressToExpand;
- (void)setButtonPressToCollapse;
- (void)setShortViewPressToCollapse;
- (void)setShortViewPressToExpand;
// Animates
- (void)expand:(BOOL)animated;
- (void)collapse;
@end

View File

@ -0,0 +1,51 @@
//
// MVMCoreUITopAlertMainView.h
// mobilefirst
//
// Created by Scott Pfeil on 8/17/16.
// Copyright © 2016 Verizon Wireless. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "MVMCoreUITopAlertBaseView.h"
#import <MVMCore/MVMCoreTopAlertAnimationDelegateProtocol.h>
@class PrimaryButton;
@interface MVMCoreUITopAlertMainView : MVMCoreUITopAlertBaseView
@property (nullable, nonatomic, weak) UILabel *label;
@property (nullable, nonatomic, weak) PrimaryButton *button;
@property (nullable, nonatomic, strong) NSLayoutConstraint *height;
// Standard
- (nullable instancetype)initWithTopAlertObject:(nonnull MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate;
- (nullable instancetype)initWithColor:(nonnull UIColor *)color message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData closeButton:(BOOL)closeButton animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate;
// inits with images
- (nullable instancetype)initWithColor:(nonnull UIColor *)color imageURL:(nullable NSString *)imageURL message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData closeButton:(BOOL)closeButton animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate;
- (nullable instancetype)initWithColor:(nonnull UIColor *)color imageURL:(nullable NSString *)imageURL message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage closeButton:(BOOL)closeButton animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate;
// Setters for label and button.
- (void)setupWithMessage:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData;
- (void)setupWithMessage:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler;
// Setters for button.
- (void)setupButtonWithActionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData;
- (void)setupButtonWithButtonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler;
#pragma mark - legacy inits
// Legacy init: inits with a label and button, no close button or icon.
- (nullable instancetype)initWithColor:(nonnull UIColor *)color message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData;
// Legacy init: inits with a label and possible icon and close button. No main button.
- (nullable instancetype)initWithColor:(nonnull UIColor *)color message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage closeButton:(BOOL)closeButton animationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate;
// Legacy init: inits with a label and button, no close button or icon. If passing in a block to use for the button, the top alert delegate button functions will not be called.
- (nullable instancetype)initWithColor:(nonnull UIColor *)color message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler;
@end

View File

@ -0,0 +1,22 @@
//
// MVMCoreUITopAlertShortView.h
// mobilefirst
//
// Created by Scott Pfeil on 7/20/16.
// Copyright © 2016 Verizon Wireless. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "MVMCoreUITopAlertBaseView.h"
@class MVMCoreTopAlertObject;
@class MFCustomButton;
@interface MVMCoreUITopAlertShortView : MVMCoreUITopAlertBaseView
@property (nullable, weak, nonatomic) UILabel *label;
@property (nullable, weak, nonatomic) MFCustomButton *button;
- (nullable instancetype)initWithColor:(nonnull UIColor *)color message:(nullable NSString *)message actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData topAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject;
@end