Skip to content
This repository has been archived by the owner on May 1, 2024. It is now read-only.

Commit

Permalink
Remove status bar underlay view in Android AppCompat (#892)
Browse files Browse the repository at this point in the history
* Remove status bar underlay and handle status bar color with theme colors

* Fix layout gap when SoftInputMode is set to resize

* Restore linker settings
  • Loading branch information
hartez authored and kingces95 committed May 4, 2017
1 parent 34a1cc8 commit 1e17850
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 112 deletions.
8 changes: 8 additions & 0 deletions Xamarin.Forms.ControlGallery.Android/Activity1.cs
Expand Up @@ -15,6 +15,8 @@
using Xamarin.Forms.Platform.Android;
using Xamarin.Forms.Platform.Android.AppLinks;
using Android.Content;
using Android.Views;
using AColor = Android.Graphics.Color;

[assembly: Dependency (typeof (CacheService))]
[assembly: Dependency (typeof (TestCloudService))]
Expand Down Expand Up @@ -286,6 +288,9 @@ protected override void OnCreate (Bundle bundle)
ToolbarResource = Resource.Layout.Toolbar;
TabLayoutResource = Resource.Layout.Tabbar;

// Uncomment the next line to run this as a full screen app (no status bar)
//Window.AddFlags(WindowManagerFlags.Fullscreen | WindowManagerFlags.TurnScreenOn);

base.OnCreate (bundle);

if (!Debugger.IsAttached)
Expand All @@ -311,6 +316,9 @@ protected override void OnCreate (Bundle bundle)
// When the native binding gallery loads up, it'll let us know so we can set up the native bindings
MessagingCenter.Subscribe<NativeBindingGalleryPage >(this, NativeBindingGalleryPage.ReadyForNativeBindingsMessage, AddNativeBindings);

// Listen for the message from the status bar color toggle test
MessagingCenter.Subscribe<AndroidStatusBarColor>(this, AndroidStatusBarColor.Message, color => SetStatusBarColor(AColor.Red));

LoadApplication(app);
}

Expand Down
Expand Up @@ -2,4 +2,5 @@
<resources>
<color name="cellback">#FFFFFFE0</color>
<color name="cellback2">#FFDAFF7F</color>
<color name="primary_dark">#1976D2</color>
</resources>
Expand Up @@ -18,7 +18,7 @@
<!-- colorPrimary is used for the default action bar background -->
<item name="colorPrimary">#2196F3</item>
<!-- colorPrimaryDark is used for the status bar -->
<item name="colorPrimaryDark">#1976D2</item>
<item name="android:colorPrimaryDark">@color/primary_dark</item>
<!-- colorAccent is used as the default value for colorControlActivated
which is used to tint widgets -->
<item name="colorAccent">#FF4081</item>
Expand Down
@@ -0,0 +1,37 @@
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;

namespace Xamarin.Forms.Controls.Issues
{
[Preserve(AllMembers = true)]
[Issue(IssueTracker.None, 5553226, "Set status bar color on Android", PlatformAffected.Android)]
public class AndroidStatusBarColor : TestContentPage
{
public const string Message = "ChangeStatusBarToRed";

protected override void Init()
{
var layout = new StackLayout
{
HorizontalOptions = LayoutOptions.Fill,
VerticalOptions = LayoutOptions.Fill,
Margin = new Thickness(100)
};

var instructions = new Label
{
Text =
"Tapping the button below should change the status bar color to red. If the status bar does not change to red, the test has failed. (Ignore this test for pre-Lollipop devices.)"
};

var button = new Button { Text = "Change Status Bar Color" };

button.Clicked += (sender, args) => { MessagingCenter.Send(this, Message); };

layout.Children.Add(instructions);
layout.Children.Add(button);

Content = layout;
}
}
}
@@ -0,0 +1,59 @@
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.AndroidSpecific;

namespace Xamarin.Forms.Controls.Issues
{
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Bugzilla, 47548, "Setting soft input mode to resize creates gap", PlatformAffected.Android)]
public class Bugzilla47548 : TestContentPage
{
static string GetMode()
{
return Application.Current.On<Android>().GetWindowSoftInputModeAdjust() == WindowSoftInputModeAdjust.Pan
? "Pan"
: "Resize";
}

protected override void Init()
{
var button = new Button() { Text = $"Toggle Soft Input Mode (Currently {GetMode()})"};

button.Clicked += (sender, args) =>
{
Application.Current.On<Android>()
.UseWindowSoftInputModeAdjust(Application.Current.On<Android>().GetWindowSoftInputModeAdjust() ==
WindowSoftInputModeAdjust.Pan
? WindowSoftInputModeAdjust.Resize
: WindowSoftInputModeAdjust.Pan);
button.Text = $"Toggle Soft Input Mode (Currently {GetMode()})";
};

Content = new StackLayout
{
BackgroundColor = Color.CadetBlue,
Spacing = 10,
VerticalOptions = LayoutOptions.Fill,
Children =
{
new Label
{
Text = @"With Soft Input Mode set to Pan, tapping the Entry at the bottom of the screen should cause the whole page to scroll up above the keyboard.
With Soft Input Mode set to Resize, tapping the Entry at the bottom of the screen should resize the content to display everything above the keyboard (the Crimson Label in the middle should be squashed to fit)."
},
button,
new Label
{
FontSize = 12f,
HeightRequest = 500,
Text = @"Meh",
BackgroundColor = Color.Crimson
},
new Entry()
}
};
}
}
}
Expand Up @@ -10,6 +10,7 @@
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)AddingMultipleItemsListView.cs" />
<Compile Include="$(MSBuildThisFileDirectory)AndroidStatusBarColor.cs" />
<Compile Include="$(MSBuildThisFileDirectory)AppBarIconColors.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla21368.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla21501.cs" />
Expand Down Expand Up @@ -160,6 +161,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla44096.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla44176.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla44453.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla47548.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla53834.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla51536.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla44940.cs" />
Expand Down
96 changes: 10 additions & 86 deletions Xamarin.Forms.Platform.Android/AppCompat/FormsAppCompatActivity.cs
Expand Up @@ -45,8 +45,6 @@ public class FormsAppCompatActivity : AppCompatActivity, IDeviceInfoProvider, IS
AndroidApplicationLifecycleState _previousState;

bool _renderersAdded, _isFullScreen;
int _statusBarHeight = -1;
global::Android.Views.View _statusBarUnderlay;

// Override this if you want to handle the default Android behavior of restoring fragments on an application restart
protected virtual bool AllowFragmentRestore => false;
Expand Down Expand Up @@ -105,7 +103,10 @@ public override bool OnOptionsItemSelected(IMenuItem item)

public void SetStatusBarColor(AColor color)
{
_statusBarUnderlay.SetBackgroundColor(color);
if (Forms.IsLollipopOrNewer)
{
Window.SetStatusBarColor(color);
}
}

protected void LoadApplication(Application application)
Expand Down Expand Up @@ -171,7 +172,7 @@ protected override void OnCreate(Bundle savedInstanceState)
}
else
bar = new AToolbar(this);

SetSupportActionBar(bar);

_layout = new ARelativeLayout(BaseContext);
Expand All @@ -184,7 +185,11 @@ protected override void OnCreate(Bundle savedInstanceState)

OnStateChanged();

AddStatusBarUnderlay();
if (Forms.IsLollipopOrNewer)
{
// Allow for the status bar color to be changed
Window.AddFlags(WindowManagerFlags.DrawsSystemBarBackgrounds);
}
}

protected override void OnDestroy()
Expand Down Expand Up @@ -280,45 +285,6 @@ protected override void OnStop()
OnStateChanged();
}

internal int GetStatusBarHeight()
{
if (_statusBarHeight >= 0)
return _statusBarHeight;

var result = 0;
int resourceId = Resources.GetIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0)
result = Resources.GetDimensionPixelSize(resourceId);
return _statusBarHeight = result;
}

void AddStatusBarUnderlay()
{
_statusBarUnderlay = new global::Android.Views.View(this);

var layoutParameters = new ARelativeLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, GetStatusBarHeight()) { AlignWithParent = true };
layoutParameters.AddRule(LayoutRules.AlignTop);
_statusBarUnderlay.LayoutParameters = layoutParameters;
_layout.AddView(_statusBarUnderlay);

if (Forms.IsLollipopOrNewer)
{
Window.AddFlags(WindowManagerFlags.DrawsSystemBarBackgrounds);
Window.SetStatusBarColor(AColor.Transparent);

int primaryColorDark = GetColorPrimaryDark();

if (primaryColorDark != 0)
{
int r = AColor.GetRedComponent(primaryColorDark);
int g = AColor.GetGreenComponent(primaryColorDark);
int b = AColor.GetBlueComponent(primaryColorDark);
int a = AColor.GetAlphaComponent(primaryColorDark);
SetStatusBarColor(AColor.Argb(a, r, g, b));
}
}
}

void AppOnPropertyChanged(object sender, PropertyChangedEventArgs args)
{
if (args.PropertyName == "MainPage")
Expand All @@ -338,32 +304,6 @@ void CheckForAppLink(Intent intent)
_application?.SendOnAppLinkRequestReceived(link);
}

int GetColorPrimaryDark()
{
FormsAppCompatActivity context = this;
int id = global::Android.Resource.Attribute.ColorPrimaryDark;
using (var value = new TypedValue())
{
try
{
Resources.Theme theme = context.Theme;
if (theme != null && theme.ResolveAttribute(id, value, true))
{
if (value.Type >= DataType.FirstInt && value.Type <= DataType.LastInt)
return value.Data;
if (value.Type == DataType.String)
return ContextCompat.GetColor(context, value.ResourceId);
}
}
catch (Exception ex)
{
Internals.Log.Warning("Xamarin.Forms.Platform.Android.FormsAppCompatActivity", "Error retrieving color resource: {0}", ex);
}

return -1;
}
}

void InternalSetPage(Page page)
{
if (!Forms.IsInitialized)
Expand Down Expand Up @@ -477,7 +417,6 @@ void SetSoftInputMode()
}

Window.SetSoftInputMode(adjust);
SetStatusBarVisibility(adjust);
}

public override void OnWindowAttributesChanged(WindowManagerLayoutParams @params)
Expand Down Expand Up @@ -512,21 +451,6 @@ public override void OnWindowAttributesChanged(WindowManagerLayoutParams @params
AppCompat.Platform.LayoutRootPage(this, Xamarin.Forms.Application.Current.MainPage, width, height);
}

void SetStatusBarVisibility(SoftInput mode)
{
if (!Forms.IsLollipopOrNewer)
return;

if (mode == SoftInput.AdjustResize)
{
Window.DecorView.SystemUiVisibility = (StatusBarVisibility)(SystemUiFlags.Immersive);
}
else
Window.DecorView.SystemUiVisibility = (StatusBarVisibility)(SystemUiFlags.LayoutFullscreen | SystemUiFlags.LayoutStable);

_layout?.Invalidate();
}

void UpdateProgressBarVisibility(bool isBusy)
{
if (!Forms.SupportsProgress)
Expand Down
Expand Up @@ -113,23 +113,17 @@ void IVisualElementRenderer.SetElement(VisualElement element)
oldElement.Disappearing -= MasterDetailPageDisappearing;
}

var statusBarHeight = 0;
if (Forms.IsLollipopOrNewer)
statusBarHeight = ((FormsAppCompatActivity)Context).GetStatusBarHeight();

if (newElement != null)
{
if (_detailLayout == null)
{
_detailLayout = new MasterDetailContainer(newElement, false, Context)
{
TopPadding = HasAncestorNavigationPage(Element) ? 0 : statusBarHeight,
LayoutParameters = new LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent)
};

_masterLayout = new MasterDetailContainer(newElement, true, Context)
{
TopPadding = ((IMasterDetailPageController)newElement).ShouldShowSplitMode ? statusBarHeight : 0,
LayoutParameters = new LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent) { Gravity = (int)GravityFlags.Start }
};

Expand Down
25 changes: 6 additions & 19 deletions Xamarin.Forms.Platform.Android/AppCompat/Platform.cs
Expand Up @@ -8,7 +8,6 @@
using Android.Views.Animations;
using ARelativeLayout = Android.Widget.RelativeLayout;
using Xamarin.Forms.Internals;
using Debug = System.Diagnostics.Debug;

namespace Xamarin.Forms.Platform.Android.AppCompat
{
Expand Down Expand Up @@ -196,7 +195,9 @@ SizeRequest IPlatform.GetNativeSize(VisualElement view, double widthConstraint,
void IPlatformLayout.OnLayout(bool changed, int l, int t, int r, int b)
{
if (changed)
{
LayoutRootPage((FormsAppCompatActivity)_context, Page, r - l, b - t);
}

Android.Platform.GetRenderer(Page).UpdateLayout();

Expand Down Expand Up @@ -286,15 +287,7 @@ bool HandleBackPressed(object sender, EventArgs e)

internal static void LayoutRootPage(FormsAppCompatActivity activity, Page page, int width, int height)
{
int statusBarHeight = Forms.IsLollipopOrNewer ? activity.GetStatusBarHeight() : 0;
statusBarHeight = activity.Window.Attributes.Flags.HasFlag(WindowManagerFlags.Fullscreen) || Forms.TitleBarVisibility == AndroidTitleBarVisibility.Never ? 0 : statusBarHeight;

if (page is MasterDetailPage)
page.Layout(new Rectangle(0, 0, activity.FromPixels(width), activity.FromPixels(height)));
else
{
page.Layout(new Rectangle(0, activity.FromPixels(statusBarHeight), activity.FromPixels(width), activity.FromPixels(height - statusBarHeight)));
}
page.Layout(new Rectangle(0, 0, activity.FromPixels(width), activity.FromPixels(height)));
}

Task PresentModal(Page modal, bool animated)
Expand Down Expand Up @@ -381,18 +374,12 @@ protected override void Dispose(bool disposing)

protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
var activity = (FormsAppCompatActivity)Context;
int statusBarHeight = Forms.IsLollipopOrNewer ? activity.GetStatusBarHeight() : 0;
if (changed)
{
if (_modal is MasterDetailPage)
_modal.Layout(new Rectangle(0, 0, activity.FromPixels(r - l), activity.FromPixels(b - t)));
else
{
_modal.Layout(new Rectangle(0, activity.FromPixels(statusBarHeight), activity.FromPixels(r - l), activity.FromPixels(b - t - statusBarHeight)));
}
var activity = (FormsAppCompatActivity)Context;

_backgroundView.Layout(0, statusBarHeight, r - l, b - t);
_modal.Layout(new Rectangle(0, 0, activity.FromPixels(r - l), activity.FromPixels(b - t)));
_backgroundView.Layout(0, 0, r - l, b - t);
}

_renderer.UpdateLayout();
Expand Down

0 comments on commit 1e17850

Please sign in to comment.