From efc4a4087349cdf10b6fffa34989dd98eb512f12 Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Mon, 30 Mar 2020 10:01:34 -0600 Subject: [PATCH 1/3] Copy build to buildTransitive (#10125) * Copy build to buildTransitive * - be less clever --- .nuspec/Xamarin.Forms.Visual.Material.nuspec | 4 +++ .nuspec/Xamarin.Forms.nuspec | 38 ++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/.nuspec/Xamarin.Forms.Visual.Material.nuspec b/.nuspec/Xamarin.Forms.Visual.Material.nuspec index 243cf0a39..2c89e42f5 100644 --- a/.nuspec/Xamarin.Forms.Visual.Material.nuspec +++ b/.nuspec/Xamarin.Forms.Visual.Material.nuspec @@ -46,6 +46,9 @@ + + + @@ -64,5 +67,6 @@ + diff --git a/.nuspec/Xamarin.Forms.nuspec b/.nuspec/Xamarin.Forms.nuspec index d844da6ca..2d2e171b0 100644 --- a/.nuspec/Xamarin.Forms.nuspec +++ b/.nuspec/Xamarin.Forms.nuspec @@ -151,6 +151,28 @@ + + + + + + + + + + + + + + + + + + + + + + @@ -173,6 +195,8 @@ + + @@ -212,6 +236,15 @@ + + + + + + + + + @@ -302,6 +335,10 @@ + + + + @@ -349,6 +386,7 @@ + From 1dcab3d27641c65421314d6c6527a68118c36370 Mon Sep 17 00:00:00 2001 From: "E.Z. Hart" Date: Mon, 30 Mar 2020 10:12:05 -0600 Subject: [PATCH 2/3] Ensure that Visual is available to EmptyView when renderers are created (#10022) fixes #8766 * Parent the EmptyView long enough to get the correct Visual * Temporarily parent empty views on Android to get correct Visual Fixes #8766 * Make instructions more explicit * Propagate the visual without a parent * Clean up last parenting clause --- .../Issue8766.cs | 54 +++++++++++++++ ...rin.Forms.Controls.Issues.Shared.projitems | 1 + Xamarin.Forms.Core/Element.cs | 37 ----------- .../PropertyPropagationExtensions.cs | 65 ++++++++++++++++--- Xamarin.Forms.Core/Items/ItemsView.cs | 2 - .../CollectionView/EmptyViewAdapter.cs | 2 +- .../CollectionView/SimpleViewHolder.cs | 6 +- .../CollectionView/TemplatedItemViewHolder.cs | 4 ++ .../CollectionView/TemplateHelpers.cs | 9 ++- 9 files changed, 129 insertions(+), 51 deletions(-) create mode 100644 Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue8766.cs diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue8766.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue8766.cs new file mode 100644 index 000000000..f369ecf8a --- /dev/null +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue8766.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Text; +using Xamarin.Forms.CustomAttributes; +using Xamarin.Forms.Internals; + +#if UITEST +using Xamarin.UITest; +using NUnit.Framework; +using Xamarin.Forms.Core.UITests; +#endif + +namespace Xamarin.Forms.Controls.Issues +{ + [Issue(IssueTracker.Github, 8766, "[Bug] CollectionView.EmptyView does not inherit parent Visual", PlatformAffected.All)] + public class Issue8766 : TestContentPage + { + protected override void Init() + { + Visual = VisualMarker.Material; + + var layout = new StackLayout(); + + var instructions = new Label { Text = "If the Entry and Button above the CollectionView and the Entry and Button inside the CollectionView, should both be using the Material Visual. If so, this test has passed."}; + layout.Children.Add(instructions); + + var entry = new Entry { Placeholder = "I am material" }; + var button = new Button { Text = "I am material" }; + layout.Children.Add(entry); + layout.Children.Add(button); + + var colv = new CollectionView() { }; + + var emptyViewEntry = new Entry { Placeholder = "I should be material" }; + var emptyViewButton = new Button { Text = "I should be material, too" }; + var stack = new StackLayout { Children = { emptyViewEntry, emptyViewButton } }; + + colv.EmptyView = stack; + layout.Children.Add(colv); + + Content = layout; + } + +#if UITEST + [Test] + [Category(UITestCategories.ManualReview)] + public void VisualPropagatesToEmptyView() + { + RunningApp.Screenshot("CollectionViewWithEmptyView"); + } +#endif + } +} diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems index f81f815ea..182e3ca48 100644 --- a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems @@ -25,6 +25,7 @@ Issue8715.xaml Code + diff --git a/Xamarin.Forms.Core/Element.cs b/Xamarin.Forms.Core/Element.cs index a38afbe3c..8c52e9534 100644 --- a/Xamarin.Forms.Core/Element.cs +++ b/Xamarin.Forms.Core/Element.cs @@ -462,43 +462,6 @@ namespace Xamarin.Forms internal event EventHandler ParentSet; - internal static void SetFlowDirectionFromParent(Element child) - { - IFlowDirectionController controller = child as IFlowDirectionController; - if (controller == null) - return; - - if (controller.EffectiveFlowDirection.IsImplicit()) - { - var parentView = child.Parent as IFlowDirectionController; - if (parentView == null) - return; - - var flowDirection = parentView.EffectiveFlowDirection.ToFlowDirection(); - - if (flowDirection != controller.EffectiveFlowDirection.ToFlowDirection()) - { - controller.EffectiveFlowDirection = flowDirection.ToEffectiveFlowDirection(); - } - } - } - - internal static void SetVisualfromParent(Element child) - { - IVisualController controller = child as IVisualController; - if (controller == null) - return; - - if (controller.Visual != VisualMarker.MatchParent) - { - controller.EffectiveVisual = controller.Visual; - return; - } - - if (child.Parent is IVisualController parentView) - controller.EffectiveVisual = parentView.EffectiveVisual; - } - internal virtual void SetChildInheritedBindingContext(Element child, object context) { SetInheritedBindingContext(child, context); diff --git a/Xamarin.Forms.Core/Internals/PropertyPropagationExtensions.cs b/Xamarin.Forms.Core/Internals/PropertyPropagationExtensions.cs index 5a7abecb6..40c22aef1 100644 --- a/Xamarin.Forms.Core/Internals/PropertyPropagationExtensions.cs +++ b/Xamarin.Forms.Core/Internals/PropertyPropagationExtensions.cs @@ -5,15 +5,15 @@ using System.Text; namespace Xamarin.Forms.Internals { - internal static class PropertyPropagationExtensions + public static class PropertyPropagationExtensions { - public static void PropagatePropertyChanged(string propertyName, Element element, IEnumerable children) + internal static void PropagatePropertyChanged(string propertyName, Element element, IEnumerable children) { if (propertyName == null || propertyName == VisualElement.FlowDirectionProperty.PropertyName) - Element.SetFlowDirectionFromParent(element); + SetFlowDirectionFromParent(element); if (propertyName == null || propertyName == VisualElement.VisualProperty.PropertyName) - Element.SetVisualfromParent(element); + SetVisualfromParent(element); if (propertyName == null || propertyName == Shell.NavBarIsVisibleProperty.PropertyName) BaseShellItem.PropagateFromParent(Shell.NavBarIsVisibleProperty, element); @@ -31,16 +31,63 @@ namespace Xamarin.Forms.Internals } } - internal static void PropagatePropertyChanged(string propertyName, Element element) + public static void PropagatePropertyChanged(string propertyName, Element target, Element source) { if (propertyName == null || propertyName == VisualElement.FlowDirectionProperty.PropertyName) - Element.SetFlowDirectionFromParent(element); + PropagateFlowDirection(target, source); if (propertyName == null || propertyName == VisualElement.VisualProperty.PropertyName) - Element.SetVisualfromParent(element); + PropagateVisual(target, source); - if (element is IPropertyPropagationController view) - view.PropagatePropertyChanged(propertyName); + if (target is IPropertyPropagationController view) + view.PropagatePropertyChanged(propertyName); + } + + internal static void PropagateFlowDirection(Element target, Element source) + { + IFlowDirectionController targetController = target as IFlowDirectionController; + if (targetController == null) + return; + + if (targetController.EffectiveFlowDirection.IsImplicit()) + { + var sourceController = source as IFlowDirectionController; + if (sourceController == null) + return; + + var flowDirection = sourceController.EffectiveFlowDirection.ToFlowDirection(); + + if (flowDirection != targetController.EffectiveFlowDirection.ToFlowDirection()) + { + targetController.EffectiveFlowDirection = flowDirection.ToEffectiveFlowDirection(); + } + } + } + + internal static void SetFlowDirectionFromParent(Element child) + { + PropagateFlowDirection(child, child.Parent); + } + + internal static void PropagateVisual(Element target, Element source) + { + IVisualController targetController = target as IVisualController; + if (targetController == null) + return; + + if (targetController.Visual != VisualMarker.MatchParent) + { + targetController.EffectiveVisual = targetController.Visual; + return; + } + + if (source is IVisualController sourceController) + targetController.EffectiveVisual = sourceController.EffectiveVisual; + } + + internal static void SetVisualfromParent(Element child) + { + PropagateVisual(child, child.Parent); } } } diff --git a/Xamarin.Forms.Core/Items/ItemsView.cs b/Xamarin.Forms.Core/Items/ItemsView.cs index 708ee7455..8c70cc7fe 100644 --- a/Xamarin.Forms.Core/Items/ItemsView.cs +++ b/Xamarin.Forms.Core/Items/ItemsView.cs @@ -97,8 +97,6 @@ namespace Xamarin.Forms _logicalChildren.Add(element); - PropertyPropagationExtensions.PropagatePropertyChanged(null, element); - element.Parent = this; } diff --git a/Xamarin.Forms.Platform.Android/CollectionView/EmptyViewAdapter.cs b/Xamarin.Forms.Platform.Android/CollectionView/EmptyViewAdapter.cs index a13831b36..72470a1ec 100644 --- a/Xamarin.Forms.Platform.Android/CollectionView/EmptyViewAdapter.cs +++ b/Xamarin.Forms.Platform.Android/CollectionView/EmptyViewAdapter.cs @@ -234,7 +234,7 @@ namespace Xamarin.Forms.Platform.Android } // EmptyView is a Forms View; display that - return SimpleViewHolder.FromFormsView(formsView, context, () => GetWidth(parent), () => GetHeight(parent)); + return SimpleViewHolder.FromFormsView(formsView, context, () => GetWidth(parent), () => GetHeight(parent), ItemsView); } var itemContentView = new SizedItemContentView(parent.Context, () => GetWidth(parent), () => GetHeight(parent)); diff --git a/Xamarin.Forms.Platform.Android/CollectionView/SimpleViewHolder.cs b/Xamarin.Forms.Platform.Android/CollectionView/SimpleViewHolder.cs index 99132282e..3a527f4d1 100644 --- a/Xamarin.Forms.Platform.Android/CollectionView/SimpleViewHolder.cs +++ b/Xamarin.Forms.Platform.Android/CollectionView/SimpleViewHolder.cs @@ -41,10 +41,14 @@ namespace Xamarin.Forms.Platform.Android return new SimpleViewHolder(textView, null); } - public static SimpleViewHolder FromFormsView(View formsView, Context context, Func width, Func height) + public static SimpleViewHolder FromFormsView(View formsView, Context context, Func width, Func height, ItemsView container) { var itemContentControl = new SizedItemContentView(context, width, height); + + // Make sure the Visual property is available during renderer creation + Internals.PropertyPropagationExtensions.PropagatePropertyChanged(null, formsView, container); itemContentControl.RealizeContent(formsView); + return new SimpleViewHolder(itemContentControl, formsView); } diff --git a/Xamarin.Forms.Platform.Android/CollectionView/TemplatedItemViewHolder.cs b/Xamarin.Forms.Platform.Android/CollectionView/TemplatedItemViewHolder.cs index 2d8a729f2..d779af481 100644 --- a/Xamarin.Forms.Platform.Android/CollectionView/TemplatedItemViewHolder.cs +++ b/Xamarin.Forms.Platform.Android/CollectionView/TemplatedItemViewHolder.cs @@ -57,8 +57,12 @@ namespace Xamarin.Forms.Platform.Android // available during OnElementChanged View.BindingContext = itemBindingContext; + // Make sure the Visual property is available when the renderer is created + PropertyPropagationExtensions.PropagatePropertyChanged(null, View, itemsView); + // Actually create the native renderer _itemContentView.RealizeContent(View); + _selectedTemplate = template; } diff --git a/Xamarin.Forms.Platform.iOS/CollectionView/TemplateHelpers.cs b/Xamarin.Forms.Platform.iOS/CollectionView/TemplateHelpers.cs index a65df6848..9220c0ebe 100644 --- a/Xamarin.Forms.Platform.iOS/CollectionView/TemplateHelpers.cs +++ b/Xamarin.Forms.Platform.iOS/CollectionView/TemplateHelpers.cs @@ -31,8 +31,12 @@ namespace Xamarin.Forms.Platform.iOS // We have a template; turn it into a Forms view var templateElement = viewTemplate.CreateContent() as View; - var renderer = CreateRenderer(templateElement); + // Make sure the Visual property is available when the renderer is created + PropertyPropagationExtensions.PropagatePropertyChanged(null, templateElement, itemsView); + + var renderer = CreateRenderer(templateElement); + // and set the EmptyView as its BindingContext BindableObject.SetInheritedBindingContext(renderer.Element, view); @@ -41,6 +45,9 @@ namespace Xamarin.Forms.Platform.iOS if (view is View formsView) { + // Make sure the Visual property is available when the renderer is created + PropertyPropagationExtensions.PropagatePropertyChanged(null, formsView, itemsView); + // No template, and the EmptyView is a Forms view; use that var renderer = CreateRenderer(formsView); From a8bc75dcbfaf46878088d5c9739f15ea7d3b840c Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Mon, 30 Mar 2020 18:16:33 -0600 Subject: [PATCH 3/3] Add equivalent androidx proguard rules (#10138) --- .nuspec/proguard.cfg | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.nuspec/proguard.cfg b/.nuspec/proguard.cfg index deead1817..85ae808c1 100644 --- a/.nuspec/proguard.cfg +++ b/.nuspec/proguard.cfg @@ -1,9 +1,14 @@ -keep class android.support.v7.widget.FitWindowsFrameLayout { *; } -dontwarn android.support.v7.widget.FitWindowsFrameLayout +-keep class androidx.appcompat.widget.FitWindowsFrameLayout { *; } +-dontwarn androidx.appcompat.widget.FitWindowsFrameLayout -keep class android.support.design.** { *; } -keep class android.support.multidex.MultiDexApplication { *; } +-keep class androidx.multidex.MultiDexApplication { *; } -keep class android.support.design.internal.BaselineLayout { *; } -dontwarn android.support.design.internal.BaselineLayout +-keep class com.google.android.material.internal.BaselineLayout { *; } +-dontwarn com.google.android.material.internal.BaselineLayout -keep class com.google.firebase.provider.FirebaseInitProvider { *; } -keep class androidx.appcompat.widget.AlertDialogLayout { *; } -keep class androidx.appcompat.widget.DialogTitle { *; }