[UWP] Attempt to resolve entry on UWP not correctly calculating the correct height when in a scroll view (#8214)
* Core Changes * Recreate Previous Behavior for issue page * Remove Resharper Setting * Fixed control value cache and updated issue instructions * Fix Typo * Add copy of min/max height/width to measure copy * Update Xamarin.Forms.ControlGallery.WindowsUniversal/CustomRenderers.cs Co-Authored-By: Gerald Versluis <github@geraldversluis.nl> * Revert "Remove Resharper Setting" This reverts commit 0f491e40337c01f963f26c29b6f01a304a2e10ee. * Reset dot settings to master Co-authored-by: Gerald Versluis <github@geraldversluis.nl> Co-authored-by: Samantha Houts <samhouts@users.noreply.github.com> fixes #2172 fixes #5711
This commit is contained in:
Родитель
0faabe0d2c
Коммит
b5b99b672e
|
@ -1,5 +1,7 @@
|
|||
using System.ComponentModel;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Input;
|
||||
using Windows.UI.Xaml.Media;
|
||||
|
@ -12,6 +14,8 @@ using Xamarin.Forms.Platform.UWP;
|
|||
[assembly: ExportRenderer(typeof(Issue1683.EntryKeyboardFlags), typeof(EntryRendererKeyboardFlags))]
|
||||
[assembly: ExportRenderer(typeof(Issue1683.EditorKeyboardFlags), typeof(EditorRendererKeyboardFlags))]
|
||||
[assembly: ExportRenderer(typeof(Issue3273.SortableListView), typeof(SortableListViewRenderer))]
|
||||
[assembly: ExportRenderer(typeof(Issue2172OldEntry), typeof(Issue2172OldEntryRenderer))]
|
||||
[assembly: ExportRenderer(typeof(Issue2172OldEditor), typeof(Issue2172OldEditorRenderer))]
|
||||
namespace Xamarin.Forms.ControlGallery.WindowsUniversal
|
||||
{
|
||||
public class EntryRendererKeyboardFlags : EntryRenderer
|
||||
|
@ -163,4 +167,107 @@ namespace Xamarin.Forms.ControlGallery.WindowsUniversal
|
|||
m_Canvas.Children.Add(text);
|
||||
}
|
||||
}
|
||||
|
||||
public class Issue2172OldEntryRenderer : EntryRenderer
|
||||
{
|
||||
public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
|
||||
{
|
||||
if (Children.Count == 0 || Control == null)
|
||||
return new SizeRequest();
|
||||
|
||||
var constraint = new Windows.Foundation.Size(widthConstraint, heightConstraint);
|
||||
FormsTextBox child = Control;
|
||||
|
||||
child.Measure(constraint);
|
||||
var result = new Size(Math.Ceiling(child.DesiredSize.Width), Math.Ceiling(child.DesiredSize.Height));
|
||||
|
||||
return new SizeRequest(result);
|
||||
}
|
||||
}
|
||||
|
||||
public class Issue2172OldEditorRenderer : EditorRenderer
|
||||
{
|
||||
static FormsTextBox _copyOfTextBox;
|
||||
static Windows.Foundation.Size _zeroSize = new Windows.Foundation.Size(0, 0);
|
||||
|
||||
FormsTextBox CreateTextBox()
|
||||
{
|
||||
return new FormsTextBox
|
||||
{
|
||||
AcceptsReturn = true,
|
||||
TextWrapping = TextWrapping.Wrap,
|
||||
Style = Windows.UI.Xaml.Application.Current.Resources["FormsTextBoxStyle"] as Windows.UI.Xaml.Style
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* Purely invalidating the layout as text is added to the TextBox will not cause it to expand.
|
||||
* If the TextBox is set to WordWrap and it is part of the layout it will refuse to Measure itself beyond its established width.
|
||||
* Even giving it infinite constraints will cause it to always set its DesiredSize to the same width but with a vertical growth.
|
||||
* The only way I was able to grow it was by setting layout renderers width explicitly to some value but then it just set its own Width to that Width which is not helpful.
|
||||
* Even vertically it would measure oddly in cases of rapid text changes.
|
||||
* Holding down the backspace key or enter key would cause the final result to be not quite right.
|
||||
* Both of these issues were fixed by just creating a static TextBox that is not part of the layout which let me just measure
|
||||
* the size of the text as it would fit into the TextBox unconstrained and then just return that Size from the GetDesiredSize call.
|
||||
* */
|
||||
Size GetCopyOfSize(FormsTextBox control, Windows.Foundation.Size constraint)
|
||||
{
|
||||
if (_copyOfTextBox == null)
|
||||
{
|
||||
_copyOfTextBox = CreateTextBox();
|
||||
|
||||
// This causes the copy to be initially setup correctly.
|
||||
// I found that if the first measure of this copy occurs with Text then it will just keep defaulting to a measure with no text.
|
||||
_copyOfTextBox.Measure(_zeroSize);
|
||||
}
|
||||
|
||||
_copyOfTextBox.Text = control.Text;
|
||||
_copyOfTextBox.FontSize = control.FontSize;
|
||||
_copyOfTextBox.FontFamily = control.FontFamily;
|
||||
_copyOfTextBox.FontStretch = control.FontStretch;
|
||||
_copyOfTextBox.FontStyle = control.FontStyle;
|
||||
_copyOfTextBox.FontWeight = control.FontWeight;
|
||||
_copyOfTextBox.Margin = control.Margin;
|
||||
_copyOfTextBox.Padding = control.Padding;
|
||||
|
||||
// have to reset the measure to zero before it will re-measure itself
|
||||
_copyOfTextBox.Measure(_zeroSize);
|
||||
_copyOfTextBox.Measure(constraint);
|
||||
|
||||
Size result = new Size
|
||||
(
|
||||
Math.Ceiling(_copyOfTextBox.DesiredSize.Width),
|
||||
Math.Ceiling(_copyOfTextBox.DesiredSize.Height)
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
SizeRequest CalculateDesiredSizes(FormsTextBox control, Windows.Foundation.Size constraint, EditorAutoSizeOption sizeOption)
|
||||
{
|
||||
if (sizeOption == EditorAutoSizeOption.TextChanges)
|
||||
{
|
||||
Size result = GetCopyOfSize(control, constraint);
|
||||
control.Measure(constraint);
|
||||
return new SizeRequest(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
control.Measure(constraint);
|
||||
Size result = new Size(Math.Ceiling(control.DesiredSize.Width), Math.Ceiling(control.DesiredSize.Height));
|
||||
return new SizeRequest(result);
|
||||
}
|
||||
}
|
||||
|
||||
public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
|
||||
{
|
||||
FormsTextBox child = Control;
|
||||
|
||||
if (Children.Count == 0 || child == null)
|
||||
return new SizeRequest();
|
||||
|
||||
return CalculateDesiredSizes(child, new Windows.Foundation.Size(widthConstraint, heightConstraint), Element.AutoSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage
|
||||
xmlns:controls="clr-namespace:Xamarin.Forms.Controls"
|
||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:issues="clr-namespace:Xamarin.Forms.Controls.Issues"
|
||||
mc:Ignorable="d"
|
||||
x:Class="Xamarin.Forms.Controls.Issues.Issue2172">
|
||||
<ContentPage.Content>
|
||||
<StackLayout>
|
||||
<Label FontSize="25" Text="Using new measure code, no text should be clipped"></Label>
|
||||
<ScrollView VerticalScrollBarVisibility="Always">
|
||||
<Grid BackgroundColor="Green" Padding="5">
|
||||
<StackLayout>
|
||||
<StackLayout>
|
||||
<Entry FontSize="30" Text="{Binding Number}" />
|
||||
<Entry FontSize="25" Text="Nested" />
|
||||
<Entry FontSize="25" />
|
||||
<Label FontSize="25" Text="Label"/>
|
||||
<Editor FontSize="25" Text="Editor"></Editor>
|
||||
<Editor FontSize="25" Text="Auto Size Editor, add more lines to test." AutoSize="TextChanges"></Editor>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</Grid>
|
||||
</ScrollView>
|
||||
|
||||
<BoxView HeightRequest="10" Color="Black"></BoxView>
|
||||
|
||||
<Label FontSize="25" Text="Using old measure code, some text should be clipped. Don't resize the window."></Label>
|
||||
<ScrollView VerticalScrollBarVisibility="Always">
|
||||
<Grid BackgroundColor="Red" Padding="5">
|
||||
<StackLayout>
|
||||
<StackLayout>
|
||||
<issues:Issue2172OldEntry FontSize="30" Text="{Binding Number}" />
|
||||
<issues:Issue2172OldEntry FontSize="25" Text="Nested" />
|
||||
<issues:Issue2172OldEntry FontSize="25" />
|
||||
<Label FontSize="25" Text="Label"/>
|
||||
<issues:Issue2172OldEditor FontSize="25" Text="Editor"></issues:Issue2172OldEditor>
|
||||
<issues:Issue2172OldEditor FontSize="25" Text="Auto Size Editor, add more lines to test." AutoSize="TextChanges"></issues:Issue2172OldEditor>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</Grid>
|
||||
</ScrollView>
|
||||
</StackLayout>
|
||||
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
|
@ -0,0 +1,33 @@
|
|||
using Xamarin.Forms.CustomAttributes;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
namespace Xamarin.Forms.Controls.Issues
|
||||
{
|
||||
[Preserve(AllMembers = true)]
|
||||
[Issue(IssueTracker.Github, 2172, "Height of Entry with data binding incorrect on UWP when Entry in ScrollView in Grid", PlatformAffected.UWP)]
|
||||
public partial class Issue2172 : ContentPage
|
||||
{
|
||||
public Issue2172()
|
||||
{
|
||||
#if APP
|
||||
InitializeComponent();
|
||||
#endif
|
||||
BindingContext = new Issue2172ViewModel();
|
||||
}
|
||||
|
||||
public class Issue2172ViewModel
|
||||
{
|
||||
public string Number => "Bound Text";
|
||||
}
|
||||
}
|
||||
|
||||
public class Issue2172OldEntry : Entry
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class Issue2172OldEditor : Editor
|
||||
{
|
||||
|
||||
}
|
||||
}
|
|
@ -36,6 +36,10 @@
|
|||
</Compile>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue7773.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue8186.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue2172.xaml.cs">
|
||||
<DependentUpon>Issue2172.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue3475.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue5749.xaml.cs">
|
||||
<SubType>Code</SubType>
|
||||
|
@ -1763,4 +1767,10 @@
|
|||
<Generator>MSBuild:Compile</Generator>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue2172.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -12,8 +12,6 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
{
|
||||
public class EditorRenderer : ViewRenderer<Editor, FormsTextBox>
|
||||
{
|
||||
private static FormsTextBox _copyOfTextBox;
|
||||
static Windows.Foundation.Size _zeroSize = new Windows.Foundation.Size(0, 0);
|
||||
bool _fontApplied;
|
||||
Brush _backgroundColorFocusedDefaultBrush;
|
||||
Brush _textDefaultBrush;
|
||||
|
@ -179,65 +177,6 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
Element.SetValueCore(Editor.TextProperty, Control.Text);
|
||||
}
|
||||
|
||||
/*
|
||||
* Purely invalidating the layout as text is added to the TextBox will not cause it to expand.
|
||||
* If the TextBox is set to WordWrap and it is part of the layout it will refuse to Measure itself beyond its established width.
|
||||
* Even giving it infinite constraints will cause it to always set its DesiredSize to the same width but with a vertical growth.
|
||||
* The only way I was able to grow it was by setting layout renderers width explicitly to some value but then it just set its own Width to that Width which is not helpful.
|
||||
* Even vertically it would measure oddly in cases of rapid text changes.
|
||||
* Holding down the backspace key or enter key would cause the final result to be not quite right.
|
||||
* Both of these issues were fixed by just creating a static TextBox that is not part of the layout which let me just measure
|
||||
* the size of the text as it would fit into the TextBox unconstrained and then just return that Size from the GetDesiredSize call.
|
||||
* */
|
||||
Size GetCopyOfSize(FormsTextBox control, Windows.Foundation.Size constraint)
|
||||
{
|
||||
if (_copyOfTextBox == null)
|
||||
{
|
||||
_copyOfTextBox = CreateTextBox();
|
||||
|
||||
// This causes the copy to be initially setup correctly.
|
||||
// I found that if the first measure of this copy occurs with Text then it will just keep defaulting to a measure with no text.
|
||||
_copyOfTextBox.Measure(_zeroSize);
|
||||
}
|
||||
|
||||
_copyOfTextBox.Text = control.Text;
|
||||
_copyOfTextBox.FontSize = control.FontSize;
|
||||
_copyOfTextBox.FontFamily = control.FontFamily;
|
||||
_copyOfTextBox.FontStretch = control.FontStretch;
|
||||
_copyOfTextBox.FontStyle = control.FontStyle;
|
||||
_copyOfTextBox.FontWeight = control.FontWeight;
|
||||
_copyOfTextBox.Margin = control.Margin;
|
||||
_copyOfTextBox.Padding = control.Padding;
|
||||
|
||||
// have to reset the measure to zero before it will re-measure itself
|
||||
_copyOfTextBox.Measure(_zeroSize);
|
||||
_copyOfTextBox.Measure(constraint);
|
||||
|
||||
Size result = new Size
|
||||
(
|
||||
Math.Ceiling(_copyOfTextBox.DesiredSize.Width),
|
||||
Math.Ceiling(_copyOfTextBox.DesiredSize.Height)
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
SizeRequest CalculateDesiredSizes(FormsTextBox control, Windows.Foundation.Size constraint, EditorAutoSizeOption sizeOption)
|
||||
{
|
||||
if (sizeOption == EditorAutoSizeOption.TextChanges)
|
||||
{
|
||||
Size result = GetCopyOfSize(control, constraint);
|
||||
control.Measure(constraint);
|
||||
return new SizeRequest(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
control.Measure(constraint);
|
||||
Size result = new Size(Math.Ceiling(control.DesiredSize.Width), Math.Ceiling(control.DesiredSize.Height));
|
||||
return new SizeRequest(result);
|
||||
}
|
||||
}
|
||||
|
||||
public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
|
||||
{
|
||||
|
@ -246,7 +185,10 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
if (Children.Count == 0 || child == null)
|
||||
return new SizeRequest();
|
||||
|
||||
return CalculateDesiredSizes(child, new Windows.Foundation.Size(widthConstraint, heightConstraint), Element.AutoSize);
|
||||
var constraint = new Windows.Foundation.Size(widthConstraint, heightConstraint);
|
||||
child.Measure(constraint);
|
||||
var result = FormsTextBox.GetCopyOfSize(child, constraint);
|
||||
return new SizeRequest(result);
|
||||
}
|
||||
|
||||
void UpdateFont()
|
||||
|
|
|
@ -457,5 +457,18 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
{
|
||||
Control.IsReadOnly = Element.IsReadOnly;
|
||||
}
|
||||
|
||||
public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
|
||||
{
|
||||
FormsTextBox child = Control;
|
||||
|
||||
if (Children.Count == 0 || child == null)
|
||||
return new SizeRequest();
|
||||
|
||||
var constraint = new Windows.Foundation.Size(widthConstraint, heightConstraint);
|
||||
child.Measure(constraint);
|
||||
var result = FormsTextBox.GetCopyOfSize(child, constraint);
|
||||
return new SizeRequest(result);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -403,5 +403,62 @@ namespace Xamarin.Forms.Platform.UWP
|
|||
WVisualStateManager.GoToState(this, state, true);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This was originally in the EditorRenderer, moved here to be shared with the entry renderer.
|
||||
* It also needs to always be applied to the size calculation, not just when the box size could change.
|
||||
*
|
||||
* Purely invalidating the layout as text is added to the TextBox will not cause it to expand.
|
||||
* If the TextBox is set to WordWrap and it is part of the layout it will refuse to Measure itself beyond its established width.
|
||||
* Even giving it infinite constraints will cause it to always set its DesiredSize to the same width but with a vertical growth.
|
||||
* The only way I was able to grow it was by setting layout renderers width explicitly to some value but then it just set its own Width to that Width which is not helpful.
|
||||
* Even vertically it would measure oddly in cases of rapid text changes.
|
||||
* Holding down the backspace key or enter key would cause the final result to be not quite right.
|
||||
* Both of these issues were fixed by just creating a static TextBox that is not part of the layout which let me just measure
|
||||
* the size of the text as it would fit into the TextBox unconstrained and then just return that Size from the GetDesiredSize call.
|
||||
* */
|
||||
static FormsTextBox _copyOfTextBox;
|
||||
static readonly Windows.Foundation.Size _zeroSize = new Windows.Foundation.Size(0, 0);
|
||||
public static Size GetCopyOfSize(FormsTextBox control, Windows.Foundation.Size constraint)
|
||||
{
|
||||
if (_copyOfTextBox == null)
|
||||
{
|
||||
_copyOfTextBox = new FormsTextBox
|
||||
{
|
||||
Style = Windows.UI.Xaml.Application.Current.Resources["FormsTextBoxStyle"] as Windows.UI.Xaml.Style
|
||||
};
|
||||
|
||||
// This causes the copy to be initially setup correctly.
|
||||
// I found that if the first measure of this copy occurs with Text then it will just keep defaulting to a measure with no text.
|
||||
_copyOfTextBox.Measure(_zeroSize);
|
||||
}
|
||||
|
||||
_copyOfTextBox.MinHeight = control.MinHeight;
|
||||
_copyOfTextBox.MaxHeight = control.MaxHeight;
|
||||
_copyOfTextBox.MinWidth = control.MinWidth;
|
||||
_copyOfTextBox.MaxWidth = control.MaxWidth;
|
||||
_copyOfTextBox.TextWrapping = control.TextWrapping;
|
||||
_copyOfTextBox.AcceptsReturn = control.AcceptsReturn;
|
||||
_copyOfTextBox.Text = control.Text;
|
||||
_copyOfTextBox.FontSize = control.FontSize;
|
||||
_copyOfTextBox.FontFamily = control.FontFamily;
|
||||
_copyOfTextBox.FontStretch = control.FontStretch;
|
||||
_copyOfTextBox.FontStyle = control.FontStyle;
|
||||
_copyOfTextBox.FontWeight = control.FontWeight;
|
||||
_copyOfTextBox.Margin = control.Margin;
|
||||
_copyOfTextBox.Padding = control.Padding;
|
||||
|
||||
// have to reset the measure to zero before it will re-measure itself
|
||||
_copyOfTextBox.Measure(_zeroSize);
|
||||
_copyOfTextBox.Measure(constraint);
|
||||
|
||||
var result = new Size
|
||||
(
|
||||
Math.Ceiling(_copyOfTextBox.DesiredSize.Width),
|
||||
Math.Ceiling(_copyOfTextBox.DesiredSize.Height)
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче