Merge branch 'develop' of https://gitlab.verizon.com/BPHV_MIPS/mvm_core_ui into feature/list_threecolumn_speedtest

This commit is contained in:
Pfeil, Scott Robert 2020-08-10 09:41:34 -04:00
commit 1d4710a25a
10 changed files with 89 additions and 11 deletions

View File

@ -20,6 +20,7 @@ import Foundation
public var height: CGFloat? public var height: CGFloat?
public var contentMode: UIView.ContentMode? public var contentMode: UIView.ContentMode?
public var localBundle: Bundle? public var localBundle: Bundle?
public var cornerRadius: CGFloat?
public init(image: String, imageFormat: String? = nil, width: CGFloat? = nil, height: CGFloat? = nil) { public init(image: String, imageFormat: String? = nil, width: CGFloat? = nil, height: CGFloat? = nil) {
self.image = image self.image = image
@ -38,5 +39,6 @@ import Foundation
case width case width
case height case height
case contentMode case contentMode
case cornerRadius
} }
} }

View File

@ -223,6 +223,8 @@ import UIKit
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
self.delegateObject = delegateObject self.delegateObject = delegateObject
super.set(with: model, delegateObject, additionalData)
guard let imageModel = model as? ImageViewModel else { return } guard let imageModel = model as? ImageViewModel else { return }
if let accessibilityString = imageModel.accessibilityText { if let accessibilityString = imageModel.accessibilityText {
imageView.accessibilityLabel = accessibilityString imageView.accessibilityLabel = accessibilityString
@ -247,6 +249,11 @@ import UIKit
if let contentMode = imageModel.contentMode { if let contentMode = imageModel.contentMode {
imageView.contentMode = contentMode imageView.contentMode = contentMode
} }
if let cornerRadius = imageModel.cornerRadius {
clipsToBounds = true
layer.cornerRadius = cornerRadius
}
} }
// MARK: - load functions // MARK: - load functions

View File

@ -29,4 +29,7 @@
// Handles making various parts accessible. // Handles making various parts accessible.
- (void)handleAccessibility; - (void)handleAccessibility;
/// Adds the top alert accessibility prefix to the view.
+ (void)amendAccesibilityLabelForView:(nonnull UIView *)view;
@end @end

View File

@ -71,18 +71,27 @@
} }
- (nonnull Button *)addCloseButtonWithAnimationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate { - (nonnull Button *)addCloseButtonWithAnimationDelegate:(nullable id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate {
Button *closeButton = [MVMCoreUICommonViewsUtility addCloseButtonTo:self action:^(Button * _Nonnull button) {
return [MVMCoreUICommonViewsUtility addCloseButtonTo:self action:^(Button * _Nonnull button) {
if (animationDelegate) { if (animationDelegate) {
[animationDelegate topAlertCloseButtonPressed]; [animationDelegate topAlertCloseButtonPressed];
} else { } else {
[[MVMCoreUISession sharedGlobal].topAlertView hideAlertView:nil]; [[MVMCoreUISession sharedGlobal].topAlertView hideAlertView:YES completionHandler:nil];
} }
} centeredVertically:YES]; } centeredVertically:YES];
[MVMCoreUITopAlertBaseView amendAccesibilityLabelForView:closeButton];
return closeButton;
} }
- (void)updateView:(CGFloat)size {} - (void)updateView:(CGFloat)size {}
- (void)handleAccessibility {} - (void)handleAccessibility {}
+ (void)amendAccesibilityLabelForView:(nonnull UIView *)view {
NSString *amendment = [MVMCoreUIUtility hardcodedStringWithKey:@"top_alert_notification"];
NSString *accessibilityLabel = view.accessibilityLabel;
if (accessibilityLabel && ![accessibilityLabel hasPrefix:amendment]) {
view.accessibilityLabel = [NSString stringWithFormat:@"%@ - %@", amendment, accessibilityLabel];
}
}
@end @end

View File

@ -52,7 +52,7 @@
- (void)handleAccessibility { - (void)handleAccessibility {
if (self.shortView.label.text.length > 0 && (!self.expanded || !self.onlyShowTopMessageWhenCollapsed)) { if (self.shortView.label.text.length > 0 && !self.expanded) {
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, self.shortView.label); UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, self.shortView.label);
} else if (self.buttonView.label.text.length > 0) { } else if (self.buttonView.label.text.length > 0) {
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, self.buttonView.label); UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, self.buttonView.label);
@ -166,7 +166,7 @@
topAlertWithButton.backgroundColor = [UIColor clearColor]; topAlertWithButton.backgroundColor = [UIColor clearColor];
[self insertSubview:topAlertWithButton belowSubview:self.shortView]; [self insertSubview:topAlertWithButton belowSubview:self.shortView];
self.buttonView = topAlertWithButton; self.buttonView = topAlertWithButton;
self.topConstraint = [NSLayoutConstraint constraintWithItem:topAlertWithButton attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.shortView attribute:NSLayoutAttributeBottom multiplier:1 constant:0]; self.topConstraint = [NSLayoutConstraint constraintWithItem:topAlertWithButton attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.shortView attribute:NSLayoutAttributeBottom multiplier:1 constant:0];
[NSLayoutConstraint constraintPinSubview:topAlertWithButton pinTop:NO topConstant:0 pinBottom:YES bottomConstant:0 pinLeft:YES leftConstant:0 pinRight:YES rightConstant:0]; [NSLayoutConstraint constraintPinSubview:topAlertWithButton pinTop:NO topConstant:0 pinBottom:YES bottomConstant:0 pinLeft:YES leftConstant:0 pinRight:YES rightConstant:0];
} }
@ -194,6 +194,8 @@
- (void)setTopMessage:(nullable NSString *)topMessage { - (void)setTopMessage:(nullable NSString *)topMessage {
[MVMCoreDispatchUtility performBlockOnMainThread:^{ [MVMCoreDispatchUtility performBlockOnMainThread:^{
self.shortView.label.text = topMessage; self.shortView.label.text = topMessage;
self.shortView.label.accessibilityLabel = topMessage;
[MVMCoreUITopAlertBaseView amendAccesibilityLabelForView:self.shortView.label];
if (topMessage && (!self.onlyShowTopMessageWhenCollapsed || !self.expanded)) { if (topMessage && (!self.onlyShowTopMessageWhenCollapsed || !self.expanded)) {
self.shortViewHeight.active = NO; self.shortViewHeight.active = NO;
@ -237,6 +239,7 @@
- (void)setShortViewPressToExpand { - (void)setShortViewPressToExpand {
__weak typeof(self) weakSelf = self; __weak typeof(self) weakSelf = self;
self.shortView.label.accessibilityTraits = UIAccessibilityTraitButton;
[self.shortView.button addActionBlockWithEvent:UIControlEventTouchUpInside :^(Button * _Nonnull button) { [self.shortView.button addActionBlockWithEvent:UIControlEventTouchUpInside :^(Button * _Nonnull button) {
if (weakSelf) { if (weakSelf) {
[weakSelf expand:YES]; [weakSelf expand:YES];
@ -246,6 +249,7 @@
- (void)setShortViewPressToCollapse { - (void)setShortViewPressToCollapse {
__weak typeof(self) weakSelf = self; __weak typeof(self) weakSelf = self;
self.shortView.label.accessibilityTraits = UIAccessibilityTraitButton;
[self.shortView.button addActionBlockWithEvent:UIControlEventTouchUpInside :^(Button * _Nonnull button) { [self.shortView.button addActionBlockWithEvent:UIControlEventTouchUpInside :^(Button * _Nonnull button) {
if (weakSelf) { if (weakSelf) {
[weakSelf collapse]; [weakSelf collapse];
@ -304,7 +308,6 @@
//accessibility - added to make only top alert label and close button accessible. Posted notification when top alert is displayed //accessibility - added to make only top alert label and close button accessible. Posted notification when top alert is displayed
weakSelf.accessibilityElements = @[weakSelf.buttonView]; weakSelf.accessibilityElements = @[weakSelf.buttonView];
weakSelf.shortView.isAccessibilityElement = NO; weakSelf.shortView.isAccessibilityElement = NO;
weakSelf.buttonView.label.accessibilityLabel = [NSString stringWithFormat:@"%@ - %@", [MVMCoreUIUtility hardcodedStringWithKey:@"top_alert_notification"],weakSelf.buttonView.label.accessibilityLabel];
void(^completion)(void) = ^(void) { void(^completion)(void) = ^(void) {
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, weakSelf.buttonView.label); UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, weakSelf.buttonView.label);
@ -347,14 +350,18 @@
dispatch_time_t dispatchTime = dispatch_time(DISPATCH_TIME_NOW, dismissTime * NSEC_PER_SEC); dispatch_time_t dispatchTime = dispatch_time(DISPATCH_TIME_NOW, dismissTime * NSEC_PER_SEC);
dispatch_after(dispatchTime, dispatch_get_main_queue(), ^(void){ dispatch_after(dispatchTime, dispatch_get_main_queue(), ^(void){
if (weakSelf && weakSelf.expanded && weakSelf.collapseAutomaticallyAfterExpanded) { if (weakSelf && weakSelf.expanded && weakSelf.collapseAutomaticallyAfterExpanded) {
[weakSelf collapse]; // If accessibility focused, delay collapse.
if ([MVMCoreUIUtility viewContainsAccessiblityFocus:self]) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(accessibilityFocusChanged:) name:UIAccessibilityElementFocusedNotification object:nil];
} else {
[weakSelf collapse];
}
} }
}); });
} }
} }
- (void)collapse { - (void)collapse {
if (self.expanded) { if (self.expanded) {
__weak typeof(self) weakSelf = self; __weak typeof(self) weakSelf = self;
MVMCoreBlockOperation *operation = [MVMCoreBlockOperation blockOperationWithBlock:^(MVMCoreBlockOperation * _Nonnull operation) { MVMCoreBlockOperation *operation = [MVMCoreBlockOperation blockOperationWithBlock:^(MVMCoreBlockOperation * _Nonnull operation) {
@ -390,4 +397,11 @@
} }
} }
- (void)accessibilityFocusChanged:(NSNotification *)notification {
if (![MVMCoreUIUtility viewContainsAccessiblityFocus:self]) {
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityElementFocusedNotification object:nil];
[self collapse];
}
}
@end @end

View File

@ -45,6 +45,8 @@
- (void)updateView:(CGFloat)size { - (void)updateView:(CGFloat)size {
[super updateView:size]; [super updateView:size];
self.label.attributedText = [MVMCoreUITopAlertBaseView getStringForMessage:self.message subMessage:self.subMessage color:self.contentColor]; self.label.attributedText = [MVMCoreUITopAlertBaseView getStringForMessage:self.message subMessage:self.subMessage color:self.contentColor];
self.label.accessibilityLabel = self.label.text;
[MVMCoreUITopAlertBaseView amendAccesibilityLabelForView:self.label];
[self.button updateView:size]; [self.button updateView:size];
} }
@ -226,6 +228,8 @@
// Sets the string // Sets the string
self.label.attributedText = [MVMCoreUITopAlertBaseView getStringForMessage:message subMessage:subMessage color:color]; self.label.attributedText = [MVMCoreUITopAlertBaseView getStringForMessage:message subMessage:subMessage color:color];
self.label.accessibilityLabel = self.label.text;
[MVMCoreUITopAlertBaseView amendAccesibilityLabelForView:self.label];
// Sets the button // Sets the button
[self setupButtonWithActionMap:actionMap additionalData:additionalData]; [self setupButtonWithActionMap:actionMap additionalData:additionalData];
@ -245,6 +249,8 @@
// Sets the string // Sets the string
self.label.attributedText = [MVMCoreUITopAlertBaseView getStringForMessage:message subMessage:subMessage color:color]; self.label.attributedText = [MVMCoreUITopAlertBaseView getStringForMessage:message subMessage:subMessage color:color];
self.label.accessibilityLabel = self.label.text;
[MVMCoreUITopAlertBaseView amendAccesibilityLabelForView:self.label];
// Sets the color // Sets the color
if (color) { if (color) {
@ -265,6 +271,9 @@
[self setupWithButton:showButton]; [self setupWithButton:showButton];
if (showButton) { if (showButton) {
[self.button setTitle:[actionMap stringForKey:KeyTitle] forState:UIControlStateNormal]; [self.button setTitle:[actionMap stringForKey:KeyTitle] forState:UIControlStateNormal];
self.button.accessibilityLabel = [self.button titleForState:UIControlStateNormal];
[MVMCoreUITopAlertBaseView amendAccesibilityLabelForView:self.button];
[MVMCoreUITopAlertBaseView addActionToButton:self.button actionMap:actionMap additionalData:additionalData]; [MVMCoreUITopAlertBaseView addActionToButton:self.button actionMap:actionMap additionalData:additionalData];
} }
}]; }];
@ -276,6 +285,8 @@
BOOL showButton = buttonTitle.length > 0; BOOL showButton = buttonTitle.length > 0;
[self setupWithButton:showButton]; [self setupWithButton:showButton];
[self.button setTitle:buttonTitle forState:UIControlStateNormal]; [self.button setTitle:buttonTitle forState:UIControlStateNormal];
self.button.accessibilityLabel = [self.button titleForState:UIControlStateNormal];
[MVMCoreUITopAlertBaseView amendAccesibilityLabelForView:self.button];
if (showButton && userActionHandler) { if (showButton && userActionHandler) {
[self.button addActionBlockWithEvent:UIControlEventTouchUpInside :userActionHandler]; [self.button addActionBlockWithEvent:UIControlEventTouchUpInside :userActionHandler];
} }

View File

@ -44,6 +44,9 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
@property (weak, nonatomic) MVMCoreUITopAlertExpandableView *topAlertClearspotView; @property (weak, nonatomic) MVMCoreUITopAlertExpandableView *topAlertClearspotView;
@property (strong, nonatomic) NSString *time; @property (strong, nonatomic) NSString *time;
/// Used if we delayed the collapse due to accessibility.
@property (copy, nonatomic) void (^ hideCompletionHandler)(BOOL finished);
@end @end
@implementation MVMCoreUITopAlertView @implementation MVMCoreUITopAlertView
@ -210,7 +213,13 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
[[MVMCoreNavigationHandler sharedNavigationHandler] addNavigationOperation:operation]; [[MVMCoreNavigationHandler sharedNavigationHandler] addNavigationOperation:operation];
} }
- (void)hideAlertView:(void (^ __nullable)(BOOL finished))completionHandler { - (void)hideAlertView:(BOOL)forceful completionHandler:(void (^ __nullable)(BOOL finished))completionHandler {
// If accessible and focused, do not collapse until unfocused.
if (!forceful && [MVMCoreUIUtility viewContainsAccessiblityFocus:self]) {
self.hideCompletionHandler = completionHandler;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(accessibilityFocusChanged:) name:UIAccessibilityElementFocusedNotification object:nil];
return;
}
__weak typeof(self) weakSelf = self; __weak typeof(self) weakSelf = self;
MVMCoreBlockOperation *operation = [MVMCoreBlockOperation blockOperationWithBlock:^(MVMCoreBlockOperation * _Nonnull operation) { MVMCoreBlockOperation *operation = [MVMCoreBlockOperation blockOperationWithBlock:^(MVMCoreBlockOperation * _Nonnull operation) {
@ -257,7 +266,7 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
[((MVMCoreUITopAlertExpandableView *)self.currentAlert) collapse]; [((MVMCoreUITopAlertExpandableView *)self.currentAlert) collapse];
} else { } else {
// Top alert is not collapsable, remove it instead. // Top alert is not collapsable, remove it instead.
[self hideAlertView:NULL]; [self hideAlertView:NO completionHandler:NULL];
} }
} }
} }
@ -294,4 +303,13 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
} }
} }
/// If the voice over user leaves top alert focus, hide.
- (void)accessibilityFocusChanged:(NSNotification *)notification {
if (![MVMCoreUIUtility viewContainsAccessiblityFocus:self]) {
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityElementFocusedNotification object:nil];
[self hideAlertView:YES completionHandler:self.hideCompletionHandler];
self.hideCompletionHandler = nil;
}
}
@end @end

View File

@ -272,7 +272,7 @@ static const CGFloat VertialShadowOffset = 6;
view.layer.shadowColor = [UIColor blackColor].CGColor; view.layer.shadowColor = [UIColor blackColor].CGColor;
view.layer.shadowOffset = CGSizeMake(0.0f, VertialShadowOffset); view.layer.shadowOffset = CGSizeMake(0.0f, VertialShadowOffset);
view.layer.shadowOpacity = 0.7f; view.layer.shadowOpacity = 0.25f;
view.layer.shadowPath = shadowPath.CGPath; view.layer.shadowPath = shadowPath.CGPath;
} }

View File

@ -34,6 +34,9 @@ NS_ASSUME_NONNULL_BEGIN
/// Gets the current visible view controller. Checks presented view controllers first, and then it checks on the NavigationController in the session object. /// Gets the current visible view controller. Checks presented view controllers first, and then it checks on the NavigationController in the session object.
+ (UIViewController *)getCurrentVisibleController; + (UIViewController *)getCurrentVisibleController;
/// Checks if the view or any descendents of the view is currently focused for voice over.
+ (BOOL)viewContainsAccessiblityFocus:(nonnull UIView *)view;
#pragma mark - Setters #pragma mark - Setters
+ (void)setMarginsForView:(nullable UIView *)view leading:(CGFloat)leading top:(CGFloat)top trailing:(CGFloat)trailing bottom:(CGFloat)bottom; + (void)setMarginsForView:(nullable UIView *)view leading:(CGFloat)leading top:(CGFloat)top trailing:(CGFloat)trailing bottom:(CGFloat)bottom;

View File

@ -81,6 +81,17 @@
return viewController; return viewController;
} }
+ (BOOL)viewContainsAccessiblityFocus:(nonnull UIView *)view {
if (!UIAccessibilityIsVoiceOverRunning()) {
return NO;
}
id focusedElement = UIAccessibilityFocusedElement(UIAccessibilityNotificationVoiceOverIdentifier);
if (![focusedElement isKindOfClass:[UIView class]]) {
return NO;
}
return [(UIView *)focusedElement isDescendantOfView:view];
}
#pragma mark - Setters #pragma mark - Setters
+ (void)setMarginsForView:(nullable UIView *)view leading:(CGFloat)leading top:(CGFloat)top trailing:(CGFloat)trailing bottom:(CGFloat)bottom { + (void)setMarginsForView:(nullable UIView *)view leading:(CGFloat)leading top:(CGFloat)top trailing:(CGFloat)trailing bottom:(CGFloat)bottom {