Allow FlutterViewController to specify whether its FlutterView is opaque (flutter/engine#6570)

* Allow FlutterViewController to specify whether its FlutterView is opaque
This commit is contained in:
Dan Field
2018-10-22 19:53:04 -07:00
committed by GitHub
parent e52ba8b257
commit bf8709d7dc
4 changed files with 80 additions and 29 deletions

View File

@@ -93,6 +93,15 @@ FLUTTER_EXPORT
*/
@property(strong, nonatomic) UIView* splashScreenView;
/**
* Controls whether the created view will be opaque or not.
*
* Default is `YES`. Note that setting this to `NO` may negatively impact performance
* when using hardware acceleration, and toggling this will trigger a re-layout of the
* view.
*/
@property(nonatomic, getter=isViewOpaque) BOOL viewOpaque;
@end
#endif // FLUTTER_FLUTTERVIEWCONTROLLER_H_

View File

@@ -9,10 +9,25 @@
#include <memory>
#include "flutter/fml/memory/weak_ptr.h"
#include "flutter/shell/common/shell.h"
#include "flutter/shell/platform/darwin/ios/ios_surface.h"
@protocol FlutterScreenshotDelegate <NSObject>
- (shell::Rasterizer::Screenshot)takeScreenshot:(shell::Rasterizer::ScreenshotType)type
asBase64Encoded:(BOOL)base64Encode;
@end
@interface FlutterView : UIView
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE;
- (instancetype)initWithDelegate:(id<FlutterScreenshotDelegate>)delegate
opaque:(BOOL)opaque NS_DESIGNATED_INITIALIZER;
- (std::unique_ptr<shell::IOSSurface>)createSurface;
@end

View File

@@ -12,8 +12,6 @@
#include "flutter/fml/trace_event.h"
#include "flutter/shell/common/platform_view.h"
#include "flutter/shell/common/rasterizer.h"
#include "flutter/shell/common/shell.h"
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h"
#include "flutter/shell/platform/darwin/ios/ios_surface_gl.h"
#include "flutter/shell/platform/darwin/ios/ios_surface_software.h"
#include "third_party/skia/include/utils/mac/SkCGUtils.h"
@@ -24,28 +22,42 @@
@implementation FlutterView
- (FlutterViewController*)flutterViewController {
// Find the first view controller in the responder chain and see if it is a FlutterViewController.
for (UIResponder* responder = self.nextResponder; responder != nil;
responder = responder.nextResponder) {
if ([responder isKindOfClass:[UIViewController class]]) {
if ([responder isKindOfClass:[FlutterViewController class]]) {
return reinterpret_cast<FlutterViewController*>(responder);
} else {
// Should only happen if a non-FlutterViewController tries to somehow (via dynamic class
// resolution or reparenting) set a FlutterView as its view.
return nil;
}
}
id<FlutterScreenshotDelegate> _delegate;
- (instancetype)init {
@throw([NSException exceptionWithName:@"FlutterView must initWithDelegate"
reason:nil
userInfo:nil]);
}
- (instancetype)initWithFrame:(CGRect)frame {
@throw([NSException exceptionWithName:@"FlutterView must initWithDelegate"
reason:nil
userInfo:nil]);
}
- (instancetype)initWithCoder:(NSCoder*)aDecoder {
@throw([NSException exceptionWithName:@"FlutterView must initWithDelegate"
reason:nil
userInfo:nil]);
}
- (instancetype)initWithDelegate:(id<FlutterScreenshotDelegate>)delegate opaque:(BOOL)opaque {
FML_DCHECK(delegate) << "Delegate must not be nil.";
self = [super initWithFrame:CGRectNull];
if (self) {
_delegate = delegate;
self.layer.opaque = opaque;
}
return nil;
return self;
}
- (void)layoutSubviews {
if ([self.layer isKindOfClass:[CAEAGLLayer class]]) {
CAEAGLLayer* layer = reinterpret_cast<CAEAGLLayer*>(self.layer);
layer.allowsGroupOpacity = YES;
layer.opaque = YES;
CGFloat screenScale = [UIScreen mainScreen].scale;
layer.contentsScale = screenScale;
layer.rasterizationScale = screenScale;
@@ -84,16 +96,8 @@
return;
}
FlutterViewController* controller = [self flutterViewController];
if (controller == nil) {
return;
}
auto& shell = [controller shell];
auto screenshot = shell.Screenshot(shell::Rasterizer::ScreenshotType::UncompressedImage,
false /* base64 encode */);
auto screenshot = [_delegate takeScreenshot:shell::Rasterizer::ScreenshotType::UncompressedImage
asBase64Encoded:NO];
if (!screenshot.data || screenshot.data->isEmpty() || screenshot.frame_size.isEmpty()) {
return;

View File

@@ -22,7 +22,7 @@
#include "flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.h"
#include "flutter/shell/platform/darwin/ios/platform_view_ios.h"
@interface FlutterViewController () <FlutterTextInputDelegate>
@interface FlutterViewController () <FlutterTextInputDelegate, FlutterScreenshotDelegate>
@property(nonatomic, readonly) NSMutableDictionary* pluginPublications;
@end
@@ -58,6 +58,7 @@
blink::ViewportMetrics _viewportMetrics;
int64_t _nextTextureId;
BOOL _initialized;
BOOL _viewOpaque;
fml::scoped_nsobject<FlutterObservatoryPublisher> _publisher;
}
@@ -75,6 +76,8 @@
else
_dartProject.reset([projectOrNil retain]);
self.viewOpaque = YES;
[self performCommonViewControllerInitialization];
}
@@ -146,7 +149,7 @@
_threadHost.io_thread->GetTaskRunner() // io
);
_flutterView.reset([[FlutterView alloc] init]);
_flutterView.reset([[FlutterView alloc] initWithDelegate:self opaque:self.isViewOpaque]);
// Lambda captures by pointers to ObjC objects are fine here because the create call is
// synchronous.
@@ -180,6 +183,18 @@
return true;
}
- (BOOL)isViewOpaque {
return _viewOpaque;
}
- (void)viewOpaque:(BOOL)value {
_viewOpaque = value;
if (_flutterView.get().layer.opaque != value) {
_flutterView.get().layer.opaque = value;
[_flutterView.get().layer setNeedsLayout];
}
}
- (void)setupChannels {
_localizationChannel.reset([[FlutterMethodChannel alloc]
initWithName:@"flutter/localization"
@@ -840,6 +855,14 @@ static blink::PointerData::DeviceKind DeviceKindFromTouchType(UITouch* touch) {
arguments:@[ @(client), actionString ]];
}
#pragma mark - Screenshot Delegate
- (shell::Rasterizer::Screenshot)takeScreenshot:(shell::Rasterizer::ScreenshotType)type
asBase64Encoded:(BOOL)base64Encode {
FML_DCHECK(_shell) << "Cannot takeScreenshot without a shell";
return _shell->Screenshot(type, base64Encode);
}
#pragma mark - Orientation updates
- (void)onOrientationPreferencesUpdated:(NSNotification*)notification {