From f8b31f9ba781c2dc1bcf63b941506345f2e32b43 Mon Sep 17 00:00:00 2001 From: Joseph Woo Date: Wed, 20 Jun 2018 18:14:01 -0700 Subject: [PATCH] Jwoo/explicit image size ios (#1374) * explicit image changes * Added 'Explicit' enum value * uwp changes * uwp changes * added explicit image sizing option for ios * removed division --- .../project.pbxproj | 9 +-- .../AdaptiveCards/ACRImageRenderer.mm | 73 +++++++++++++++---- 2 files changed, 61 insertions(+), 21 deletions(-) diff --git a/source/ios/AdaptiveCards/ADCIOSVisualizer/ADCIOSVisualizer.xcodeproj/project.pbxproj b/source/ios/AdaptiveCards/ADCIOSVisualizer/ADCIOSVisualizer.xcodeproj/project.pbxproj index db725d97b7..43a0b0fca7 100644 --- a/source/ios/AdaptiveCards/ADCIOSVisualizer/ADCIOSVisualizer.xcodeproj/project.pbxproj +++ b/source/ios/AdaptiveCards/ADCIOSVisualizer/ADCIOSVisualizer.xcodeproj/project.pbxproj @@ -19,11 +19,11 @@ 30860BCB20C9B5C9009F9D99 /* ColumnSet.Input.Text.VerticalStretch.json in Resources */ = {isa = PBXBuildFile; fileRef = 30860BBF20C9B5C9009F9D99 /* ColumnSet.Input.Text.VerticalStretch.json */; }; 30860BCC20C9B5C9009F9D99 /* ColumnSet_Container.VerticalStretch.json in Resources */ = {isa = PBXBuildFile; fileRef = 30860BC020C9B5C9009F9D99 /* ColumnSet_Container.VerticalStretch.json */; }; 30860BCD20C9B5C9009F9D99 /* ColumnSet.Input.Time.VerticalStretch.json in Resources */ = {isa = PBXBuildFile; fileRef = 30860BC120C9B5C9009F9D99 /* ColumnSet.Input.Time.VerticalStretch.json */; }; - 30A3885D20D315AA00AAEE59 /* IconsInSomeActions.json in Resources */ = {isa = PBXBuildFile; fileRef = 30A3885B20D315AA00AAEE59 /* IconsInSomeActions.json */; }; 30A3885E20D315AA00AAEE59 /* NotificationCard.json in Resources */ = {isa = PBXBuildFile; fileRef = 30A3885C20D315AA00AAEE59 /* NotificationCard.json */; }; 6B268FE320CEF19400D99C1B /* (null) in Resources */ = {isa = PBXBuildFile; }; 6B268FE520CEF89100D99C1B /* (null) in Resources */ = {isa = PBXBuildFile; }; 6B7B1A9B20C21CA900260731 /* SportingEvent.json in Resources */ = {isa = PBXBuildFile; fileRef = 6B7B1A9920C21CA800260731 /* SportingEvent.json */; }; + 6B9AB30620D9857B005C8E15 /* Image.Explicit.Size.json in Resources */ = {isa = PBXBuildFile; fileRef = 6B9AB30520D9857A005C8E15 /* Image.Explicit.Size.json */; }; 6BF339D620A665E600DA5973 /* CustomTextBlockRenderer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6BF339D420A665E600DA5973 /* CustomTextBlockRenderer.mm */; }; 6BF339E320A66A3F00DA5973 /* AdaptiveCards.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6BF339E220A66A3F00DA5973 /* AdaptiveCards.framework */; }; 6BF339E420A66A4D00DA5973 /* AdaptiveCards.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 6BF339E220A66A3F00DA5973 /* AdaptiveCards.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -137,9 +137,9 @@ 30860BBF20C9B5C9009F9D99 /* ColumnSet.Input.Text.VerticalStretch.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = ColumnSet.Input.Text.VerticalStretch.json; path = ../../../../samples/Tests/ColumnSet.Input.Text.VerticalStretch.json; sourceTree = ""; }; 30860BC020C9B5C9009F9D99 /* ColumnSet_Container.VerticalStretch.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = ColumnSet_Container.VerticalStretch.json; path = ../../../../samples/Tests/ColumnSet_Container.VerticalStretch.json; sourceTree = ""; }; 30860BC120C9B5C9009F9D99 /* ColumnSet.Input.Time.VerticalStretch.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = ColumnSet.Input.Time.VerticalStretch.json; path = ../../../../samples/Tests/ColumnSet.Input.Time.VerticalStretch.json; sourceTree = ""; }; - 30A3885B20D315AA00AAEE59 /* IconsInSomeActions.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = IconsInSomeActions.json; path = ../../../../samples/Tests/IconsInSomeActions.json; sourceTree = ""; }; 30A3885C20D315AA00AAEE59 /* NotificationCard.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = NotificationCard.json; path = ../../../../samples/Tests/NotificationCard.json; sourceTree = ""; }; 6B7B1A9920C21CA800260731 /* SportingEvent.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = SportingEvent.json; path = ../../../../samples/v1.0/Scenarios/SportingEvent.json; sourceTree = ""; }; + 6B9AB30520D9857A005C8E15 /* Image.Explicit.Size.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = Image.Explicit.Size.json; path = ../../../../samples/Tests/Image.Explicit.Size.json; sourceTree = ""; }; 6BF339D420A665E600DA5973 /* CustomTextBlockRenderer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CustomTextBlockRenderer.mm; sourceTree = ""; }; 6BF339D520A665E600DA5973 /* CustomTextBlockRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CustomTextBlockRenderer.h; sourceTree = ""; }; 6BF339E220A66A3F00DA5973 /* AdaptiveCards.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = AdaptiveCards.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -346,9 +346,8 @@ F4D33E341F045B6E00941E44 /* Jsons */ = { isa = PBXGroup; children = ( - 30A3885B20D315AA00AAEE59 /* IconsInSomeActions.json */, + 6B9AB30520D9857A005C8E15 /* Image.Explicit.Size.json */, 30A3885C20D315AA00AAEE59 /* NotificationCard.json */, - 30184A9620D1B298001C5A68 /* InputsFormWithHeightStretch.json */, 30860BC020C9B5C9009F9D99 /* ColumnSet_Container.VerticalStretch.json */, 30860BBE20C9B5C8009F9D99 /* ColumnSet.FactSet.VerticalStretch.json */, 30860BBB20C9B5C8009F9D99 /* ColumnSet.ImageSet.VerticalStretch.json */, @@ -528,7 +527,6 @@ F4933CE41F79852C00F6EBFD /* TextBlock.Color.json in Resources */, F4933CD41F79852C00F6EBFD /* Image.HorizontalAlignment.json in Resources */, F4933CC51F79852C00F6EBFD /* Action.Submit.json in Resources */, - 30A3885D20D315AA00AAEE59 /* IconsInSomeActions.json in Resources */, 6B268FE520CEF89100D99C1B /* (null) in Resources */, F4933CED1F79852C00F6EBFD /* TextBlock.Weight.json in Resources */, F4933D061F79853B00F6EBFD /* StockUpdate.json in Resources */, @@ -542,6 +540,7 @@ 30A3885E20D315AA00AAEE59 /* NotificationCard.json in Resources */, F4933CE81F79852C00F6EBFD /* TextBlock.Markdown.json in Resources */, F4933D021F79853B00F6EBFD /* InputForm.json in Resources */, + 6B9AB30620D9857B005C8E15 /* Image.Explicit.Size.json in Resources */, 30860BCA20C9B5C9009F9D99 /* ColumnSet.FactSet.VerticalStretch.json in Resources */, F4933D031F79853B00F6EBFD /* Inputs.json in Resources */, F4933CD81F79852C00F6EBFD /* Image.Style.json in Resources */, diff --git a/source/ios/AdaptiveCards/AdaptiveCards/AdaptiveCards/ACRImageRenderer.mm b/source/ios/AdaptiveCards/AdaptiveCards/AdaptiveCards/ACRImageRenderer.mm index f5cd1d45e2..5c434d1da1 100644 --- a/source/ios/AdaptiveCards/AdaptiveCards/AdaptiveCards/ACRImageRenderer.mm +++ b/source/ios/AdaptiveCards/AdaptiveCards/AdaptiveCards/ACRImageRenderer.mm @@ -39,9 +39,54 @@ - (UIView *)render:(UIView *)viewGroup std::shared_ptr elem = [acoElem element]; std::shared_ptr imgElem = std::dynamic_pointer_cast(elem); ACRUIImageView *view; + NSInteger pixelWidth = imgElem->GetPixelWidth(), pixelHeight = imgElem->GetPixelHeight(); + BOOL hasExplicitMeasurements = (pixelWidth || pixelHeight); + BOOL isAspectRatioNeeded = !(pixelWidth && pixelHeight); CGSize cgsize = [acoConfig getImageSize:imgElem->GetImageSize()]; + + NSMutableDictionary *imageViewMap = [rootView getImageMap]; + // Syncronize access to imageViewMap + NSNumber *number = [NSNumber numberWithUnsignedLongLong:(unsigned long long)imgElem.get()]; + NSString *key = [number stringValue]; + UIImage *img = imageViewMap[key]; + + CGFloat heightToWidthRatio = 0.0f, widthToHeightRatio = 0.0f; + if(img){ + if(img.size.width > 0) { + heightToWidthRatio = img.size.height / img.size.width; + } + + if(img.size.height > 0) { + widthToHeightRatio =img.size.width / img.size.height; + } + } + + if(hasExplicitMeasurements) { + if(pixelWidth){ + cgsize.width = pixelWidth; + if(isAspectRatioNeeded) { + cgsize.height = pixelWidth * heightToWidthRatio; + } + } + if(pixelHeight){ + cgsize.height = pixelHeight; + if(isAspectRatioNeeded) { + cgsize.width = pixelHeight * widthToHeightRatio; + } + } + } view = [[ACRUIImageView alloc] initWithFrame:CGRectMake(0, 0, cgsize.width, cgsize.height)]; - if(imgElem->GetImageSize() != ImageSize::Auto && imgElem->GetImageSize() != ImageSize::Stretch && imgElem->GetImageSize() != ImageSize::None){ + view.image = img; + + ImageSize size = ImageSize::None; + if (!hasExplicitMeasurements){ + size = imgElem->GetImageSize(); + if (size == ImageSize::None) { + size = [acoConfig getHostConfig]->image.imageSize; + } + } + + if(size != ImageSize::Auto && size != ImageSize::Stretch){ [view addConstraints:@[[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual @@ -57,15 +102,8 @@ - (UIView *)render:(UIView *)viewGroup multiplier:1.0 constant:cgsize.height]]]; } - NSMutableDictionary *imageViewMap = [rootView getImageMap]; - UIImage *img = nil; - // Syncronize access to imageViewMap - NSNumber *number = [NSNumber numberWithUnsignedLongLong:(unsigned long long)imgElem.get()]; - NSString *key = [number stringValue]; - img = imageViewMap[key]; - view.image = img; - if(img && (img.size.width > 0) && (imgElem->GetImageSize() == ImageSize::Auto || imgElem->GetImageSize() == ImageSize::Stretch || imgElem->GetImageSize() == ImageSize::None)){ - CGFloat heightToWidthRatio = img.size.height / img.size.width; + + if(heightToWidthRatio && widthToHeightRatio && (size == ImageSize::Auto || size == ImageSize::Stretch)){ [view addConstraints:@[[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual @@ -73,7 +111,6 @@ - (UIView *)render:(UIView *)viewGroup attribute:NSLayoutAttributeWidth multiplier:heightToWidthRatio constant:0]]]; - CGFloat widthToHeightRatio = img.size.width/ img.size.height; [view addConstraints:@[[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual @@ -83,7 +120,11 @@ - (UIView *)render:(UIView *)viewGroup constant:0]]]; } - view.contentMode = UIViewContentModeScaleAspectFit; + if(!isAspectRatioNeeded){ + view.contentMode = UIViewContentModeScaleToFill; + } else { + view.contentMode = UIViewContentModeScaleAspectFit; + } view.clipsToBounds = NO; if(imgElem->GetImageStyle() == ImageStyle::Person) { CALayer *imgLayer = view.layer; @@ -100,7 +141,7 @@ - (UIView *)render:(UIView *)viewGroup withSuperview:wrappingview toView:view]]; // ImageSize::Auto should maintain its intrinsic size - if(imgElem->GetImageSize() == ImageSize::Auto || imgElem->GetImageSize() == ImageSize::Stretch || imgElem->GetImageSize() == ImageSize::None){ + if(size == ImageSize::Auto || size == ImageSize::Stretch) { NSArray *visualFormats = [NSArray arrayWithObjects:@"H:[view(<=wrappingview)]", @"V:|-[view(<=wrappingview)]-|", nil]; NSDictionary *viewMap = NSDictionaryOfVariableBindings(view, wrappingview); for(NSString *constraint in visualFormats){ @@ -111,13 +152,13 @@ - (UIView *)render:(UIView *)viewGroup [wrappingview setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical]; } - if(imgElem->GetImageSize() == ImageSize::Auto || imgElem->GetImageSize() == ImageSize::None){ + if(size == ImageSize::Auto) { [view setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal]; [view setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical]; [wrappingview setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal]; [wrappingview setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical]; - - if(imgElem->GetHeight() == HeightType::Stretch){ + + if(imgElem->GetHeight() == HeightType::Stretch) { UIView *blankTrailingSpace = [[UIView alloc] init]; [blankTrailingSpace setContentHuggingPriority:(UILayoutPriorityDefaultLow) forAxis:UILayoutConstraintAxisVertical]; [viewGroup addArrangedSubview:blankTrailingSpace];