main added

This commit is contained in:
arnaucode
2017-02-18 12:17:52 +01:00
parent 0ef2b84b13
commit b5f4ee6bc3
254 changed files with 33106 additions and 19 deletions

View File

@@ -0,0 +1,167 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.cordova.statusbar;
import android.app.Activity;
import android.graphics.Color;
import android.os.Build;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaArgs;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.LOG;
import org.apache.cordova.PluginResult;
import org.json.JSONException;
public class StatusBar extends CordovaPlugin {
private static final String TAG = "StatusBar";
/**
* Sets the context of the Command. This can then be used to do things like
* get file paths associated with the Activity.
*
* @param cordova The context of the main Activity.
* @param webView The CordovaWebView Cordova is running in.
*/
@Override
public void initialize(final CordovaInterface cordova, CordovaWebView webView) {
LOG.v(TAG, "StatusBar: initialization");
super.initialize(cordova, webView);
this.cordova.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
// Clear flag FLAG_FORCE_NOT_FULLSCREEN which is set initially
// by the Cordova.
Window window = cordova.getActivity().getWindow();
window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
// Read 'StatusBarBackgroundColor' from config.xml, default is #000000.
setStatusBarBackgroundColor(preferences.getString("StatusBarBackgroundColor", "#000000"));
}
});
}
/**
* Executes the request and returns PluginResult.
*
* @param action The action to execute.
* @param args JSONArry of arguments for the plugin.
* @param callbackContext The callback id used when calling back into JavaScript.
* @return True if the action was valid, false otherwise.
*/
@Override
public boolean execute(final String action, final CordovaArgs args, final CallbackContext callbackContext) throws JSONException {
LOG.v(TAG, "Executing action: " + action);
final Activity activity = this.cordova.getActivity();
final Window window = activity.getWindow();
if ("_ready".equals(action)) {
boolean statusBarVisible = (window.getAttributes().flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0;
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, statusBarVisible));
return true;
}
if ("show".equals(action)) {
this.cordova.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
// SYSTEM_UI_FLAG_FULLSCREEN is available since JellyBean, but we
// use KitKat here to be aligned with "Fullscreen" preference
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
int uiOptions = window.getDecorView().getSystemUiVisibility();
uiOptions &= ~View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
uiOptions &= ~View.SYSTEM_UI_FLAG_FULLSCREEN;
window.getDecorView().setSystemUiVisibility(uiOptions);
}
// CB-11197 We still need to update LayoutParams to force status bar
// to be hidden when entering e.g. text fields
window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
});
return true;
}
if ("hide".equals(action)) {
this.cordova.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
// SYSTEM_UI_FLAG_FULLSCREEN is available since JellyBean, but we
// use KitKat here to be aligned with "Fullscreen" preference
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
int uiOptions = window.getDecorView().getSystemUiVisibility()
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_FULLSCREEN;
window.getDecorView().setSystemUiVisibility(uiOptions);
}
// CB-11197 We still need to update LayoutParams to force status bar
// to be hidden when entering e.g. text fields
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
});
return true;
}
if ("backgroundColorByHexString".equals(action)) {
this.cordova.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
try {
setStatusBarBackgroundColor(args.getString(0));
} catch (JSONException ignore) {
LOG.e(TAG, "Invalid hexString argument, use f.i. '#777777'");
}
}
});
return true;
}
return false;
}
private void setStatusBarBackgroundColor(final String colorPref) {
if (Build.VERSION.SDK_INT >= 21) {
if (colorPref != null && !colorPref.isEmpty()) {
final Window window = cordova.getActivity().getWindow();
// Method and constants not available on all SDKs but we want to be able to compile this code with any SDK
window.clearFlags(0x04000000); // SDK 19: WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.addFlags(0x80000000); // SDK 21: WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
try {
// Using reflection makes sure any 5.0+ device will work without having to compile with SDK level 21
window.getClass().getDeclaredMethod("setStatusBarColor", int.class).invoke(window, Color.parseColor(colorPref));
} catch (IllegalArgumentException ignore) {
LOG.e(TAG, "Invalid hexString argument, use f.i. '#999999'");
} catch (Exception ignore) {
// this should not happen, only in case Android removes this method in a version > 21
LOG.w(TAG, "Method window.setStatusBarColor not found for SDK level " + Build.VERSION.SDK_INT);
}
}
}
}
}

View File

@@ -0,0 +1,48 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
function notSupported(win,fail) {
//
console.log('StatusBar is not supported');
setTimeout(function(){
win();
// note that while it is not explicitly supported, it does not fail
// this is really just here to allow developers to test their code in the browser
// and if we fail, then their app might as well. -jm
},0);
}
module.exports = {
isVisible: false,
styleBlackTranslucent:notSupported,
styleDefault:notSupported,
styleLightContent:notSupported,
styleBlackOpaque:notSupported,
overlaysWebView:notSupported,
styleLightContect: notSupported,
backgroundColorByName: notSupported,
backgroundColorByHexString: notSupported,
hide: notSupported,
show: notSupported,
_ready:notSupported
};
require("cordova/exec/proxy").add("StatusBar", module.exports);

View File

@@ -0,0 +1,49 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
#import <Cordova/CDVPlugin.h>
#import <Cordova/CDVInvokedUrlCommand.h>
@interface CDVStatusBar : CDVPlugin {
@protected
BOOL _statusBarOverlaysWebView;
UIView* _statusBarBackgroundView;
BOOL _uiviewControllerBasedStatusBarAppearance;
UIColor* _statusBarBackgroundColor;
NSString* _eventsCallbackId;
}
@property (atomic, assign) BOOL statusBarOverlaysWebView;
- (void) overlaysWebView:(CDVInvokedUrlCommand*)command;
- (void) styleDefault:(CDVInvokedUrlCommand*)command;
- (void) styleLightContent:(CDVInvokedUrlCommand*)command;
- (void) styleBlackTranslucent:(CDVInvokedUrlCommand*)command;
- (void) styleBlackOpaque:(CDVInvokedUrlCommand*)command;
- (void) backgroundColorByName:(CDVInvokedUrlCommand*)command;
- (void) backgroundColorByHexString:(CDVInvokedUrlCommand*)command;
- (void) hide:(CDVInvokedUrlCommand*)command;
- (void) show:(CDVInvokedUrlCommand*)command;
- (void) _ready:(CDVInvokedUrlCommand*)command;
@end

View File

@@ -0,0 +1,508 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
/*
NOTE: plugman/cordova cli should have already installed this,
but you need the value UIViewControllerBasedStatusBarAppearance
in your Info.plist as well to set the styles in iOS 7
*/
#import "CDVStatusBar.h"
#import <objc/runtime.h>
#import <Cordova/CDVViewController.h>
static const void *kHideStatusBar = &kHideStatusBar;
static const void *kStatusBarStyle = &kStatusBarStyle;
@interface CDVViewController (StatusBar)
@property (nonatomic, retain) id sb_hideStatusBar;
@property (nonatomic, retain) id sb_statusBarStyle;
@end
@implementation CDVViewController (StatusBar)
@dynamic sb_hideStatusBar;
@dynamic sb_statusBarStyle;
- (id)sb_hideStatusBar {
return objc_getAssociatedObject(self, kHideStatusBar);
}
- (void)setSb_hideStatusBar:(id)newHideStatusBar {
objc_setAssociatedObject(self, kHideStatusBar, newHideStatusBar, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (id)sb_statusBarStyle {
return objc_getAssociatedObject(self, kStatusBarStyle);
}
- (void)setSb_statusBarStyle:(id)newStatusBarStyle {
objc_setAssociatedObject(self, kStatusBarStyle, newStatusBarStyle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL) prefersStatusBarHidden {
return [self.sb_hideStatusBar boolValue];
}
- (UIStatusBarStyle)preferredStatusBarStyle
{
return (UIStatusBarStyle)[self.sb_statusBarStyle intValue];
}
@end
@interface CDVStatusBar () <UIScrollViewDelegate>
- (void)fireTappedEvent;
- (void)updateIsVisible:(BOOL)visible;
@end
@implementation CDVStatusBar
- (id)settingForKey:(NSString*)key
{
return [self.commandDelegate.settings objectForKey:[key lowercaseString]];
}
- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context
{
if ([keyPath isEqual:@"statusBarHidden"]) {
NSNumber* newValue = [change objectForKey:NSKeyValueChangeNewKey];
[self updateIsVisible:![newValue boolValue]];
}
}
-(void)cordovaViewWillAppear:(NSNotification*)notification
{
[self resizeWebView];
}
-(void)statusBarDidChangeFrame:(NSNotification*)notification
{
//add a small delay for iOS 7 ( 0.1 seconds )
__weak CDVStatusBar* weakSelf = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[weakSelf resizeWebView];
});
}
- (void)pluginInitialize
{
BOOL isiOS7 = (IsAtLeastiOSVersion(@"7.0"));
// init
NSNumber* uiviewControllerBasedStatusBarAppearance = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UIViewControllerBasedStatusBarAppearance"];
_uiviewControllerBasedStatusBarAppearance = (uiviewControllerBasedStatusBarAppearance == nil || [uiviewControllerBasedStatusBarAppearance boolValue]) && isiOS7;
// observe the statusBarHidden property
[[UIApplication sharedApplication] addObserver:self forKeyPath:@"statusBarHidden" options:NSKeyValueObservingOptionNew context:NULL];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusBarDidChangeFrame:) name: UIApplicationDidChangeStatusBarFrameNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cordovaViewWillAppear:) name: @"CDVViewWillAppearNotification" object:nil];
_statusBarOverlaysWebView = YES; // default
[self initializeStatusBarBackgroundView];
self.viewController.view.autoresizesSubviews = YES;
NSString* setting;
setting = @"StatusBarBackgroundColor";
if ([self settingForKey:setting]) {
[self _backgroundColorByHexString:[self settingForKey:setting]];
}
setting = @"StatusBarStyle";
if ([self settingForKey:setting]) {
[self setStatusBarStyle:[self settingForKey:setting]];
}
// blank scroll view to intercept status bar taps
self.webView.scrollView.scrollsToTop = NO;
UIScrollView *fakeScrollView = [[UIScrollView alloc] initWithFrame:UIScreen.mainScreen.bounds];
fakeScrollView.delegate = self;
fakeScrollView.scrollsToTop = YES;
[self.viewController.view addSubview:fakeScrollView]; // Add scrollview to the view heirarchy so that it will begin accepting status bar taps
[self.viewController.view sendSubviewToBack:fakeScrollView]; // Send it to the very back of the view heirarchy
fakeScrollView.contentSize = CGSizeMake(UIScreen.mainScreen.bounds.size.width, UIScreen.mainScreen.bounds.size.height * 2.0f); // Make the scroll view longer than the screen itself
fakeScrollView.contentOffset = CGPointMake(0.0f, UIScreen.mainScreen.bounds.size.height); // Scroll down so a tap will take scroll view back to the top
}
- (void)onReset {
_eventsCallbackId = nil;
}
- (void)fireTappedEvent {
if (_eventsCallbackId == nil) {
return;
}
NSDictionary* payload = @{@"type": @"tap"};
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:payload];
[result setKeepCallbackAsBool:YES];
[self.commandDelegate sendPluginResult:result callbackId:_eventsCallbackId];
}
- (void)updateIsVisible:(BOOL)visible {
if (_eventsCallbackId == nil) {
return;
}
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:visible];
[result setKeepCallbackAsBool:YES];
[self.commandDelegate sendPluginResult:result callbackId:_eventsCallbackId];
}
- (void) _ready:(CDVInvokedUrlCommand*)command
{
_eventsCallbackId = command.callbackId;
[self updateIsVisible:![UIApplication sharedApplication].statusBarHidden];
NSString* setting = @"StatusBarOverlaysWebView";
if ([self settingForKey:setting]) {
self.statusBarOverlaysWebView = [(NSNumber*)[self settingForKey:setting] boolValue];
if (self.statusBarOverlaysWebView) {
[self resizeWebView];
}
}
}
- (void) initializeStatusBarBackgroundView
{
CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame;
if ([[UIApplication sharedApplication]statusBarOrientation] == UIInterfaceOrientationPortraitUpsideDown &&
statusBarFrame.size.height + statusBarFrame.origin.y == [self.viewController.view.window bounds].size.height) {
// When started in upside-down orientation on iOS 7, status bar will be bound to lower edge of the
// screen (statusBarFrame.origin.y will be somewhere around screen height). In this case we need to
// correct frame's coordinates
statusBarFrame.origin.y = 0;
}
statusBarFrame = [self invertFrameIfNeeded:statusBarFrame];
_statusBarBackgroundView = [[UIView alloc] initWithFrame:statusBarFrame];
_statusBarBackgroundView.backgroundColor = _statusBarBackgroundColor;
_statusBarBackgroundView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin);
_statusBarBackgroundView.autoresizesSubviews = YES;
}
- (CGRect) invertFrameIfNeeded:(CGRect)rect {
// landscape is where (width > height). On iOS < 8, we need to invert since frames are
// always in Portrait context. Do not run this on ios 8 or above to avoid breaking ipad pro multitask layout
if (!IsAtLeastiOSVersion(@"8.0") && UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) {
CGFloat temp = rect.size.width;
rect.size.width = rect.size.height;
rect.size.height = temp;
rect.origin = CGPointZero;
}
return rect;
}
- (void) setStatusBarOverlaysWebView:(BOOL)statusBarOverlaysWebView
{
// we only care about the latest iOS version or a change in setting
if (!IsAtLeastiOSVersion(@"7.0") || statusBarOverlaysWebView == _statusBarOverlaysWebView) {
return;
}
_statusBarOverlaysWebView = statusBarOverlaysWebView;
[self resizeWebView];
if (statusBarOverlaysWebView) {
[_statusBarBackgroundView removeFromSuperview];
} else {
[self initializeStatusBarBackgroundView];
[self.webView.superview addSubview:_statusBarBackgroundView];
}
}
- (BOOL) statusBarOverlaysWebView
{
return _statusBarOverlaysWebView;
}
- (void) overlaysWebView:(CDVInvokedUrlCommand*)command
{
id value = [command argumentAtIndex:0];
if (!([value isKindOfClass:[NSNumber class]])) {
value = [NSNumber numberWithBool:YES];
}
self.statusBarOverlaysWebView = [value boolValue];
}
- (void) refreshStatusBarAppearance
{
SEL sel = NSSelectorFromString(@"setNeedsStatusBarAppearanceUpdate");
if ([self.viewController respondsToSelector:sel]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[self.viewController performSelector:sel withObject:nil];
#pragma clang diagnostic pop
}
}
- (void) setStyleForStatusBar:(UIStatusBarStyle)style
{
if (_uiviewControllerBasedStatusBarAppearance) {
CDVViewController* vc = (CDVViewController*)self.viewController;
vc.sb_statusBarStyle = [NSNumber numberWithInt:style];
[self refreshStatusBarAppearance];
} else {
[[UIApplication sharedApplication] setStatusBarStyle:style];
}
}
- (void) setStatusBarStyle:(NSString*)statusBarStyle
{
// default, lightContent, blackTranslucent, blackOpaque
NSString* lcStatusBarStyle = [statusBarStyle lowercaseString];
if ([lcStatusBarStyle isEqualToString:@"default"]) {
[self styleDefault:nil];
} else if ([lcStatusBarStyle isEqualToString:@"lightcontent"]) {
[self styleLightContent:nil];
} else if ([lcStatusBarStyle isEqualToString:@"blacktranslucent"]) {
[self styleBlackTranslucent:nil];
} else if ([lcStatusBarStyle isEqualToString:@"blackopaque"]) {
[self styleBlackOpaque:nil];
}
}
- (void) styleDefault:(CDVInvokedUrlCommand*)command
{
[self setStyleForStatusBar:UIStatusBarStyleDefault];
}
- (void) styleLightContent:(CDVInvokedUrlCommand*)command
{
[self setStyleForStatusBar:UIStatusBarStyleLightContent];
}
- (void) styleBlackTranslucent:(CDVInvokedUrlCommand*)command
{
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 70000
# define TRANSLUCENT_STYLE UIStatusBarStyleBlackTranslucent
#else
# define TRANSLUCENT_STYLE UIStatusBarStyleLightContent
#endif
[self setStyleForStatusBar:TRANSLUCENT_STYLE];
}
- (void) styleBlackOpaque:(CDVInvokedUrlCommand*)command
{
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 70000
# define OPAQUE_STYLE UIStatusBarStyleBlackOpaque
#else
# define OPAQUE_STYLE UIStatusBarStyleLightContent
#endif
[self setStyleForStatusBar:OPAQUE_STYLE];
}
- (void) backgroundColorByName:(CDVInvokedUrlCommand*)command
{
id value = [command argumentAtIndex:0];
if (!([value isKindOfClass:[NSString class]])) {
value = @"black";
}
SEL selector = NSSelectorFromString([value stringByAppendingString:@"Color"]);
if ([UIColor respondsToSelector:selector]) {
_statusBarBackgroundView.backgroundColor = [UIColor performSelector:selector];
}
}
- (void) _backgroundColorByHexString:(NSString*)hexString
{
unsigned int rgbValue = 0;
NSScanner* scanner = [NSScanner scannerWithString:hexString];
[scanner setScanLocation:1];
[scanner scanHexInt:&rgbValue];
_statusBarBackgroundColor = [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16)/255.0 green:((rgbValue & 0xFF00) >> 8)/255.0 blue:(rgbValue & 0xFF)/255.0 alpha:1.0];
_statusBarBackgroundView.backgroundColor = _statusBarBackgroundColor;
}
- (void) backgroundColorByHexString:(CDVInvokedUrlCommand*)command
{
NSString* value = [command argumentAtIndex:0];
if (!([value isKindOfClass:[NSString class]])) {
value = @"#000000";
}
if (![value hasPrefix:@"#"] || [value length] < 7) {
return;
}
[self _backgroundColorByHexString:value];
}
- (void) hideStatusBar
{
if (_uiviewControllerBasedStatusBarAppearance) {
CDVViewController* vc = (CDVViewController*)self.viewController;
vc.sb_hideStatusBar = [NSNumber numberWithBool:YES];
[self refreshStatusBarAppearance];
} else {
UIApplication* app = [UIApplication sharedApplication];
[app setStatusBarHidden:YES];
}
}
- (void) hide:(CDVInvokedUrlCommand*)command
{
UIApplication* app = [UIApplication sharedApplication];
if (!app.isStatusBarHidden)
{
[self hideStatusBar];
if (IsAtLeastiOSVersion(@"7.0")) {
[_statusBarBackgroundView removeFromSuperview];
}
[self resizeWebView];
_statusBarBackgroundView.hidden = YES;
}
}
- (void) showStatusBar
{
if (_uiviewControllerBasedStatusBarAppearance) {
CDVViewController* vc = (CDVViewController*)self.viewController;
vc.sb_hideStatusBar = [NSNumber numberWithBool:NO];
[self refreshStatusBarAppearance];
} else {
UIApplication* app = [UIApplication sharedApplication];
[app setStatusBarHidden:NO];
}
}
- (void) show:(CDVInvokedUrlCommand*)command
{
UIApplication* app = [UIApplication sharedApplication];
if (app.isStatusBarHidden)
{
BOOL isIOS7 = (IsAtLeastiOSVersion(@"7.0"));
[self showStatusBar];
[self resizeWebView];
if (isIOS7) {
if (!self.statusBarOverlaysWebView) {
// there is a possibility that when the statusbar was hidden, it was in a different orientation
// from the current one. Therefore we need to expand the statusBarBackgroundView as well to the
// statusBar's current size
CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame;
statusBarFrame = [self invertFrameIfNeeded:statusBarFrame];
CGRect sbBgFrame = _statusBarBackgroundView.frame;
sbBgFrame.size = statusBarFrame.size;
_statusBarBackgroundView.frame = sbBgFrame;
[self.webView.superview addSubview:_statusBarBackgroundView];
}
}
_statusBarBackgroundView.hidden = NO;
}
}
-(void)resizeWebView
{
BOOL isIOS7 = (IsAtLeastiOSVersion(@"7.0"));
if (isIOS7) {
CGRect bounds = [self.viewController.view.window bounds];
bounds = [self invertFrameIfNeeded:bounds];
if (UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])) {
self.viewController.view.frame = bounds;
} else if (self.viewController.presentedViewController != nil) {
// https://issues.apache.org/jira/browse/CB-11018
BOOL isIOS8 = (IsAtLeastiOSVersion(@"8.0"));
BOOL isIOS9 = (IsAtLeastiOSVersion(@"9.0"));
if (isIOS8 && !isIOS9) {
// iOS 8
bounds = CGRectMake(0, 0, bounds.size.width, bounds.size.height);
} else {
// iOS7, iOS9+
if ([self.viewController.presentedViewController.presentationController isKindOfClass:[UIPopoverPresentationController class]] || UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad) {
bounds = CGRectMake(0, 0, bounds.size.width, bounds.size.height);
} else {
bounds = CGRectMake(0, 0, bounds.size.height, bounds.size.width);
}
}
}
self.webView.frame = bounds;
CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame;
statusBarFrame = [self invertFrameIfNeeded:statusBarFrame];
CGRect frame = self.webView.frame;
CGFloat height = statusBarFrame.size.height;
if (!self.statusBarOverlaysWebView) {
// CB-10158 If a full screen video is playing the status bar height will be 0, set it to 20
frame.origin.y = height > 0 ? height: 20;
} else {
// Even if overlay is used, we want to handle in-call/recording/hotspot larger status bar
frame.origin.y = height >= 20 ? height - 20 : 0;
}
frame.size.height -= frame.origin.y;
self.webView.frame = frame;
} else {
CGRect bounds = [[UIScreen mainScreen] applicationFrame];
self.viewController.view.frame = bounds;
}
}
- (void) dealloc
{
[[UIApplication sharedApplication] removeObserver:self forKeyPath:@"statusBarHidden"];
[[NSNotificationCenter defaultCenter]removeObserver:self name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
}
#pragma mark - UIScrollViewDelegate
- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView
{
[self fireTappedEvent];
return NO;
}
@end

View File

@@ -0,0 +1,114 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
/* global Windows */
var _supported = null; // set to null so we can check first time
function isSupported() {
// if not checked before, run check
if (_supported === null) {
var viewMan = Windows.UI.ViewManagement;
_supported = (viewMan.StatusBar && viewMan.StatusBar.getForCurrentView);
}
return _supported;
}
function getViewStatusBar() {
if (!isSupported()) {
throw new Error("Status bar is not supported");
}
return Windows.UI.ViewManagement.StatusBar.getForCurrentView();
}
function hexToRgb(hex) {
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
hex = hex.replace(shorthandRegex, function (m, r, g, b) {
return r + r + g + g + b + b;
});
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
module.exports = {
_ready: function(win, fail) {
if(isSupported()) {
var statusBar = getViewStatusBar();
win(statusBar.occludedRect.height !== 0);
}
},
overlaysWebView: function () {
// not supported
},
styleDefault: function () {
// dark text ( to be used on a light background )
if (isSupported()) {
getViewStatusBar().foregroundColor = { a: 0, r: 0, g: 0, b: 0 };
}
},
styleLightContent: function () {
// light text ( to be used on a dark background )
if (isSupported()) {
getViewStatusBar().foregroundColor = { a: 0, r: 255, g: 255, b: 255 };
}
},
styleBlackTranslucent: function () {
// #88000000 ? Apple says to use lightContent instead
return module.exports.styleLightContent();
},
styleBlackOpaque: function () {
// #FF000000 ? Apple says to use lightContent instead
return module.exports.styleLightContent();
},
backgroundColorByHexString: function (win, fail, args) {
var rgb = hexToRgb(args[0]);
if(isSupported()) {
var statusBar = getViewStatusBar();
statusBar.backgroundColor = { a: 0, r: rgb.r, g: rgb.g, b: rgb.b };
statusBar.backgroundOpacity = 1;
}
},
show: function (win, fail) {
// added support check so no error thrown, when calling this method
if (isSupported()) {
getViewStatusBar().showAsync().done(win, fail);
}
},
hide: function (win, fail) {
// added support check so no error thrown, when calling this method
if (isSupported()) {
getViewStatusBar().hideAsync().done(win, fail);
}
}
};
require("cordova/exec/proxy").add("StatusBar", module.exports);

View File

@@ -0,0 +1,141 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
using Microsoft.Phone.Shell;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Threading;
using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;
/*
* http://www.idev101.com/code/User_Interface/StatusBar.html
* https://developer.apple.com/library/ios/documentation/userexperience/conceptual/transitionguide/Bars.html
* https://developer.apple.com/library/ios/documentation/uikit/reference/UIApplication_Class/Reference/Reference.html#//apple_ref/c/econst/UIStatusBarStyleDefault
* */
namespace WPCordovaClassLib.Cordova.Commands
{
public class StatusBar : BaseCommand
{
// returns an argb value, if the hex is only rgb, it will be full opacity
protected Color ColorFromHex(string hexString)
{
string cleanHex = hexString.Replace("#", "").Replace("0x", "");
// turn #FFF into #FFFFFF
if (cleanHex.Length == 3)
{
cleanHex = "" + cleanHex[0] + cleanHex[0] + cleanHex[1] + cleanHex[1] + cleanHex[2] + cleanHex[2];
}
// add an alpha 100% if it is missing
if (cleanHex.Length == 6)
{
cleanHex = "FF" + cleanHex;
}
int argb = Int32.Parse(cleanHex, NumberStyles.HexNumber);
Color clr = Color.FromArgb((byte)((argb & 0xff000000) >> 0x18),
(byte)((argb & 0xff0000) >> 0x10),
(byte)((argb & 0xff00) >> 8),
(byte)(argb & 0xff));
return clr;
}
public void _ready(string options)
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
bool isVis = SystemTray.IsVisible;
// TODO: pass this to JS
//Debug.WriteLine("Result::" + res);
DispatchCommandResult(new PluginResult(PluginResult.Status.OK, isVis));
});
}
public void overlaysWebView(string options)
{ //exec(null, null, "StatusBar", "overlaysWebView", [doOverlay]);
// string arg = JSON.JsonHelper.Deserialize<string[]>(options)[0];
}
public void styleDefault(string options)
{ //exec(null, null, "StatusBar", "styleDefault", []);
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
SystemTray.ForegroundColor = Colors.Black;
});
}
public void styleLightContent(string options)
{ //exec(null, null, "StatusBar", "styleLightContent", []);
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
SystemTray.ForegroundColor = Colors.White;
});
}
public void styleBlackTranslucent(string options)
{ //exec(null, null, "StatusBar", "styleBlackTranslucent", []);
styleLightContent(options);
}
public void styleBlackOpaque(string options)
{ //exec(null, null, "StatusBar", "styleBlackOpaque", []);
styleLightContent(options);
}
public void backgroundColorByName(string options)
{ //exec(null, null, "StatusBar", "backgroundColorByName", [colorname]);
// this should NOT be called, js should now be using/converting color names to hex
}
public void backgroundColorByHexString(string options)
{ //exec(null, null, "StatusBar", "backgroundColorByHexString", [hexString]);
string argb = JSON.JsonHelper.Deserialize<string[]>(options)[0];
Color clr = ColorFromHex(argb);
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
SystemTray.Opacity = clr.A / 255.0d;
SystemTray.BackgroundColor = clr;
});
}
public void hide(string options)
{ //exec(null, null, "StatusBar", "hide", []);
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
SystemTray.IsVisible = false;
});
}
public void show(string options)
{ //exec(null, null, "StatusBar", "show", []);
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
SystemTray.IsVisible = true;
});
}
}
}