Merge branch '3.1.0'
This commit is contained in:
Коммит
c22b8b9e0f
|
@ -0,0 +1,43 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Xamarin.Forms.Controls.Issues.Issue2625">
|
||||
<ContentPage.Content>
|
||||
<StackLayout>
|
||||
|
||||
<Label Text="The buttons below should have their background colors set by the VisualStateManager. If they have the default button background color, this test has failed."></Label>
|
||||
|
||||
<Button
|
||||
HorizontalOptions="Center"
|
||||
Text="I should have a Lime background"
|
||||
VerticalOptions="Center">
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="BackgroundColor" Value="Lime" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
HorizontalOptions="Center"
|
||||
Text="I should have a Pink background"
|
||||
IsEnabled="False"
|
||||
VerticalOptions="Center">
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="BackgroundColor" Value="Pink" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Button>
|
||||
|
||||
</StackLayout>
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.CustomAttributes;
|
||||
using Xamarin.Forms.Internals;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace Xamarin.Forms.Controls.Issues
|
||||
{
|
||||
#if APP
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
#endif
|
||||
[Preserve(AllMembers = true)]
|
||||
[Issue(IssueTracker.Github, 2625, "VisualStateManager attached to Button seems to not work on Android", PlatformAffected.Android)]
|
||||
public partial class Issue2625 : ContentPage
|
||||
{
|
||||
public Issue2625 ()
|
||||
{
|
||||
#if APP
|
||||
InitializeComponent ();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
|
@ -307,6 +307,10 @@
|
|||
<Compile Include="$(MSBuildThisFileDirectory)Issue1672.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue2394.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue2595.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue2625.xaml.cs">
|
||||
<DependentUpon>Issue2625.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue2983.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue2963.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue2981.cs" />
|
||||
|
@ -891,4 +895,10 @@
|
|||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue2625.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -76,6 +76,12 @@ namespace Xamarin.Forms.Controls
|
|||
map.MoveToRegion (MapSpan.FromCenterAndRadius (new Position (41.890202, 12.492049), Distance.FromMiles (0.5)));
|
||||
};
|
||||
|
||||
var buttonRemove = new Button { Text = "Remove Pin" };
|
||||
buttonRemove.Clicked += (a, e) =>
|
||||
{
|
||||
map.Pins.RemoveAt(0);
|
||||
};
|
||||
|
||||
_stack = new StackLayout {
|
||||
Spacing = 0,
|
||||
Padding = new Thickness (30, 0)
|
||||
|
@ -114,7 +120,8 @@ namespace Xamarin.Forms.Controls
|
|||
_stack.Children.Add (buttonAddressFromPosition);
|
||||
_stack.Children.Add (buttonHome);
|
||||
_stack.Children.Add (buttonZoomPin);
|
||||
_stack.Children.Add(buttonEditPin);
|
||||
_stack.Children.Add (buttonEditPin);
|
||||
_stack.Children.Add (buttonRemove);
|
||||
|
||||
Content = _stack;
|
||||
}
|
||||
|
@ -159,7 +166,7 @@ namespace Xamarin.Forms.Controls
|
|||
{
|
||||
Pin pin = (Pin)sender;
|
||||
Application.Current.MainPage.DisplayAlert("Pin Click",
|
||||
$"You clicked the {pin.Label} pin, located at {pin.Address}, or coordinates ({pin.Position.Latitude}, {pin.Position.Longitude})",
|
||||
$"You clicked the {pin.Label} pin, located at {pin.Address}, or coordinates ({pin.Position.Latitude}, {pin.Position.Longitude})",
|
||||
"OK");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -212,5 +212,55 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
Assert.That(groups1[0].CurrentState.Name, Is.EqualTo(NormalStateName));
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VisualElementGoesToCorrectStateWhenAvailable()
|
||||
{
|
||||
var label = new Label();
|
||||
double targetBottomMargin = 1.5;
|
||||
|
||||
var group = new VisualStateGroup();
|
||||
var list = new VisualStateGroupList();
|
||||
|
||||
var normalState = new VisualState { Name = NormalStateName };
|
||||
normalState.Setters.Add(new Setter { Property = View.MarginBottomProperty, Value = targetBottomMargin });
|
||||
|
||||
list.Add(group);
|
||||
group.States.Add(normalState);
|
||||
|
||||
VisualStateManager.SetVisualStateGroups(label, list);
|
||||
|
||||
Assert.That(label.Margin.Bottom, Is.EqualTo(targetBottomMargin));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VisualElementGoesToCorrectStateWhenAvailableFromSetter()
|
||||
{
|
||||
double targetBottomMargin = 1.5;
|
||||
|
||||
var group = new VisualStateGroup();
|
||||
var list = new VisualStateGroupList();
|
||||
|
||||
var normalState = new VisualState { Name = NormalStateName };
|
||||
normalState.Setters.Add(new Setter { Property = View.MarginBottomProperty, Value = targetBottomMargin });
|
||||
|
||||
var x = new Setter
|
||||
{
|
||||
Property = VisualStateManager.VisualStateGroupsProperty,
|
||||
Value = list
|
||||
};
|
||||
|
||||
list.Add(group);
|
||||
group.States.Add(normalState);
|
||||
|
||||
var label1 = new Label();
|
||||
var label2 = new Label();
|
||||
|
||||
x.Apply(label1);
|
||||
x.Apply(label2);
|
||||
|
||||
Assert.That(label1.Margin.Bottom, Is.EqualTo(targetBottomMargin));
|
||||
Assert.That(label2.Margin.Bottom, Is.EqualTo(targetBottomMargin));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,11 +19,20 @@ namespace Xamarin.Forms
|
|||
public static readonly BindableProperty VisualStateGroupsProperty =
|
||||
BindableProperty.CreateAttached("VisualStateGroups", typeof(VisualStateGroupList), typeof(VisualElement),
|
||||
defaultValue: null, propertyChanged: VisualStateGroupsPropertyChanged,
|
||||
defaultValueCreator: bindable => new VisualStateGroupList());
|
||||
defaultValueCreator: bindable => new VisualStateGroupList {VisualElement = (VisualElement)bindable});
|
||||
|
||||
static void VisualStateGroupsPropertyChanged(BindableObject bindable, object oldValue, object newValue)
|
||||
{
|
||||
GoToState((VisualElement)bindable, CommonStates.Normal);
|
||||
if (oldValue is VisualStateGroupList oldVisualStateGroupList)
|
||||
{
|
||||
oldVisualStateGroupList.VisualElement = null;
|
||||
}
|
||||
|
||||
var visualElement = (VisualElement)bindable;
|
||||
|
||||
((VisualStateGroupList)newValue).VisualElement = visualElement;
|
||||
|
||||
visualElement.ChangeVisualState();
|
||||
}
|
||||
|
||||
public static IList<VisualStateGroup> GetVisualStateGroups(VisualElement visualElement)
|
||||
|
@ -94,7 +103,7 @@ namespace Xamarin.Forms
|
|||
{
|
||||
readonly IList<VisualStateGroup> _internalList;
|
||||
|
||||
void Validate(IList<VisualStateGroup> groups)
|
||||
static void Validate(IList<VisualStateGroup> groups)
|
||||
{
|
||||
// If we have 1 group, no need to worry about duplicate group names
|
||||
if (groups.Count > 1)
|
||||
|
@ -118,12 +127,18 @@ namespace Xamarin.Forms
|
|||
|
||||
public VisualStateGroupList()
|
||||
{
|
||||
_internalList = new WatchAddList<VisualStateGroup>(Validate);
|
||||
_internalList = new WatchAddList<VisualStateGroup>(ValidateAndNotify);
|
||||
}
|
||||
|
||||
void ValidateOnStatesChanged(object sender, EventArgs eventArgs)
|
||||
void ValidateAndNotify(object sender, EventArgs eventArgs)
|
||||
{
|
||||
Validate(_internalList);
|
||||
ValidateAndNotify(_internalList);
|
||||
}
|
||||
|
||||
void ValidateAndNotify(IList<VisualStateGroup> groups)
|
||||
{
|
||||
Validate(groups);
|
||||
OnStatesChanged();
|
||||
}
|
||||
|
||||
public IEnumerator<VisualStateGroup> GetEnumerator()
|
||||
|
@ -139,14 +154,14 @@ namespace Xamarin.Forms
|
|||
public void Add(VisualStateGroup item)
|
||||
{
|
||||
_internalList.Add(item);
|
||||
item.StatesChanged += ValidateOnStatesChanged;
|
||||
item.StatesChanged += ValidateAndNotify;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
foreach (var group in _internalList)
|
||||
{
|
||||
group.StatesChanged -= ValidateOnStatesChanged;
|
||||
group.StatesChanged -= ValidateAndNotify;
|
||||
}
|
||||
|
||||
_internalList.Clear();
|
||||
|
@ -164,7 +179,7 @@ namespace Xamarin.Forms
|
|||
|
||||
public bool Remove(VisualStateGroup item)
|
||||
{
|
||||
item.StatesChanged -= ValidateOnStatesChanged;
|
||||
item.StatesChanged -= ValidateAndNotify;
|
||||
return _internalList.Remove(item);
|
||||
}
|
||||
|
||||
|
@ -179,13 +194,13 @@ namespace Xamarin.Forms
|
|||
|
||||
public void Insert(int index, VisualStateGroup item)
|
||||
{
|
||||
item.StatesChanged += ValidateOnStatesChanged;
|
||||
item.StatesChanged += ValidateAndNotify;
|
||||
_internalList.Insert(index, item);
|
||||
}
|
||||
|
||||
public void RemoveAt(int index)
|
||||
{
|
||||
_internalList[index].StatesChanged -= ValidateOnStatesChanged;
|
||||
_internalList[index].StatesChanged -= ValidateAndNotify;
|
||||
_internalList.RemoveAt(index);
|
||||
}
|
||||
|
||||
|
@ -194,6 +209,13 @@ namespace Xamarin.Forms
|
|||
get => _internalList[index];
|
||||
set => _internalList[index] = value;
|
||||
}
|
||||
|
||||
internal VisualElement VisualElement { get; set; }
|
||||
|
||||
void OnStatesChanged()
|
||||
{
|
||||
VisualElement?.ChangeVisualState();
|
||||
}
|
||||
}
|
||||
|
||||
[RuntimeNameProperty(nameof(Name))]
|
||||
|
|
|
@ -16,7 +16,7 @@ using Math = System.Math;
|
|||
|
||||
namespace Xamarin.Forms.Maps.Android
|
||||
{
|
||||
public class MapRenderer : ViewRenderer<Map, MapView>, GoogleMap.IOnCameraMoveListener, IOnMapReadyCallback
|
||||
public class MapRenderer : ViewRenderer<Map, MapView>, GoogleMap.IOnCameraMoveListener, IOnMapReadyCallback
|
||||
{
|
||||
const string MoveMessageName = "MapMoveToRegion";
|
||||
|
||||
|
@ -192,31 +192,31 @@ namespace Xamarin.Forms.Maps.Android
|
|||
MoveToRegion(Element.LastMoveToRegion, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected virtual void OnMapReady(GoogleMap map)
|
||||
{
|
||||
if (map == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
map.SetOnCameraMoveListener(this);
|
||||
map.InfoWindowClick += MapOnMarkerClick;
|
||||
|
||||
|
||||
map.UiSettings.ZoomControlsEnabled = Map.HasZoomEnabled;
|
||||
map.UiSettings.ZoomGesturesEnabled = Map.HasZoomEnabled;
|
||||
map.UiSettings.ScrollGesturesEnabled = Map.HasScrollEnabled;
|
||||
map.MyLocationEnabled = map.UiSettings.MyLocationButtonEnabled = Map.IsShowingUser;
|
||||
SetMapType();
|
||||
}
|
||||
|
||||
|
||||
protected virtual MarkerOptions CreateMarker(Pin pin)
|
||||
{
|
||||
var opts = new MarkerOptions();
|
||||
opts.SetPosition(new LatLng(pin.Position.Latitude, pin.Position.Longitude));
|
||||
opts.SetTitle(pin.Label);
|
||||
opts.SetSnippet(pin.Address);
|
||||
|
||||
|
||||
return opts;
|
||||
}
|
||||
|
||||
|
@ -290,7 +290,7 @@ namespace Xamarin.Forms.Maps.Android
|
|||
break;
|
||||
}
|
||||
|
||||
// only consider event handled if a handler is present.
|
||||
// only consider event handled if a handler is present.
|
||||
// Else allow default behavior of displaying an info window.
|
||||
targetPin?.SendTap();
|
||||
}
|
||||
|
@ -373,8 +373,8 @@ namespace Xamarin.Forms.Maps.Android
|
|||
foreach (Pin p in pins)
|
||||
{
|
||||
p.PropertyChanged -= PinOnPropertyChanged;
|
||||
var marker = _markers.FirstOrDefault(m => m.Id == (string)p.Id);
|
||||
|
||||
var marker = _markers.FirstOrDefault(m => (object)m.Id == p.Id);
|
||||
if (marker == null)
|
||||
{
|
||||
continue;
|
||||
|
|
|
@ -247,7 +247,11 @@ namespace Xamarin.Forms.Platform.Android.FastRenderers
|
|||
return;
|
||||
|
||||
Color borderColor = Element.BorderColor;
|
||||
_backgroundDrawable.SetStroke(3, borderColor.IsDefault ? AColor.White : borderColor.ToAndroid());
|
||||
|
||||
if (borderColor.IsDefault)
|
||||
_backgroundDrawable.SetStroke(0, AColor.Transparent);
|
||||
else
|
||||
_backgroundDrawable.SetStroke(3, borderColor.ToAndroid());
|
||||
}
|
||||
|
||||
void UpdateShadow()
|
||||
|
|
|
@ -349,6 +349,18 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
ScrollTo(listProxy.ProxiedEnumerable, listProxy[0], ScrollToPosition.Start, true, true);
|
||||
}
|
||||
|
||||
bool ScrollToItemWithAnimation(ScrollViewer viewer, object item)
|
||||
{
|
||||
var selectorItem = List.ContainerFromItem(item) as Windows.UI.Xaml.Controls.Primitives.SelectorItem;
|
||||
var transform = selectorItem?.TransformToVisual(viewer.Content as UIElement);
|
||||
var position = transform?.TransformPoint(new Windows.Foundation.Point(0, 0));
|
||||
if (!position.HasValue)
|
||||
return false;
|
||||
// scroll with animation
|
||||
viewer.ChangeView(position.Value.X, position.Value.Y, null);
|
||||
return true;
|
||||
}
|
||||
|
||||
#pragma warning disable 1998 // considered for removal
|
||||
async void ScrollTo(object group, object item, ScrollToPosition toPosition, bool shouldAnimate, bool includeGroup = false, bool previouslyFailed = false)
|
||||
#pragma warning restore 1998
|
||||
|
@ -375,6 +387,10 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
object[] t = templatedItems.GetGroup(location.Item1).ItemsSource.Cast<object>().ToArray();
|
||||
object c = t[location.Item2];
|
||||
|
||||
// scroll to desired item with animation
|
||||
if (shouldAnimate && ScrollToItemWithAnimation(viewer, c))
|
||||
return;
|
||||
|
||||
double viewportHeight = viewer.ViewportHeight;
|
||||
|
||||
var semanticLocation = new SemanticZoomLocation { Item = c };
|
||||
|
|
|
@ -96,8 +96,9 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
|
||||
// If the Forms VisualStateManager is in play or the user wants to disable the Forms legacy
|
||||
// color stuff, then the underlying textbox should just use the Forms VSM states
|
||||
_queryTextBox.UseFormsVsm = Element.HasVisualStateGroups()
|
||||
|| !Element.OnThisPlatform().GetIsLegacyColorModeEnabled();
|
||||
if (_queryTextBox != null)
|
||||
_queryTextBox.UseFormsVsm = Element.HasVisualStateGroups()
|
||||
|| !Element.OnThisPlatform().GetIsLegacyColorModeEnabled();
|
||||
}
|
||||
|
||||
void OnQuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs e)
|
||||
|
|
|
@ -48,9 +48,10 @@ using UIKit;
|
|||
[assembly: ExportRenderer(typeof(CarouselPage), typeof(CarouselPageRenderer))]
|
||||
[assembly: ExportRenderer(typeof(Page), typeof(PageRenderer))]
|
||||
[assembly: ExportRenderer(typeof(MasterDetailPage), typeof(PhoneMasterDetailRenderer), UIUserInterfaceIdiom.Phone)]
|
||||
[assembly: ExportRenderer(typeof(MasterDetailPage), typeof(TabletMasterDetailRenderer), UIUserInterfaceIdiom.Pad)]
|
||||
#endif
|
||||
|
||||
[assembly: ExportRenderer(typeof(MasterDetailPage), typeof(TabletMasterDetailRenderer), UIUserInterfaceIdiom.Pad)]
|
||||
|
||||
[assembly: ExportCell(typeof(Cell), typeof(CellRenderer))]
|
||||
[assembly: ExportCell(typeof(ImageCell), typeof(ImageCellRenderer))]
|
||||
[assembly: ExportCell(typeof(EntryCell), typeof(EntryCellRenderer))]
|
||||
|
|
|
@ -113,6 +113,18 @@
|
|||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Entry>
|
||||
|
||||
<Entry x:Name="Button1">
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="BackgroundColor" Value="Lime" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Entry>
|
||||
|
||||
</StackLayout>
|
||||
|
||||
|
|
|
@ -170,6 +170,17 @@ namespace Xamarin.Forms.Xaml.UnitTests
|
|||
Assert.That(normal.Setters.Count, Is.EqualTo(0));
|
||||
Assert.That(disabled.Setters.Count, Is.EqualTo(2));
|
||||
}
|
||||
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public void VisualElementGoesToCorrectStateWhenAvailable(bool useCompiledXaml)
|
||||
{
|
||||
var layout = new VisualStateManagerTests(useCompiledXaml);
|
||||
|
||||
var button = layout.Button1;
|
||||
|
||||
Assert.That(button.BackgroundColor, Is.EqualTo(Color.Lime));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче