Merge branch 'feature/load_image_swift' into 'develop'

Feature/load image swift

See merge request BPHV_MIPS/mvm_core_ui!8
This commit is contained in:
Suresh, Kamlesh 2019-03-21 14:46:44 -04:00
commit 103f465cc8
17 changed files with 525 additions and 629 deletions

View File

@ -20,6 +20,8 @@
D22D1F562204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D22D1F542204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
D22D1F572204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D22D1F552204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m */; };
D274CA332236A78900B01B62 /* StandardFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D274CA322236A78900B01B62 /* StandardFooterView.swift */; };
D282AAB4223FDDAE00C46919 /* MFLoadImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D282AAB3223FDDAE00C46919 /* MFLoadImageView.swift */; };
D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D282AAB9224131D100C46919 /* MFTransparentGIFView.swift */; };
D28B4F8A21FF967C00712C7A /* MVMCoreUIObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D28B4F8821FF967C00712C7A /* MVMCoreUIObject.h */; settings = {ATTRIBUTES = (Public, ); }; };
D28B4F8B21FF967C00712C7A /* MVMCoreUIObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D28B4F8921FF967C00712C7A /* MVMCoreUIObject.m */; };
D29770C821F7C4AE00B2F0D0 /* TopLabelsView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */; };
@ -80,10 +82,6 @@
D29DF25921E6A22D003B2FB9 /* MFButtonProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF25821E6A22D003B2FB9 /* MFButtonProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
D29DF25C21E6A2B6003B2FB9 /* DashLine.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF25A21E6A2B6003B2FB9 /* DashLine.h */; settings = {ATTRIBUTES = (Public, ); }; };
D29DF25D21E6A2B6003B2FB9 /* DashLine.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF25B21E6A2B6003B2FB9 /* DashLine.m */; };
D29DF26021E6A985003B2FB9 /* MFLoadImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF25E21E6A985003B2FB9 /* MFLoadImageView.h */; settings = {ATTRIBUTES = (Public, ); }; };
D29DF26121E6A985003B2FB9 /* MFLoadImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF25F21E6A985003B2FB9 /* MFLoadImageView.m */; };
D29DF26421E6A9D9003B2FB9 /* MFTransparentGIFView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF26221E6A9D9003B2FB9 /* MFTransparentGIFView.h */; settings = {ATTRIBUTES = (Public, ); }; };
D29DF26521E6A9D9003B2FB9 /* MFTransparentGIFView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF26321E6A9D9003B2FB9 /* MFTransparentGIFView.m */; };
D29DF26C21E6AA0B003B2FB9 /* FLAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF26821E6AA0B003B2FB9 /* FLAnimatedImage.m */; };
D29DF26D21E6AA0B003B2FB9 /* FLAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF26921E6AA0B003B2FB9 /* FLAnimatedImageView.m */; };
D29DF26E21E6AA0B003B2FB9 /* FLAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF26A21E6AA0B003B2FB9 /* FLAnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; };
@ -176,6 +174,8 @@
D22D1F542204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIStackableViewController.h; sourceTree = "<group>"; };
D22D1F552204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIStackableViewController.m; sourceTree = "<group>"; };
D274CA322236A78900B01B62 /* StandardFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StandardFooterView.swift; sourceTree = "<group>"; };
D282AAB3223FDDAE00C46919 /* MFLoadImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MFLoadImageView.swift; sourceTree = "<group>"; };
D282AAB9224131D100C46919 /* MFTransparentGIFView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MFTransparentGIFView.swift; sourceTree = "<group>"; };
D28B4F8821FF967C00712C7A /* MVMCoreUIObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIObject.h; sourceTree = "<group>"; };
D28B4F8921FF967C00712C7A /* MVMCoreUIObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIObject.m; sourceTree = "<group>"; };
D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TopLabelsView.m; sourceTree = "<group>"; };
@ -246,10 +246,6 @@
D29DF25821E6A22D003B2FB9 /* MFButtonProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFButtonProtocol.h; sourceTree = "<group>"; };
D29DF25A21E6A2B6003B2FB9 /* DashLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DashLine.h; sourceTree = "<group>"; };
D29DF25B21E6A2B6003B2FB9 /* DashLine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DashLine.m; sourceTree = "<group>"; };
D29DF25E21E6A985003B2FB9 /* MFLoadImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFLoadImageView.h; sourceTree = "<group>"; };
D29DF25F21E6A985003B2FB9 /* MFLoadImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFLoadImageView.m; sourceTree = "<group>"; };
D29DF26221E6A9D9003B2FB9 /* MFTransparentGIFView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFTransparentGIFView.h; sourceTree = "<group>"; };
D29DF26321E6A9D9003B2FB9 /* MFTransparentGIFView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFTransparentGIFView.m; sourceTree = "<group>"; };
D29DF26821E6AA0B003B2FB9 /* FLAnimatedImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLAnimatedImage.m; sourceTree = "<group>"; };
D29DF26921E6AA0B003B2FB9 /* FLAnimatedImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLAnimatedImageView.m; sourceTree = "<group>"; };
D29DF26A21E6AA0B003B2FB9 /* FLAnimatedImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLAnimatedImage.h; sourceTree = "<group>"; };
@ -556,10 +552,8 @@
D2C5001C21F8EE66001DA659 /* LabelWithInternalButton.m */,
D29DF28721E7AC2B003B2FB9 /* ViewConstrainingView.h */,
D29DF28821E7AC2B003B2FB9 /* ViewConstrainingView.m */,
D29DF26221E6A9D9003B2FB9 /* MFTransparentGIFView.h */,
D29DF26321E6A9D9003B2FB9 /* MFTransparentGIFView.m */,
D29DF25E21E6A985003B2FB9 /* MFLoadImageView.h */,
D29DF25F21E6A985003B2FB9 /* MFLoadImageView.m */,
D282AAB9224131D100C46919 /* MFTransparentGIFView.swift */,
D282AAB3223FDDAE00C46919 /* MFLoadImageView.swift */,
D29DF2AD21E7B3A4003B2FB9 /* MFTextView.h */,
D29DF2AB21E7B3A4003B2FB9 /* MFTextView.m */,
D29DF2AC21E7B3A4003B2FB9 /* MFTextView.xib */,
@ -704,7 +698,6 @@
buildActionMask = 2147483647;
files = (
D29DF18021E69E49003B2FB9 /* MFView.h in Headers */,
D29DF26421E6A9D9003B2FB9 /* MFTransparentGIFView.h in Headers */,
D29DF27921E7A533003B2FB9 /* MVMCoreUISession.h in Headers */,
D29DF25C21E6A2B6003B2FB9 /* DashLine.h in Headers */,
D206997721FB8A0B00CAE0DE /* MVMCoreUINavigationController.h in Headers */,
@ -765,7 +758,6 @@
D29DF17421E69E1F003B2FB9 /* MFCustomButton.h in Headers */,
D29DF29721E7ADB8003B2FB9 /* MFScrollingViewController.h in Headers */,
D29DF26F21E6AA0B003B2FB9 /* FLAnimatedImageView.h in Headers */,
D29DF26021E6A985003B2FB9 /* MFLoadImageView.h in Headers */,
D29DF2A121E7AF4E003B2FB9 /* MVMCoreUIUtility.h in Headers */,
D29DF17621E69E1F003B2FB9 /* PrimaryButton.h in Headers */,
D29DF2C821E7BFC1003B2FB9 /* MFSizeObject.h in Headers */,
@ -860,6 +852,7 @@
D29770F221F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.m in Sources */,
D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */,
D22D1F1F220343560077CEC0 /* MVMCoreUICheckMarkView.m in Sources */,
D282AAB4223FDDAE00C46919 /* MFLoadImageView.swift in Sources */,
D29DF11721E6805F003B2FB9 /* UIColor+MFConvenience.m in Sources */,
D29DF25321E6A177003B2FB9 /* MFDigitTextField.m in Sources */,
D29770F921F7C73800B2F0D0 /* PrimaryButtonView.m in Sources */,
@ -878,7 +871,7 @@
D29DF2A221E7AF4E003B2FB9 /* MVMCoreUIUtility.m in Sources */,
D29DF12B21E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.m in Sources */,
D29DF25421E6A177003B2FB9 /* MFMdnTextField.m in Sources */,
D29DF26521E6A9D9003B2FB9 /* MFTransparentGIFView.m in Sources */,
D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */,
D2A514672213885800345BFB /* StandardHeaderView.swift in Sources */,
D29DF13021E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m in Sources */,
D28B4F8B21FF967C00712C7A /* MVMCoreUIObject.m in Sources */,
@ -888,7 +881,6 @@
D29DF18121E69E50003B2FB9 /* MFView.m in Sources */,
D29DF18321E69E54003B2FB9 /* SeparatorView.m in Sources */,
D29DF17A21E69E1F003B2FB9 /* MFCustomButton.m in Sources */,
D29DF26121E6A985003B2FB9 /* MFLoadImageView.m in Sources */,
D274CA332236A78900B01B62 /* StandardFooterView.swift in Sources */,
D29DF2BF21E7BEA4003B2FB9 /* MVMCoreUITabBarPageControlViewController.m in Sources */,
D29DF28321E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.m in Sources */,
@ -950,6 +942,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
@ -1014,6 +1007,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";

View File

@ -75,6 +75,10 @@ static CGFloat const PrimaryButtonSmallHeight = 30.0;
#pragma mark - Setting
// The new defaults.
- (void)setAsStandardCustom;
- (void)setAsSecondaryCustom;
// For setting after creation.
- (void)setAsSmallButton:(BOOL)smallButton enabled:(BOOL)enabled bordered:(BOOL)bordered;

View File

@ -34,6 +34,56 @@
@implementation PrimaryButton
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
[self pinHeight];
[self setAsRed];
[self setAsSmallButton:NO];
}
return self;
}
- (CGSize)intrinsicContentSize {
CGSize size = [super intrinsicContentSize];
CGSize newSize = CGSizeMake(size.width + (self.smallButton ? [[self innerPaddingSmallButton] getValueBasedOnSize:self.sizeForSizing]*2 : [[self innerPadding] getValueBasedOnSize:self.sizeForSizing]*2), size.height);
if (self.tinyButton) {
newSize = CGSizeMake(size.width + [[self innerPaddingTinyButton] getValueBasedOnSize:self.sizeForSizing]*2 , size.height);
}
if (self.smallButton) {
CGFloat minimumWidth = [[self minimumWidthSmallButton] getValueBasedOnSize:self.sizeForSizing];
if (newSize.width > minimumWidth) {
return newSize;
} else {
return CGSizeMake(minimumWidth, size.height);
}
} else if (self.tinyButton) {
CGFloat minimumWidth = [[self minimumWidthTinyButton] getValueBasedOnSize:self.sizeForSizing];
if (newSize.width > minimumWidth) {
return newSize;
} else {
return CGSizeMake(minimumWidth, size.height);
}
} else {
CGFloat minimumWidth = [[self minimumWidth] getValueBasedOnSize:self.sizeForSizing];
if (newSize.width > minimumWidth) {
return newSize;
} else {
return CGSizeMake(minimumWidth, size.height);
}
}
}
- (void)pinHeight {
// Adds the height constraint.
if (!self.height) {
NSLayoutConstraint *height = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:[[self buttonHeight] getValueBasedOnSize:self.sizeForSizing]];
self.height = height;
self.heightConstraint = height;
height.active = YES;
}
}
#pragma mark - Sizing
- (MFSizeObject *)innerPadding {
@ -470,6 +520,15 @@
#pragma mark - Creation
+ (instancetype)getButton {
PrimaryButton *button = [PrimaryButton buttonWithType:UIButtonTypeCustom];
button.translatesAutoresizingMaskIntoConstraints = NO;
button.sizeForSizing = [MVMCoreUISplitViewController getApplicationViewWidth];
[button pinHeight];
button.skipHighlighted = NO;
return button;
}
+ (instancetype)primaryButton:(BOOL)enabled {
PrimaryButton *button = [self getButton];
button.primaryButtonType = PrimaryButtonTypeBlack;
@ -561,86 +620,56 @@
return button;
}
#pragma mark - For Subclassing
#pragma mark - Molecule protocol
- (void)setAsStandardCustom {
// Default to standard look.
self.primaryButtonType = PrimaryButtonTypeCustom;
self.fillColor = [UIColor blackColor];
self.textColor = [UIColor whiteColor];
self.borderColor = nil;
_bordered = false;
}
- (void)setAsSecondaryCustom {
// Default to standard look.
self.primaryButtonType = PrimaryButtonTypeCustom;
self.fillColor = nil;
self.textColor = nil;
self.borderColor = [UIColor blackColor];
_bordered = true;
}
- (void)setAsMolecule {
[self setAsStandardCustom];
}
- (void)setWithJSON:(NSDictionary *)json delegate:(NSObject *)delegate additionalData:(nullable NSDictionary *)additionalData {
self.primaryButtonType = PrimaryButtonTypeCustom;
NSString *color = [json string:@"fillColor"];
self.fillColor = (color ? [UIColor mfGetColorForHex:color] : nil);
color = [json string:KeyTextColor];
self.textColor = (color ? [UIColor mfGetColorForHex:color] : nil);
color = [json string:@"borderColor"];
self.borderColor = (color ? [UIColor mfGetColorForHex:color] : nil);
if (color) {
self.fillColor = [UIColor mfGetColorForHex:color];
}
if ((color = [json string:KeyTextColor])) {
self.textColor = [UIColor mfGetColorForHex:color];
}
if ((color = [json string:@"borderColor"])) {
self.borderColor = [UIColor mfGetColorForHex:color];
}
_bordered = self.borderColor != nil;
color = [json string:@"disabledFillColor"];
self.disabledFillColor = (color ? [UIColor mfGetColorForHex:color] : nil);
color = [json string:@"disabledTextColor"];
self.disabledTextColor = (color ? [UIColor mfGetColorForHex:color] : nil);
color = [json string:@"disabledBorderColor"];
self.disabledBorderColor = (color ? [UIColor mfGetColorForHex:color] : nil);
if ((color = [json string:@"disabledFillColor"])) {
self.disabledFillColor = [UIColor mfGetColorForHex:color];
}
if ((color = [json string:@"disabledTextColor"])) {
self.disabledTextColor = [UIColor mfGetColorForHex:color];
}
if ((color = [json string:@"disabledBorderColor"])) {
self.disabledBorderColor = [UIColor mfGetColorForHex:color];
}
[self setAsSmallButton:[json boolForKey:@"small"]];
[self setWithActionMap:json actionDelegate:([delegate conformsToProtocol:@protocol(MVMCoreActionDelegateProtocol)] ? (NSObject <MVMCoreActionDelegateProtocol>*)delegate : nil) additionalData:additionalData buttonDelegate:([delegate conformsToProtocol:@protocol(ButtonDelegateProtocol)] ? (id <ButtonDelegateProtocol>)delegate : nil)];
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
[self pinHeight];
[self setAsRed];
[self setAsSmallButton:NO];
}
return self;
}
- (CGSize)intrinsicContentSize {
CGSize size = [super intrinsicContentSize];
CGSize newSize = CGSizeMake(size.width + (self.smallButton ? [[self innerPaddingSmallButton] getValueBasedOnSize:self.sizeForSizing]*2 : [[self innerPadding] getValueBasedOnSize:self.sizeForSizing]*2), size.height);
if (self.tinyButton) {
newSize = CGSizeMake(size.width + [[self innerPaddingTinyButton] getValueBasedOnSize:self.sizeForSizing]*2 , size.height);
}
if (self.smallButton) {
CGFloat minimumWidth = [[self minimumWidthSmallButton] getValueBasedOnSize:self.sizeForSizing];
if (newSize.width > minimumWidth) {
return newSize;
} else {
return CGSizeMake(minimumWidth, size.height);
}
} else if (self.tinyButton) {
CGFloat minimumWidth = [[self minimumWidthTinyButton] getValueBasedOnSize:self.sizeForSizing];
if (newSize.width > minimumWidth) {
return newSize;
} else {
return CGSizeMake(minimumWidth, size.height);
}
} else {
CGFloat minimumWidth = [[self minimumWidth] getValueBasedOnSize:self.sizeForSizing];
if (newSize.width > minimumWidth) {
return newSize;
} else {
return CGSizeMake(minimumWidth, size.height);
}
}
}
+ (instancetype)getButton {
PrimaryButton *button = [PrimaryButton buttonWithType:UIButtonTypeCustom];
button.translatesAutoresizingMaskIntoConstraints = NO;
button.sizeForSizing = [MVMCoreUISplitViewController getApplicationViewWidth];
[button pinHeight];
button.skipHighlighted = NO;
return button;
}
- (void)pinHeight {
// Adds the height constraint.
if (!self.height) {
NSLayoutConstraint *height = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:[[self buttonHeight] getValueBasedOnSize:self.sizeForSizing]];
self.height = height;
self.heightConstraint = height;
height.active = YES;
}
}
#pragma mark - Handling Validations
- (void)setEnabledByValidity {

View File

@ -1,76 +0,0 @@
//
// MFLoadImageView.h
// mobilefirst
//
// Created by Scott Pfeil on 5/26/16.
// Copyright © 2016 Verizon Wireless. All rights reserved.
//
// Shows a loading indicator while the image is downloading and then replaces loading indicator with image after
#import <Foundation/Foundation.h>
#import <MVMCoreUI/MFTransparentGIFView.h>
@import MVMCore.MVMCoreCache;
@class MFLoadingSpinner;
@interface MFLoadImageView : UIView
@property (nonnull, strong, nonatomic) MFLoadingSpinner *loadingSpinner;
@property (nonnull, strong, nonatomic) MFTransparentGIFView *imageView;
@property (nullable, weak, nonatomic) NSLayoutConstraint *leftPin;
@property (nullable, weak, nonatomic) NSLayoutConstraint *rightPin;
@property (nullable, weak, nonatomic) NSLayoutConstraint *topPin;
@property (nullable, weak, nonatomic) NSLayoutConstraint *centerX;
@property (nullable, weak, nonatomic) NSLayoutConstraint *centerY;
@property (nullable, weak, nonatomic) NSLayoutConstraint *bottomPin;
@property (nullable, weak, nonatomic) NSLayoutConstraint *widthConstraint;
@property (nullable, weak, nonatomic) NSLayoutConstraint *heightConstraint;
// If true, will add size constraints once the image is downloaded. This will help remove white space for aspect fit issues.
@property (nonatomic) BOOL addSizeConstraintsForAspectRatio;
// image loaded in the center.
- (nonnull instancetype)initWithCenteredImage;
// Use to pin edges for the image. Shouldn't pin both left and right or top and bottom because then the image will stretch.
- (nonnull instancetype)initWithPinnedEdges:(UIRectEdge)edge;
// Returns the default setter block to be used
- (nonnull MVMCoreGetImageBlock)defaultCompletionBlock;
// Allows to pin edges after initialization
- (void)pinEdges:(UIRectEdge)edge;
// Helper for if we need to load a new image. Returns true if: there is no current image, imageName and the current loadingImageName are not the same, width and the current width are not the same, we are using a fallback image.
- (BOOL)shouldLoadImageWithName:(nullable NSString *)imageName width:(CGFloat)width;
// Loads an image with the name. This function will use the scene 7 MFCache function to download from server or from local
// @param imageName The string for the image, url or local name
// @param format The scene 7 format of the image
// @param width The scene7 width.
// @param height The scene7 height.
// @param customFallbackImage if nil, the default fallback for MF is used.
// @param completionHandler can be used to define a custom completion handler. Useful when loading images in a collection view. Load a UIImage when receiving image, load a gif when receiving imageData.
// See MFCache for more information of load image function
- (void)loadImageWithName:(nullable NSString *)imageName;
- (void)loadImageWithName:(nullable NSString *)imageName width:(nullable NSNumber *)width;
- (void)loadImageWithName:(nullable NSString *)imageName height:(nullable NSNumber *)height;
- (void)loadImageWithName:(nullable NSString *)imageName width:(nullable NSNumber *)width height:(nullable NSNumber *)height;
- (void)loadImageWithName:(nullable NSString *)imageName format:(nullable NSString *)format width:(nullable NSNumber *)width height:(nullable NSNumber *)height;
- (void)loadImageWithName:(nullable NSString *)imageName width:(nullable NSNumber *)width height:(nullable NSNumber *)height customFallbackImage:(nullable NSString *)customFallbackImage;
- (void)loadImageWithName:(nullable NSString *)imageName width:(nullable NSNumber *)width height:(nullable NSNumber *)height completionHandler:(nonnull MVMCoreGetImageBlock)completionHandler;
- (void)loadImageWithName:(nullable NSString *)imageName format:(nullable NSString *)format width:(nullable NSNumber *)width height:(nullable NSNumber *)height customFallbackImage:(nullable NSString *)customFallbackImage completionHandler:(nonnull MVMCoreGetImageBlock)completionHandler;
- (void)loadImageWithName:(nullable NSString *)imageName exceptImageType:(nullable NSString *)format width:(nullable NSNumber *)width height:(nullable NSNumber *)height customFallbackImage:(nullable NSString *)customFallbackImage;
// Loads a cropped image with the name. This function will use the scene 7 MFCache function to download from server or from local
// @param imageName The string for the image, url or local name
// @param width The scene7 width.
// @param height The scene7 height.
// @param cropRect The crop rectangle requested
// @param customFallbackImage if nil, the default fallback for MF is used.
// See MFCache for more information of load image function
- (void)loadCroppedImageWithName:(nullable NSString *)imageName width:(nullable NSNumber *)width height:(nullable NSNumber *)height cropRect:(CGRect)cropRect flipImage:(BOOL)flipImage customFallbackImage:(nullable NSString *)customFallbackImage;
@end

View File

@ -1,312 +0,0 @@
//
// MFLoadImageView.m
// mobilefirst
//
// Created by Scott Pfeil on 5/26/16.
// Copyright © 2016 Verizon Wireless. All rights reserved.
//
#import "MFLoadImageView.h"
#import "MFLoadingSpinner.h"
#import "NSLayoutConstraint+MFConvenience.h"
#import "MVMCoreUIUtility.h"
@import MVMCore.NSDictionary_MFConvenience;
@import MVMCore.MVMCoreDispatchUtility;
@import MVMCore.MVMCoreGetterUtility;
@import MVMCore.MVMCoreCache;
@interface MFLoadImageView ()
@property (nonnull, strong, nonatomic) NSLayoutConstraint *loadingSpinnerHeight;
@property (nonatomic) CGFloat height;
@property (strong, nonatomic) NSString *loadingImageName;
@property (nonatomic) CGFloat width;
@property (nonatomic) BOOL isFallbackImage;
@end
@implementation MFLoadImageView
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
[self setupView:UIRectEdgeNone];
}
return self;
}
- (nonnull instancetype)initWithCenteredImage {
return [self initWithPinnedEdges:UIRectEdgeNone];
}
- (nonnull instancetype)initWithPinnedEdges:(UIRectEdge)edge {
if (self = [super init]) {
[self setupView:edge];
}
return self;
}
- (void)setupView:(UIRectEdge)edge {
if (!self.imageView) {
self.clipsToBounds = YES;
self.translatesAutoresizingMaskIntoConstraints = NO;
[self setContentHuggingPriority:950 forAxis:UILayoutConstraintAxisHorizontal];
[self setContentHuggingPriority:950 forAxis:UILayoutConstraintAxisVertical];
MFTransparentGIFView *imageView = [[MFTransparentGIFView alloc] initWithFrame:CGRectZero];
imageView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:imageView];
self.imageView = imageView;
if (edge == UIRectEdgeAll) {
[imageView setContentHuggingPriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];
[imageView setContentHuggingPriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisVertical];
} else {
[imageView setContentHuggingPriority:900 forAxis:UILayoutConstraintAxisHorizontal];
[imageView setContentHuggingPriority:900 forAxis:UILayoutConstraintAxisVertical];
}
[self pinEdges:edge];
MFLoadingSpinner *loadingSpinner = [[MFLoadingSpinner alloc] initWithFrame:CGRectZero];
loadingSpinner.clipsToBounds = YES;
loadingSpinner.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:loadingSpinner];
self.loadingSpinner = loadingSpinner;
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0@500-[loadingSpinner]-0@500-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(loadingSpinner)]];
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0@500-[loadingSpinner]-0@500-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(loadingSpinner)]];
[NSLayoutConstraint constraintWithItem:loadingSpinner attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0].active = YES;
[NSLayoutConstraint constraintWithItem:loadingSpinner attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0].active = YES;
self.loadingSpinnerHeight = [[loadingSpinner pinWidthAndHeight] objectForKey:ConstraintHeight ofType:[NSLayoutConstraint class]];
self.height = self.loadingSpinnerHeight.constant;
self.loadingSpinnerHeight.constant = 0;
self.loadingSpinnerHeight.active = YES;
[loadingSpinner pauseSpinner];
}
}
- (void)pinEdges:(UIRectEdge)edge {
if (self.topPin) {
[self removeConstraint:self.topPin];
}
NSLayoutRelation relation;
if (edge & UIRectEdgeTop) {
relation = NSLayoutRelationEqual;
} else {
relation = NSLayoutRelationGreaterThanOrEqual;
}
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeTop relatedBy:relation toItem:self attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
constraint.active = YES;
self.topPin = constraint;
if (self.bottomPin) {
[self removeConstraint:self.bottomPin];
}
if (edge & UIRectEdgeBottom) {
relation = NSLayoutRelationEqual;
} else {
relation = NSLayoutRelationGreaterThanOrEqual;
}
constraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeBottom relatedBy:relation toItem:self.imageView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0];
constraint.active = YES;
self.bottomPin = constraint;
if (self.leftPin) {
[self removeConstraint:self.leftPin];
}
if (edge & UIRectEdgeLeft) {
relation = NSLayoutRelationEqual;
} else {
relation = NSLayoutRelationGreaterThanOrEqual;
}
constraint = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeLeft relatedBy:relation toItem:self attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0];
constraint.active = YES;
self.leftPin = constraint;
if (self.rightPin) {
[self removeConstraint:self.rightPin];
}
if (edge & UIRectEdgeRight) {
relation = NSLayoutRelationEqual;
} else {
relation = NSLayoutRelationGreaterThanOrEqual;
}
constraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeRight relatedBy:relation toItem:self.imageView attribute:NSLayoutAttributeRight multiplier:1.0 constant:0];
constraint.active = YES;
self.rightPin = constraint;
if (self.centerY) {
[self removeConstraint:self.centerY];
}
if ((edge & (UIRectEdgeTop | UIRectEdgeBottom)) == 0) {
constraint = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0];
constraint.active = YES;
self.centerY = constraint;
}
if (self.centerX) {
[self removeConstraint:self.centerX];
}
if ((edge & (UIRectEdgeLeft | UIRectEdgeRight)) == 0) {
constraint = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0];
constraint.active = YES;
self.centerX = constraint;
}
}
- (nonnull MVMCoreGetImageBlock)defaultCompletionBlock {
return ^(UIImage * _Nullable image, NSData * _Nullable gifData, BOOL isFallBackImage) {
[MVMCoreDispatchUtility performBlockOnMainThread:^{
if (image && [image isKindOfClass:[UIImage class]]) {
[self.imageView setImage:image];
[self layoutIfNeeded];
} else if (gifData) {
[self.imageView loadGifWithData:gifData];
[self layoutIfNeeded];
}
}];
};
}
- (BOOL)shouldLoadImageWithName:(nullable NSString *)imageName width:(CGFloat)width {
return (!self.imageView.image && !self.imageView.animatedImage) || ![imageName isEqualToString:self.loadingImageName] || !fequal(width,self.width) || self.isFallbackImage;
}
- (void)loadImageWithName:(nullable NSString *)imageName {
[self loadImageWithName:imageName format:nil width:nil height:nil customFallbackImage:nil completionHandler:[self defaultCompletionBlock]];
}
- (void)loadImageWithName:(nullable NSString *)imageName width:(nullable NSNumber *)width {
[self loadImageWithName:imageName format:nil width:width height:nil customFallbackImage:nil completionHandler:[self defaultCompletionBlock]];
}
- (void)loadImageWithName:(nullable NSString *)imageName height:(nullable NSNumber *)height {
[self loadImageWithName:imageName format:nil width:nil height:height customFallbackImage:nil completionHandler:[self defaultCompletionBlock]];
}
- (void)loadImageWithName:(nullable NSString *)imageName width:(nullable NSNumber *)width height:(nullable NSNumber *)height {
[self loadImageWithName:imageName format:nil width:width height:height customFallbackImage:nil completionHandler:[self defaultCompletionBlock]];
}
- (void)loadImageWithName:(nullable NSString *)imageName format:(nullable NSString *)format width:(nullable NSNumber *)width height:(nullable NSNumber *)height {
[self loadImageWithName:imageName format:format width:width height:height customFallbackImage:nil completionHandler:[self defaultCompletionBlock]];
}
- (void)loadImageWithName:(nullable NSString *)imageName width:(nullable NSNumber *)width height:(nullable NSNumber *)height customFallbackImage:(nullable NSString *)customFallbackImage {
[self loadImageWithName:imageName format:nil width:width height:height customFallbackImage:customFallbackImage completionHandler:[self defaultCompletionBlock]];
}
- (void)loadImageWithName:(nullable NSString *)imageName width:(nullable NSNumber *)width height:(nullable NSNumber *)height completionHandler:(nonnull MVMCoreGetImageBlock)completionHandler {
[self loadImageWithName:imageName format:nil width:width height:height customFallbackImage:nil completionHandler:completionHandler];
}
- (void)loadImageWithName:(nullable NSString *)imageName exceptImageType:(nullable NSString *)format width:(nullable NSNumber *)width height:(nullable NSNumber *)height customFallbackImage:(nullable NSString *)customFallbackImage {
[self loadImageWithName:imageName format:format width:width height:height customFallbackImage:customFallbackImage completionHandler:[self defaultCompletionBlock]];
}
- (void)addConstraintsForWidth:(nullable NSNumber *)width height:(nullable NSNumber *)height size:(CGSize)size {
self.widthConstraint.active = NO;
self.heightConstraint.active = NO;
if (self.addSizeConstraintsForAspectRatio) {
if (width && height) {
NSLayoutConstraint *constraint = [self.imageView.heightAnchor constraintEqualToConstant:height.floatValue];
constraint.priority = 900;
constraint.active = YES;
self.heightConstraint = constraint;
constraint = [self.imageView.widthAnchor constraintEqualToConstant:width.floatValue];
constraint.priority = 900;
constraint.active = YES;
self.widthConstraint = constraint;
} else if (width) {
NSLayoutConstraint *constraint = [self.imageView.widthAnchor constraintEqualToConstant:width.floatValue];
constraint.priority = 900;
constraint.active = YES;
self.widthConstraint = constraint;
constraint = [self.imageView.heightAnchor constraintEqualToAnchor:self.imageView.widthAnchor multiplier:size.height/size.width];
constraint.priority = 900;
constraint.active = YES;
self.heightConstraint = constraint;
} else if (height) {
NSLayoutConstraint *constraint = [self.imageView.heightAnchor constraintEqualToConstant:height.floatValue];
constraint.priority = 900;
constraint.active = YES;
self.heightConstraint = constraint;
constraint = [self.imageView.widthAnchor constraintEqualToAnchor:self.imageView.heightAnchor multiplier:size.width/size.height];
constraint.priority = 900;
constraint.active = YES;
self.widthConstraint = constraint;
}
[self.imageView setContentHuggingPriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];
[self.imageView setContentHuggingPriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisVertical];
}
}
- (void)loadImageWithName:(nullable NSString *)imageName format:(nullable NSString *)format width:(nullable NSNumber *)width height:(nullable NSNumber *)height customFallbackImage:(nullable NSString *)customFallbackImage completionHandler:(nonnull MVMCoreGetImageBlock)completionHandler {
__weak typeof(self) weakSelf = self;
[MVMCoreDispatchUtility performBlockOnMainThread:^{
self.loadingImageName = imageName;
self.width = [width floatValue];
[self.loadingSpinner resumeSpinnerAfterDelay];
self.loadingSpinnerHeight.constant = self.height;
void (^finishedLoadBlock)(UIImage * _Nullable, NSData * _Nullable, BOOL) = ^(UIImage * _Nullable image, NSData * _Nullable imageData, BOOL isFallBackImage) {
[MVMCoreDispatchUtility performBlockOnMainThread:^{
// Makes sure the last requested image is the one we are loading.
if ([weakSelf.loadingImageName isEqualToString:imageName]) {
weakSelf.isFallbackImage = isFallBackImage;
weakSelf.loadingSpinnerHeight.constant = 0;
[weakSelf.loadingSpinner pauseSpinner];
[weakSelf addConstraintsForWidth:width height:height size:image.size];
completionHandler(image, imageData, isFallBackImage);
}
}];
};
NSString *fallBackImageName = [MVMCoreUIUtility localizedImageName:@"fallback"];
if ([[format lowercaseString] containsString:@"gif"]) {
// Gifs aren't supported by default and need special handling
[[MVMCoreCache sharedCache] getGif:imageName useWidth:(width ? YES : NO) widthForS7:[width floatValue] useHeight:(height ? YES : NO) heightForS7:[height floatValue] format:format localFallbackImageName:(customFallbackImage ?: fallBackImageName) completionHandler:^(UIImage * _Nullable image, NSData * _Nullable imageData, BOOL isFallBackImage) {
finishedLoadBlock(image, imageData, isFallBackImage);
}];
} else {
[[MVMCoreCache sharedCache] getImage:imageName useWidth:(width ? YES : NO) widthForS7:[width floatValue] useHeight:(height ? YES : NO) heightForS7:[height floatValue] format:format localFallbackImageName:(customFallbackImage ?: fallBackImageName) completionHandler:^(UIImage * _Nullable image, NSData * _Nullable imageData, BOOL isFallBackImage) {
finishedLoadBlock(image, nil, isFallBackImage);
}];
}
}];
}
- (void)loadCroppedImageWithName:(nullable NSString *)imageName width:(nullable NSNumber *)width height:(nullable NSNumber *)height cropRect:(CGRect)cropRect flipImage:(BOOL)flipImage customFallbackImage:(nullable NSString *)customFallbackImage {
[MVMCoreDispatchUtility performBlockOnMainThread:^{
self.loadingImageName = imageName;
[self.loadingSpinner resumeSpinnerAfterDelay];
self.loadingSpinnerHeight.constant = self.height;
__weak typeof(self) weakSelf = self;
[[MVMCoreCache sharedCache] getCroppedImage:imageName useWidth:(width ? YES : NO) widthForS7:[width floatValue] useHeight:(height ? YES : NO) heightForS7:[height floatValue] finalRect:cropRect flipImage:flipImage localFallbackImageName:(customFallbackImage ?: @"fallback") completionHandler:^(UIImage * _Nullable image, NSData * _Nullable imageData, BOOL isFallBackImage) {
[MVMCoreDispatchUtility performBlockOnMainThread:^{
if (image && [image isKindOfClass:[UIImage class]] && ([weakSelf.loadingImageName isEqualToString:imageName])) {
weakSelf.loadingSpinnerHeight.constant = 0;
[weakSelf.loadingSpinner pauseSpinner];
if (flipImage) {
[weakSelf.imageView setImage:[UIImage imageWithCGImage:image.CGImage
scale:image.scale
orientation:UIImageOrientationUpMirrored]];
} else {
[weakSelf.imageView setImage:image];
}
}
[weakSelf layoutIfNeeded];
}];
}];
}];
}
- (void)setFrame:(CGRect)frame {
[super setFrame:frame];
}
@end

View File

@ -0,0 +1,308 @@
//
// LoadImageView.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 3/18/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import UIKit
@objcMembers open class MFLoadImageView: ViewConstrainingView {
public let loadingSpinner = MFLoadingSpinner(frame: .zero)
public let imageView = MFTransparentGIFView(frame: .zero)
public var addSizeConstraintsForAspectRatio = false
var centerX: NSLayoutConstraint?
var centerY: NSLayoutConstraint?
var widthConstraint: NSLayoutConstraint?
var heightConstraint: NSLayoutConstraint?
var loadingSpinnerHeightConstraint: NSLayoutConstraint?
// For keeping track of current state.
var edges: UIRectEdge?
var spinnerHeight: CGFloat?
var width: CGFloat?
var loadingImageName: String?
var isFallbackImage: Bool = false
public init(pinnedEdges edge: UIRectEdge) {
edges = edge
super.init(frame: .zero)
}
// The default is an image that is centered with no edges pinned. So it will take the size of the content and fill as needed.
public init() {
edges = UIRectEdge(rawValue: 0)
super.init(frame: .zero)
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
public func pinEdges(_ edge: UIRectEdge) {
edges = edge
if edge == UIRectEdge.all {
imageView.setContentHuggingPriority(UILayoutPriority.defaultLow, for: NSLayoutConstraint.Axis.horizontal)
imageView.setContentHuggingPriority(UILayoutPriority.defaultLow, for: NSLayoutConstraint.Axis.vertical)
} else {
imageView.setContentHuggingPriority(UILayoutPriority(rawValue: 900), for: NSLayoutConstraint.Axis.horizontal)
imageView.setContentHuggingPriority(UILayoutPriority(rawValue: 900), for: NSLayoutConstraint.Axis.vertical)
}
if let topPin = topPin {
removeConstraint(topPin)
}
if edge.contains(UIRectEdge.top) {
topPin = imageView.topAnchor.constraint(equalTo: topAnchor)
} else {
topPin = imageView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor)
}
topPin?.isActive = true
if let bottomPin = bottomPin {
removeConstraint(bottomPin)
}
if edge.contains(UIRectEdge.bottom) {
bottomPin = bottomAnchor.constraint(equalTo: imageView.bottomAnchor)
} else {
bottomPin = bottomAnchor.constraint(greaterThanOrEqualTo: imageView.bottomAnchor)
}
bottomPin?.isActive = true
if let leftPin = leftPin {
removeConstraint(leftPin)
}
if edge.contains(UIRectEdge.left) {
leftPin = imageView.leftAnchor.constraint(equalTo: leftAnchor)
} else {
leftPin = imageView.leftAnchor.constraint(greaterThanOrEqualTo: leftAnchor)
}
leftPin?.isActive = true
if let rightPin = rightPin {
removeConstraint(rightPin)
}
if edge.contains(UIRectEdge.right) {
rightPin = rightAnchor.constraint(equalTo: imageView.rightAnchor)
} else {
rightPin = rightAnchor.constraint(greaterThanOrEqualTo: imageView.rightAnchor)
}
rightPin?.isActive = true
// If neither the top or the bottom are pinned, center it.
if let centerY = centerY {
removeConstraint(centerY)
}
if !edge.contains(UIRectEdge.top) && !edge.contains(UIRectEdge.bottom) {
centerY = imageView.centerYAnchor.constraint(equalTo: centerYAnchor)
centerY?.isActive = true
}
// If neither the left or the right are pinned, center it.
if let centerX = centerX {
removeConstraint(centerX)
}
if !edge.contains(UIRectEdge.left) && !edge.contains(UIRectEdge.right) {
centerX = imageView.centerXAnchor.constraint(equalTo: centerXAnchor)
centerX?.isActive = true
}
}
override open func setupView() {
super.setupView()
guard subviews.count == 0 else {
return
}
clipsToBounds = true
setContentHuggingPriority(UILayoutPriority(rawValue: 950), for: NSLayoutConstraint.Axis.horizontal)
setContentHuggingPriority(UILayoutPriority(rawValue: 950), for: NSLayoutConstraint.Axis.vertical)
// Setup image.
imageView.translatesAutoresizingMaskIntoConstraints = false;
addSubview(imageView)
// Setup edges constraints
if edges == nil {
edges = UIRectEdge(rawValue: 0)
}
pinEdges(edges!)
// Setup spinner.
loadingSpinner.clipsToBounds = true
loadingSpinner.translatesAutoresizingMaskIntoConstraints = false
addSubview(loadingSpinner)
NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0@500-[loadingSpinner]-0@500-|", metrics: nil, views: ["loadingSpinner" : loadingSpinner]))
NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0@500-[loadingSpinner]-0@500-|", metrics: nil, views: ["loadingSpinner" : loadingSpinner]))
loadingSpinner.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
loadingSpinner.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
if let constraint = loadingSpinner.pinWidthAndHeight()?[ConstraintHeight] as! NSLayoutConstraint? {
loadingSpinnerHeightConstraint = constraint
spinnerHeight = constraint.constant
loadingSpinnerHeightConstraint?.constant = 0
loadingSpinnerHeightConstraint?.isActive = true
loadingSpinner.pause()
}
}
open func defaultCompletionBlock() -> MVMCoreGetImageBlock {
return {image,gifData,_ in MVMCoreDispatchUtility.performBlock(onMainThread: { [weak self] in
if let image = image {
self?.imageView.image = image
self?.layoutIfNeeded()
} else if let gifData = gifData {
self?.imageView.loadGifWithData(gifData)
self?.layoutIfNeeded()
}
})}
}
open func shouldLoadImage(withName imageName: String?, width: CGFloat) -> Bool {
// We should load a new image if there is no current image, the image names are different, the width is different, or we are using a fallback image.
guard let currentWidth = self.width else {
return true
}
return (imageView.image == nil && imageView.animatedImage == nil) || imageName != loadingImageName || !MVMCoreGetterUtility.cgfequal(width, currentWidth) || self.isFallbackImage
}
// Constrains the image view to be the size provided. Used to size it to the image to fix aspect fit defect.
func addConstraints(width: NSNumber?, height: NSNumber?, size: CGSize?) {
widthConstraint?.isActive = false
heightConstraint?.isActive = false
guard addSizeConstraintsForAspectRatio else {
return
}
if let width = width, let height = height {
heightConstraint = imageView.heightAnchor.constraint(equalToConstant: height.cgfloat())
widthConstraint = imageView.widthAnchor.constraint(equalToConstant: width.cgfloat())
} else if let width = width, let size = size {
widthConstraint = imageView.widthAnchor.constraint(equalToConstant: width.cgfloat())
heightConstraint = imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor, multiplier: size.height/size.width)
} else if let height = height, let size = size {
heightConstraint = imageView.heightAnchor.constraint(equalToConstant: height.cgfloat())
widthConstraint = imageView.widthAnchor.constraint(equalTo: imageView.heightAnchor, multiplier: size.width/size.height)
}
widthConstraint?.priority = UILayoutPriority(rawValue: 900)
heightConstraint?.priority = UILayoutPriority(rawValue: 900)
heightConstraint?.isActive = true
widthConstraint?.isActive = true
imageView.setContentHuggingPriority(UILayoutPriority.defaultLow, for: NSLayoutConstraint.Axis.horizontal)
imageView.setContentHuggingPriority(UILayoutPriority.defaultLow, for: NSLayoutConstraint.Axis.vertical)
}
open override func updateView(_ size: CGFloat) {
super.updateView(size)
let width = size.rounded()
if let imageName = json?.optionalStringForKey("image"), shouldLoadImage(withName: imageName, width: width) {
imageView.image = nil
imageView.animatedImage = nil
loadImage(withName: imageName, format: json?.optionalStringForKey("imageFormat"), width: NSNumber(value: Double(width)), height: nil)
loadImage(withName: imageName, format: json?.optionalStringForKey("imageFormat"), width: NSNumber(value: Double(width)), height: nil, customFallbackImage: json?.optionalStringForKey("fallbackImage"))
}
}
// MARK: - MVMCoreUIMoleculeViewProtocol functions
open override func setWithJSON(_ json: [AnyHashable : Any]?, delegate: NSObject?, additionalData: [AnyHashable : Any]?) {
super.setWithJSON(json, delegate: delegate, additionalData: additionalData)
if let backgroundColorString = json?.optionalStringForKey(KeyBackgroundColor) {
backgroundColor = UIColor.mfGet(forHex: backgroundColorString)
}
if let accessibilityString = json?.optionalStringForKey("accessibilityText") {
imageView.accessibilityLabel = accessibilityString
imageView.accessibilityTraits = .staticText
imageView.isAccessibilityElement = true
}
}
// MARK: - load functions
public func loadImage(withName imageName: String?, format: String?, width: NSNumber?, height: NSNumber?, customFallbackImage: String?, completionHandler: @escaping MVMCoreGetImageBlock) {
MVMCoreDispatchUtility.performBlock(onMainThread: { [unowned self] in
self.loadingImageName = imageName
if let width = width {
self.width = width.cgfloat()
}
self.loadingSpinner.resumeSpinnerAfterDelay()
if let height = self.spinnerHeight {
self.loadingSpinnerHeightConstraint?.constant = height
}
let finishedLoadingBlock: MVMCoreGetImageBlock = {[weak self] (image, data, isFallbackImage) in MVMCoreDispatchUtility.performBlock(onMainThread: { [weak self] in
guard let loadingImageName = self?.loadingImageName, loadingImageName == imageName else {
return
}
self?.isFallbackImage = isFallbackImage
self?.loadingSpinnerHeightConstraint?.constant = 0
self?.loadingSpinner.pause()
self?.addConstraints(width: width, height: height, size: image?.size)
completionHandler(image,data,isFallbackImage)
})}
let fallbackImageName = customFallbackImage ?? MVMCoreUIUtility.localizedImageName("fallback")
if let format = format, format.lowercased().contains("gif") {
// Gifs aren't supported by default and need special handling
MVMCoreCache.shared()?.getGif(imageName, useWidth: width != nil, widthForS7: width?.intValue ?? 0, useHeight: height != nil, heightForS7: height?.intValue ?? 0, format: format, localFallbackImageName: fallbackImageName, completionHandler: finishedLoadingBlock)
} else {
MVMCoreCache.shared()?.getImage(imageName, useWidth: width != nil, widthForS7: width?.intValue ?? 0, useHeight: height != nil, heightForS7: height?.intValue ?? 0, localFallbackImageName: fallbackImageName, completionHandler: finishedLoadingBlock)
}
})
}
public func loadCroppedImage(withName imageName:
String?, width: NSNumber?, height: NSNumber?, cropRect: CGRect, flipImage: Bool, customFallbackImage: String?) {
MVMCoreDispatchUtility.performBlock(onMainThread: { [unowned self] in
self.loadingImageName = imageName
self.loadingSpinner.resumeSpinnerAfterDelay()
if let height = self.spinnerHeight {
self.loadingSpinnerHeightConstraint?.constant = height
}
MVMCoreCache.shared()?.getCroppedImage(imageName, useWidth: width != nil, widthForS7: width?.intValue ?? 0, useHeight: height != nil, heightForS7: height?.intValue ?? 0, finalRect: cropRect, flipImage: flipImage, localFallbackImageName: customFallbackImage ?? MVMCoreUIUtility.localizedImageName("fallback"), completionHandler: { [weak self] (image, data, isFallBackImage) in
MVMCoreDispatchUtility.performBlock(onMainThread: {
guard let image = image, let loadingImageName = self?.loadingImageName, loadingImageName == imageName else {
return
}
self?.loadingSpinnerHeightConstraint?.constant = 0
self?.loadingSpinner.pause()
if flipImage, let cgImage = image.cgImage {
self?.imageView.image = UIImage(cgImage: cgImage, scale: image.scale, orientation: UIImage.Orientation.upMirrored)
} else {
self?.imageView.image = image
}
self?.layoutIfNeeded()
})
})
})
}
public func loadImage(withName imageName: String?) {
loadImage(withName: imageName, format: nil, width: nil, height: nil, customFallbackImage: nil, completionHandler: defaultCompletionBlock())
}
public func loadImage(withName imageName: String?, width: NSNumber?) {
loadImage(withName: imageName, format: nil, width: width, height: nil, customFallbackImage: nil, completionHandler: defaultCompletionBlock())
}
public func loadImage(withName imageName: String?, height: NSNumber?) {
loadImage(withName: imageName, format: nil, width: nil, height: height, customFallbackImage: nil, completionHandler: defaultCompletionBlock())
}
public func loadImage(withName imageName: String?, width: NSNumber?, height: NSNumber?) {
loadImage(withName: imageName, format: nil, width: width, height: height, customFallbackImage: nil, completionHandler: defaultCompletionBlock())
}
public func loadImage(withName imageName: String?, format: String?, width: NSNumber?, height: NSNumber?) {
loadImage(withName: imageName, format: format, width: width, height: height, customFallbackImage: nil, completionHandler: defaultCompletionBlock())
}
public func loadImage(withName imageName: String?, width: NSNumber?, height: NSNumber?, customFallbackImage: String?) {
loadImage(withName: imageName, format: nil, width: width, height: height, customFallbackImage: customFallbackImage, completionHandler: defaultCompletionBlock())
}
public func loadImage(withName imageName: String?, width: NSNumber?, height: NSNumber?, completionHandler: @escaping MVMCoreGetImageBlock) {
loadImage(withName: imageName, format: nil, width: width, height: height, customFallbackImage: nil, completionHandler: completionHandler)
}
public func loadImage(withName imageName: String?, format: String?, width: NSNumber?, height: NSNumber?, customFallbackImage: String?) {
loadImage(withName: imageName, format: format, width: width, height: height, customFallbackImage: customFallbackImage, completionHandler: defaultCompletionBlock())
}
}

View File

@ -1,33 +0,0 @@
//
// MFTransparentGIFView.h
// mobilefirst
//
// Created by Wesolowski, Brendan on 3/16/16.
// Copyright © 2016 Verizon Wireless. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <MVMCoreUI/FLAnimatedImageView.h>
@interface MFTransparentGIFView : FLAnimatedImageView
/** Creates the GIF display view with the passed in frame.
frame: frame to set the view to.
ImageName: name of the .gif to load. Should not contain the extension.
StartImmediately: should the gif immeidately begin playing. If YES, it will start. If NO, call [performAnimations] to start it.
Duration: how long the animation takes to loop. Pass a negative value to use the default.
LoopCompletionBlock: a block called whenever the gif finishes a loop.
animatedImage : set as nil when use this view in reusable cell
*/
-(nullable instancetype)initWithFrame:(CGRect)frame ImageName:(nonnull NSString *)imageName StartImmediately:(BOOL)startImmediately Duration:(NSTimeInterval)duration LoopCompletionBlock:(void (^ __nullable)(NSUInteger loopCountRemaining))loopCompletionBlock;
-(void)loadImage:(nonnull NSString *)imageName StartImmediately:(BOOL)startImmediately Duration:(NSTimeInterval)duration LoopCompletionBlock:(void (^ __nullable)(NSUInteger))loopCompletionBlock;
-(void)loadGifWithData:(nonnull NSData *)imageData;
-(void)setImageData:(nonnull NSData *)imageData;
-(void)performAnimations;
@end

View File

@ -1,74 +0,0 @@
//
// MFTransparentGIFView.m
// mobilefirst
//
// Created by Wesolowski, Brendan on 3/16/16.
// Copyright © 2016 Verizon Wireless. All rights reserved.
//
#import "MFTransparentGIFView.h"
#import "FLAnimatedImage.h"
#import "MVMCoreUIUtility.h"
@import MVMCore.MFFreebeeHandler;
@import MVMCore.MVMCoreConstants;
@interface MFTransparentGIFView ()
@property (strong, nullable, nonatomic) NSData *imageData;
@end
@implementation MFTransparentGIFView
-(instancetype)initWithFrame:(CGRect)frame ImageName:(NSString *)imageName StartImmediately:(BOOL)startImmediately Duration:(NSTimeInterval)duration LoopCompletionBlock:(void (^)(NSUInteger))loopCompletionBlock {
if(self = [super initWithFrame:frame]) {
[self loadImage:imageName StartImmediately:startImmediately Duration:duration LoopCompletionBlock:loopCompletionBlock];
}
return self;
}
-(void)loadImage:(NSString *)imageName StartImmediately:(BOOL)startImmediately Duration:(NSTimeInterval)duration LoopCompletionBlock:(void (^)(NSUInteger))loopCompletionBlock {
self.contentMode = UIViewContentModeScaleAspectFill;
self.clipsToBounds = YES;
if(duration >= 0.0) {
self.animationDuration = duration;
}
self.loopCompletionBlock = loopCompletionBlock;
self.backgroundColor = [UIColor clearColor];
NSURL *url;
if([imageName containsString:@"http"]) {
url = [[NSURL alloc] initWithString:imageName];
} else {
url = [[MVMCoreUIUtility bundleForMVMCoreUI] URLForResource:imageName withExtension:@"gif"];
}
self.imageData = [[MFFreebeeHandler sharedHandler] freebee_dataWithContentsOfURL:url];
self.runLoopMode = NSRunLoopCommonModes;
if(startImmediately) {
[self performAnimations];
}
}
-(void)loadGifWithData:(nonnull NSData *)imageData {
self.contentMode = UIViewContentModeScaleAspectFill;
self.clipsToBounds = YES;
self.backgroundColor = [UIColor clearColor];
self.imageData = imageData;
self.runLoopMode = NSRunLoopCommonModes;
[self performAnimations];
}
-(void)setImageData:(NSData *)imageData {
_imageData = imageData;
}
-(void) performAnimations{
self.animatedImage = [[FLAnimatedImage alloc] initWithAnimatedGIFData:self.imageData optimalFrameCacheSize:250 predrawingEnabled:YES];
}
@end

View File

@ -0,0 +1,71 @@
//
// MFTransparentGifView.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 3/19/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import UIKit
@objcMembers public class MFTransparentGIFView: FLAnimatedImageView {
var imageData: Data?
/** Creates the GIF display view with the passed in frame.
frame: frame to set the view to.
ImageName: name of the .gif to load. Should not contain the extension.
StartImmediately: should the gif immeidately begin playing. If YES, it will start. If NO, call [performAnimations] to start it.
Duration: how long the animation takes to loop. Pass a negative value to use the default.
LoopCompletionBlock: a block called whenever the gif finishes a loop.
animatedImage : set as nil when use this view in reusable cell
*/
public init(withFrame frame: CGRect, imageName: String, startImmediately: Bool, duration: TimeInterval, loopCompletionBlock: ((UInt) -> Void)?) {
super.init(frame: frame)
loadImage(imageName, startImmediately: startImmediately, duration: duration, loopCompletionBlock: loopCompletionBlock)
}
public override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
public func loadImage(_ imageName: String, startImmediately: Bool, duration: TimeInterval, loopCompletionBlock: ((UInt) -> Void)?) {
contentMode = UIView.ContentMode.scaleAspectFill
clipsToBounds = true
if duration >= 0 {
animationDuration = duration
}
self.loopCompletionBlock = loopCompletionBlock
backgroundColor = .clear
var url: URL?
if imageName.contains("http") {
url = URL(string: imageName)
} else {
url = MVMCoreUIUtility.bundleForMVMCoreUI()?.url(forResource: imageName, withExtension: "gif")
}
imageData = MFFreebeeHandler.shared()?.freebee_data(withContentsOf: url)
runLoopMode = RunLoop.Mode.common.rawValue
if startImmediately {
performAnimations()
}
}
public func loadGifWithData(_ imageData: Data) {
contentMode = UIView.ContentMode.scaleAspectFill
clipsToBounds = true
backgroundColor = .clear
self.imageData = imageData
runLoopMode = RunLoop.Mode.common.rawValue
performAnimations()
}
public func performAnimations() {
animatedImage = FLAnimatedImage(animatedGIFData: imageData, optimalFrameCacheSize: 250, predrawingEnabled: true)
}
}

View File

@ -12,6 +12,8 @@
@interface MFView : UIView <MVMCoreViewProtocol, MVMCoreUIMoleculeViewProtocol>
@property (nullable, nonatomic, strong) NSDictionary *json;
// Called in the initialization functions. Can setup ui here.
- (void)setupView;

View File

@ -44,6 +44,7 @@
#pragma mark - MVMCoreUIMoleculeViewProtocol
- (void)setWithJSON:(NSDictionary *)json delegate:(NSObject *)delegate additionalData:(nullable NSDictionary *)additionalData {
self.json = json;
}
@end

View File

@ -13,10 +13,10 @@
@import MVMCore.NSDictionary_MFConvenience;
@import MVMCore.MVMCoreJSONConstants;
#import "NSLayoutConstraint+MFConvenience.h"
#import "MFTransparentGIFView.h"
#import "MVMCoreUIUtility.h"
#import "MVMCoreUIConstants.h"
#import "MVMCoreUISession.h"
#import <MVMCoreUI/MVMCoreUI-Swift.h>
@interface MFScrollingViewController ()
@ -299,7 +299,7 @@ static NSTimeInterval const HandScrollAnimationTiming = 7.f;
if (!self.gifView) {
MFTransparentGIFView *gifView = [[MFTransparentGIFView alloc] initWithFrame:CGRectZero ImageName:KeyHandScroll StartImmediately:YES Duration:-1 LoopCompletionBlock:nil];
MFTransparentGIFView *gifView = [[MFTransparentGIFView alloc] initWithFrame:CGRectZero imageName:KeyHandScroll startImmediately:YES duration:-1 loopCompletionBlock:nil];
gifView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:gifView];
gifView.contentMode = UIViewContentModeScaleAspectFit;

View File

@ -21,13 +21,13 @@
@import MVMCore.NSArray_MFConvenience;
@import MVMCore.MVMCoreGetterUtility;
@import MVMCore.MVMCoreConstants;
@import MVMCore.MVMCoreCache;
#import "NSLayoutConstraint+MFConvenience.h"
#import "UIColor+MFConvenience.h"
#import "MVMCoreUICommonViewsUtility.h"
#import "MFStyler.h"
#import "MVMCoreUISplitViewController.h"
#import "MVMCoreUITabBarPageControlViewController.h"
#import "MFLoadImageView.h"
#import "MFFonts.h"
#import <MVMCoreUI/MFSizeObject.h>
#import "MVMCoreUIUtility.h"

View File

@ -76,8 +76,6 @@ FOUNDATION_EXPORT const unsigned char MVMCoreUIVersionString[];
#import <MVMCoreUI/MFLabel.h>
#import <MVMCoreUI/LabelWithInternalButton.h>
#import <MVMCoreUI/ViewConstrainingView.h>
#import <MVMCoreUI/MFTransparentGIFView.h>
#import <MVMCoreUI/MFLoadImageView.h>
#import <MVMCoreUI/MFLoadingSpinner.h>
#import <MVMCoreUI/MFTextView.h>
#import <MVMCoreUI/MFCaretView.h>

View File

@ -24,14 +24,9 @@
// Inits with two buttons.
- (nonnull instancetype)initWithTwoButtons;
// Inits with whatever is in the passed in button map. (could be 0, 1, or 2 buttons)
// Legacy: Sets up with whatever is in the passed in button map. (could be 0, 1, or 2 buttons)
- (nonnull instancetype)initButtonSmall:(BOOL)small buttonMap:(nullable NSDictionary *)buttonMap actionDelegate:(nullable NSObject <MVMCoreActionDelegateProtocol>*)actionDelegate additionalData:(nullable NSDictionary *)additionalData buttonDelegate:(nullable id <ButtonDelegateProtocol>)buttonDelegate;
- (nonnull instancetype)initWithPrimaryButtonMap:(nullable NSDictionary *)primaryButtonMap secondaryButtonMap:(nullable NSDictionary *)secondaryButtonMap actionDelegate:(nullable NSObject <MVMCoreActionDelegateProtocol>*)actionDelegate additionalData:(nullable NSDictionary *)additionalData buttonDelegate:(nullable id <ButtonDelegateProtocol>)buttonDelegate;
// Sets up with whatever is in the passed in. (could be 0, 1, or 2 buttons)
- (void)setupWithFirstButtonJSON:(nullable NSDictionary *)firstButtonJSON secondButtonJSON:(nullable NSDictionary *)secondButtonJSON additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject <MVMCoreActionDelegateProtocol>*)actionDelegate buttonDelegate:(nullable id <ButtonDelegateProtocol>)buttonDelegate;
// Legacy: Sets up with whatever is in the passed in button map. (could be 0, 1, or 2 buttons)
- (void)setupWithButtonMap:(nullable NSDictionary *)buttonMap actionDelegate:(nullable NSObject <MVMCoreActionDelegateProtocol>*)actionDelegate additionalData:(nullable NSDictionary *)additionalData buttonDelegate:(nullable id <ButtonDelegateProtocol>)buttonDelegate;
- (void)setupWithPrimaryButtonMap:(nullable NSDictionary *)primaryButtonMap secondaryButtonMap:(nullable NSDictionary *)secondaryButtonMap actionDelegate:(nullable NSObject <MVMCoreActionDelegateProtocol>*)actionDelegate additionalData:(nullable NSDictionary *)additionalData buttonDelegate:(nullable id <ButtonDelegateProtocol>)buttonDelegate;

View File

@ -42,7 +42,13 @@
if (backgroundColorString) {
self.backgroundColor = [UIColor mfGetColorForHex:backgroundColorString];
}
[self setupWithFirstButtonJSON:[json dict:@"firstButton"] secondButtonJSON:[json dict:@"secondButton"] additionalData:nil actionDelegate:([delegate conformsToProtocol:@protocol(MVMCoreActionDelegateProtocol)] ? (NSObject <MVMCoreActionDelegateProtocol>*)delegate : nil) buttonDelegate:([delegate conformsToProtocol:@protocol(ButtonDelegateProtocol)] ? (id <ButtonDelegateProtocol>)delegate : nil)];
NSDictionary *primaryButtonMap = [json dict:@"primaryButton"];
NSDictionary *secondaryButtonMap = [json dict:@"secondaryButton"];
[self setupUIWithPrimaryButtonMap:primaryButtonMap secondaryButtonMap:secondaryButtonMap];
[self.primaryButton setAsStandardCustom];
[self.secondaryButton setAsSecondaryCustom];
[self.primaryButton setWithJSON:primaryButtonMap delegate:delegate additionalData:additionalData];
[self.secondaryButton setWithJSON:secondaryButtonMap delegate:delegate additionalData:additionalData];
}
#pragma mark - Inits
@ -89,6 +95,8 @@
return self;
}
#pragma mark - Legacy Setup
- (nonnull instancetype)initButtonSmall:(BOOL)small buttonMap:(nullable NSDictionary *)buttonMap actionDelegate:(nullable NSObject <MVMCoreActionDelegateProtocol>*)actionDelegate additionalData:(nullable NSDictionary *)additionalData buttonDelegate:(nullable id <ButtonDelegateProtocol>)buttonDelegate {
if (self = [self init]) {
[self setupWithButtonMap:buttonMap actionDelegate:actionDelegate additionalData:additionalData buttonDelegate:buttonDelegate];
@ -105,24 +113,29 @@
return self;
}
#pragma mark - Setup
- (void)setupWithButtonMap:(nullable NSDictionary *)buttonMap actionDelegate:(nullable NSObject <MVMCoreActionDelegateProtocol>*)actionDelegate additionalData:(nullable NSDictionary *)additionalData buttonDelegate:(nullable id <ButtonDelegateProtocol>)buttonDelegate {
NSDictionary *secondaryButtonMap = [buttonMap dict:KeySecondaryButton];
NSDictionary *primaryButtonMap = [buttonMap dict:KeyPrimaryButton];
[self setupWithPrimaryButtonMap:primaryButtonMap secondaryButtonMap:secondaryButtonMap actionDelegate:actionDelegate additionalData:additionalData buttonDelegate:buttonDelegate];
}
- (void)setupWithFirstButtonJSON:(nullable NSDictionary *)firstButtonJSON secondButtonJSON:(nullable NSDictionary *)secondButtonJSON additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject <MVMCoreActionDelegateProtocol>*)actionDelegate buttonDelegate:(nullable id <ButtonDelegateProtocol>)buttonDelegate {
[self setupWithPrimaryButtonMap:secondButtonJSON secondaryButtonMap:firstButtonJSON additionalData:additionalData actionDelegate:actionDelegate buttonDelegate:buttonDelegate legacyJSON:NO];
}
- (void)setupWithPrimaryButtonMap:(nullable NSDictionary *)primaryButtonMap secondaryButtonMap:(nullable NSDictionary *)secondaryButtonMap actionDelegate:(nullable NSObject <MVMCoreActionDelegateProtocol>*)actionDelegate additionalData:(nullable NSDictionary *)additionalData buttonDelegate:(nullable id <ButtonDelegateProtocol>)buttonDelegate {
[self setupWithPrimaryButtonMap:primaryButtonMap secondaryButtonMap:secondaryButtonMap additionalData:additionalData actionDelegate:actionDelegate buttonDelegate:buttonDelegate legacyJSON:YES];
[self setupUIWithPrimaryButtonMap:primaryButtonMap secondaryButtonMap:secondaryButtonMap];
if (self.primaryButton && self.secondaryButton) {
[self.primaryButton setWithActionMap:primaryButtonMap actionDelegate:actionDelegate additionalData:additionalData buttonDelegate:buttonDelegate];
[self.secondaryButton setWithActionMap:secondaryButtonMap actionDelegate:actionDelegate additionalData:additionalData buttonDelegate:buttonDelegate];
} else if (self.primaryButton) {
[self.primaryButton setWithActionMap:primaryButtonMap actionDelegate:actionDelegate additionalData:additionalData buttonDelegate:buttonDelegate];
self.primaryButton.bordered = NO;
} else {
[self.primaryButton setWithActionMap:secondaryButtonMap actionDelegate:actionDelegate additionalData:additionalData buttonDelegate:buttonDelegate];
self.primaryButton.bordered = YES;
}
}
- (void)setupWithPrimaryButtonMap:(nullable NSDictionary *)primaryButtonMap secondaryButtonMap:(nullable NSDictionary *)secondaryButtonMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject <MVMCoreActionDelegateProtocol>*)actionDelegate buttonDelegate:(nullable id <ButtonDelegateProtocol>)buttonDelegate legacyJSON:(BOOL)legacyJSON {
#pragma mark - Setup
- (void)setupUIWithPrimaryButtonMap:(nullable NSDictionary *)primaryButtonMap secondaryButtonMap:(nullable NSDictionary *)secondaryButtonMap {
if (primaryButtonMap && secondaryButtonMap) {
self.height.active = NO;
@ -132,13 +145,6 @@
self.twoButtonView = nil;
[self setupWithTwoButtons];
}
if (legacyJSON) {
[self.primaryButton setWithActionMap:primaryButtonMap actionDelegate:actionDelegate additionalData:additionalData buttonDelegate:buttonDelegate];
[self.secondaryButton setWithActionMap:secondaryButtonMap actionDelegate:actionDelegate additionalData:additionalData buttonDelegate:buttonDelegate];
} else {
[self.primaryButton setWithJSON:primaryButtonMap delegate:actionDelegate additionalData:additionalData];
[self.secondaryButton setWithJSON:secondaryButtonMap delegate:actionDelegate additionalData:additionalData];
}
} else if (primaryButtonMap || secondaryButtonMap) {
self.height.active = NO;
@ -149,23 +155,6 @@
self.secondaryButton = nil;
[self setupWithSingleButton];
}
[self alignCenter];
if (legacyJSON) {
if (primaryButtonMap) {
// Only primary button
[self.primaryButton setWithActionMap:primaryButtonMap actionDelegate:actionDelegate additionalData:additionalData buttonDelegate:buttonDelegate];
self.primaryButton.bordered = NO;
} else {
// Only secondary button
[self.primaryButton setWithActionMap:secondaryButtonMap actionDelegate:actionDelegate additionalData:additionalData buttonDelegate:buttonDelegate];
self.primaryButton.bordered = YES;
}
} else {
[self.primaryButton setWithJSON:primaryButtonMap delegate:actionDelegate additionalData:additionalData];
}
} else {
[self removeSubviews];
if (!self.height) {

View File

@ -15,7 +15,7 @@
#import <MVMCore/MVMCoreTopAlertObject.h>
#import "UIColor+MFConvenience.h"
#import <MVMCore/MVMCoreAlertHandler.h>
#import "MFLoadImageView.h"
#import <MVMCoreUI/MVMCoreUI-Swift.h>
#import <MVMCore/MVMCoreJSONConstants.h>
#import "MVMCoreUICommonViewsUtility.h"
#import "MVMCoreUITopAlertView.h"
@ -155,7 +155,7 @@
}
if (imageURL) {
MFLoadImageView *imageView = [[MFLoadImageView alloc] initWithCenteredImage];
MFLoadImageView *imageView = [[MFLoadImageView alloc] init];
imageView.translatesAutoresizingMaskIntoConstraints = NO;
[imageView setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal];
[self addSubview:imageView];