Use character truncation in Windows (#321)
Change layout order ViewCells on Windows to correct label length layout issues Add extra layout pass on ViewCell load to make cells without margins visible
This commit is contained in:
Родитель
0bc22bda64
Коммит
1b7250167f
|
@ -0,0 +1,216 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Xamarin.Forms.CustomAttributes;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
namespace Xamarin.Forms.Controls
|
||||
{
|
||||
[Preserve(AllMembers = true)]
|
||||
[Issue(IssueTracker.Bugzilla, 42519, "Text Truncation in UWP")]
|
||||
public class Bugzilla42519 : TestNavigationPage
|
||||
{
|
||||
public static readonly string LongLabelSingle =
|
||||
"longleftlabelthequickbrownfoxjumpedoverthelazydogsthequickbrownfoxjumpedoverthelazydogs";
|
||||
|
||||
public static readonly string LongLabelWords =
|
||||
"long left label the quick brown fox jumped over the lazy dogs the quick brown fox jumped over the lazy dogs";
|
||||
|
||||
protected override void Init()
|
||||
{
|
||||
PushAsync(Menu());
|
||||
}
|
||||
|
||||
static ContentPage CreateContent(Type cellType)
|
||||
{
|
||||
return new ContentPage { Content = CreateListView(new DataTemplate(cellType)) };
|
||||
}
|
||||
|
||||
static ListView CreateListView(DataTemplate template)
|
||||
{
|
||||
var items = new List<_42519Item>
|
||||
{
|
||||
new _42519Item
|
||||
{
|
||||
TitleLeft = LongLabelWords,
|
||||
TitleRight = "32522665",
|
||||
SubLeft = "LeftLabel",
|
||||
SubRight = "Long Right Label"
|
||||
},
|
||||
new _42519Item
|
||||
{
|
||||
TitleLeft = LongLabelSingle,
|
||||
TitleRight = "12552665222",
|
||||
SubLeft = "LeftLabel",
|
||||
SubRight = "Long Right Label"
|
||||
},
|
||||
new _42519Item
|
||||
{
|
||||
TitleLeft = LongLabelSingle,
|
||||
TitleRight = "225565365",
|
||||
SubLeft = "LeftLabel",
|
||||
SubRight = "Long Right Label"
|
||||
},
|
||||
new _42519Item
|
||||
{
|
||||
TitleLeft = LongLabelWords,
|
||||
TitleRight = "215565365",
|
||||
SubLeft = "LeftLabel",
|
||||
SubRight = "Long Right Label"
|
||||
}
|
||||
};
|
||||
|
||||
return new ListView
|
||||
{
|
||||
HasUnevenRows = true,
|
||||
ItemTemplate = template,
|
||||
ItemsSource = items
|
||||
};
|
||||
}
|
||||
|
||||
static ContentPage Menu()
|
||||
{
|
||||
var page = new ContentPage();
|
||||
|
||||
var heading = new Label { Text = "Select an option below to see text tail truncation in various contexts." };
|
||||
|
||||
if (Device.Idiom == TargetIdiom.Phone)
|
||||
{
|
||||
heading.Text += " Rotating the phone between portrait and landscape mode should not cause the ellipsis to disappear from truncated text.";
|
||||
}
|
||||
|
||||
var labelButton = new Button { Text = "Single Label" };
|
||||
var gridButton = new Button { Text = "Single Grid" };
|
||||
var listWithLabelsButton = new Button { Text = "ListView with Label ViewCell" };
|
||||
var listWithGridsButton = new Button { Text = "ListView with Grid ViewCell" };
|
||||
|
||||
labelButton.Clicked += (sender, args) =>
|
||||
{
|
||||
var content = new Label { Text = LongLabelSingle, LineBreakMode = LineBreakMode.TailTruncation };
|
||||
page.Navigation.PushAsync(new ContentPage { Content = content });
|
||||
};
|
||||
|
||||
gridButton.Clicked += (sender, args) =>
|
||||
{
|
||||
var content = new ContentPage
|
||||
{
|
||||
Content = _42519CustomViewCellGrid.CreateGrid(),
|
||||
BindingContext = new _42519Item
|
||||
{
|
||||
TitleLeft = LongLabelSingle,
|
||||
TitleRight = "32522665",
|
||||
SubLeft = "LeftLabel",
|
||||
SubRight = "Long Right Label"
|
||||
}
|
||||
};
|
||||
page.Navigation.PushAsync(content);
|
||||
};
|
||||
|
||||
listWithLabelsButton.Clicked +=
|
||||
(sender, args) => { page.Navigation.PushAsync(CreateContent(typeof(_42519CustomViewCellLabel))); };
|
||||
|
||||
listWithGridsButton.Clicked +=
|
||||
(sender, args) => { page.Navigation.PushAsync(CreateContent(typeof(_42519CustomViewCellGrid))); };
|
||||
|
||||
page.Content = new StackLayout
|
||||
{
|
||||
Children =
|
||||
{
|
||||
heading,
|
||||
labelButton,
|
||||
gridButton,
|
||||
listWithLabelsButton,
|
||||
listWithGridsButton
|
||||
}
|
||||
};
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
[Preserve(AllMembers = true)]
|
||||
internal class _42519Item
|
||||
{
|
||||
public string SubLeft { get; set; }
|
||||
|
||||
public string SubRight { get; set; }
|
||||
|
||||
public string TitleLeft { get; set; }
|
||||
|
||||
public string TitleRight { get; set; }
|
||||
}
|
||||
|
||||
[Preserve(AllMembers = true)]
|
||||
internal class _42519CustomViewCellGrid : ViewCell
|
||||
{
|
||||
public _42519CustomViewCellGrid()
|
||||
{
|
||||
View = CreateGrid();
|
||||
}
|
||||
|
||||
public static Grid CreateGrid()
|
||||
{
|
||||
var grid = new Grid
|
||||
{
|
||||
VerticalOptions = LayoutOptions.FillAndExpand,
|
||||
RowDefinitions =
|
||||
{
|
||||
new RowDefinition { Height = new GridLength(24, GridUnitType.Absolute) },
|
||||
new RowDefinition { Height = new GridLength(24, GridUnitType.Absolute) }
|
||||
},
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) },
|
||||
new ColumnDefinition { Width = GridLength.Auto }
|
||||
},
|
||||
Padding = new Thickness(16, 12, 16, 12)
|
||||
};
|
||||
var leftLabel = new Label
|
||||
{
|
||||
LineBreakMode = LineBreakMode.TailTruncation
|
||||
};
|
||||
leftLabel.SetBinding(Label.TextProperty, "TitleLeft");
|
||||
|
||||
var rightLabel = new Label
|
||||
{
|
||||
FontSize = 20,
|
||||
HorizontalOptions = LayoutOptions.End
|
||||
};
|
||||
rightLabel.SetBinding(Label.TextProperty, "TitleRight");
|
||||
|
||||
var subLeft = new Label
|
||||
{
|
||||
LineBreakMode = LineBreakMode.TailTruncation
|
||||
};
|
||||
subLeft.SetBinding(Label.TextProperty, "SubLeft");
|
||||
|
||||
var subRight = new Label
|
||||
{
|
||||
HorizontalOptions = LayoutOptions.End
|
||||
};
|
||||
subRight.SetBinding(Label.TextProperty, "SubRight");
|
||||
|
||||
grid.Children.Add(leftLabel, 0, 0);
|
||||
grid.Children.Add(rightLabel, 1, 0);
|
||||
grid.Children.Add(subLeft, 0, 1);
|
||||
grid.Children.Add(subRight, 1, 1);
|
||||
|
||||
return grid;
|
||||
}
|
||||
}
|
||||
|
||||
[Preserve(AllMembers = true)]
|
||||
internal class _42519CustomViewCellLabel : ViewCell
|
||||
{
|
||||
public _42519CustomViewCellLabel()
|
||||
{
|
||||
var leftLabel = new Label
|
||||
{
|
||||
LineBreakMode = LineBreakMode.TailTruncation
|
||||
};
|
||||
|
||||
leftLabel.SetBinding(Label.TextProperty, "TitleLeft");
|
||||
|
||||
View = leftLabel;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -122,6 +122,7 @@
|
|||
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla42075.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla42329.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla42364.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla42519.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)CarouselAsync.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla34561.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla34727.cs" />
|
||||
|
|
|
@ -417,7 +417,7 @@ namespace Xamarin.Forms
|
|||
|
||||
bool ShouldLayoutChildren()
|
||||
{
|
||||
if (!LogicalChildrenInternal.Any() || Width <= 0 || Height <= 0 || !IsVisible || !IsNativeStateConsistent || DisableLayout)
|
||||
if (Width <= 0 || Height <= 0 || !LogicalChildrenInternal.Any() || !IsVisible || !IsNativeStateConsistent || DisableLayout)
|
||||
return false;
|
||||
|
||||
foreach (Element element in VisibleDescendants())
|
||||
|
|
|
@ -41,6 +41,7 @@ namespace Xamarin.Forms.Platform.WinPhone
|
|||
{
|
||||
frameworkElement.Loaded += (sender, args) =>
|
||||
{
|
||||
(_view as Layout)?.ForceLayout();
|
||||
((IVisualElementController)_view).InvalidateMeasure(InvalidationTrigger.MeasureChanged);
|
||||
InvalidateMeasure();
|
||||
};
|
||||
|
@ -61,16 +62,22 @@ namespace Xamarin.Forms.Platform.WinPhone
|
|||
protected override System.Windows.Size MeasureOverride(System.Windows.Size availableSize)
|
||||
{
|
||||
var content = Content as FrameworkElement;
|
||||
content?.Measure(availableSize);
|
||||
Size request = _view.Measure(availableSize.Width, availableSize.Height, MeasureFlags.IncludeMargins).Request;
|
||||
|
||||
System.Windows.Size result;
|
||||
if (_view.HorizontalOptions.Alignment == LayoutAlignment.Fill && !double.IsInfinity(availableSize.Width) && availableSize.Width != 0)
|
||||
{
|
||||
result = new System.Windows.Size(availableSize.Width, request.Height);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = new System.Windows.Size(request.Width, request.Height);
|
||||
}
|
||||
|
||||
_view.Layout(new Rectangle(0, 0, result.Width, result.Height));
|
||||
|
||||
content?.Measure(availableSize);
|
||||
|
||||
_view.Layout(new Rectangle(0, 0, result.Width, result.Width));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -165,7 +165,7 @@ namespace Xamarin.Forms.Platform.WinRT
|
|||
textBlock.TextWrapping = TextWrapping.NoWrap;
|
||||
break;
|
||||
case LineBreakMode.TailTruncation:
|
||||
textBlock.TextTrimming = TextTrimming.WordEllipsis;
|
||||
textBlock.TextTrimming = TextTrimming.CharacterEllipsis;
|
||||
textBlock.TextWrapping = TextWrapping.NoWrap;
|
||||
break;
|
||||
case LineBreakMode.MiddleTruncation:
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using Windows.Foundation;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
#if WINDOWS_UWP
|
||||
|
||||
|
@ -41,6 +42,8 @@ namespace Xamarin.Forms.Platform.WinRT
|
|||
{
|
||||
readonly View _view;
|
||||
|
||||
FrameworkElement FrameworkElement => Content as FrameworkElement;
|
||||
|
||||
public WrapperControl(View view)
|
||||
{
|
||||
_view = view;
|
||||
|
@ -54,9 +57,17 @@ namespace Xamarin.Forms.Platform.WinRT
|
|||
Content = renderer.ContainerElement;
|
||||
|
||||
// make sure we re-measure once the template is applied
|
||||
FrameworkElement frameworkElement = renderer.ContainerElement;
|
||||
if (frameworkElement != null)
|
||||
frameworkElement.Loaded += (sender, args) => InvalidateMeasure();
|
||||
if (FrameworkElement != null)
|
||||
{
|
||||
FrameworkElement.Loaded += (sender, args) =>
|
||||
{
|
||||
// If the view is a layout (stacklayout, grid, etc) we need to trigger a layout pass
|
||||
// with all the controls in a consistent native state (i.e., loaded) so they'll actually
|
||||
// have Bounds set
|
||||
(_view as Layout)?.ForceLayout();
|
||||
InvalidateMeasure();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
protected override Windows.Foundation.Size ArrangeOverride(Windows.Foundation.Size finalSize)
|
||||
|
@ -65,18 +76,15 @@ namespace Xamarin.Forms.Platform.WinRT
|
|||
Layout.LayoutChildIntoBoundingRegion(_view, new Rectangle(0, 0, finalSize.Width, finalSize.Height));
|
||||
_view.IsInNativeLayout = false;
|
||||
|
||||
var content = Content as FrameworkElement;
|
||||
content.Arrange(new Rect(_view.X, _view.Y, _view.Width, _view.Height));
|
||||
FrameworkElement?.Arrange(new Rect(_view.X, _view.Y, _view.Width, _view.Height));
|
||||
return finalSize;
|
||||
}
|
||||
|
||||
protected override Windows.Foundation.Size MeasureOverride(Windows.Foundation.Size availableSize)
|
||||
{
|
||||
var content = Content as FrameworkElement;
|
||||
content?.Measure(availableSize);
|
||||
Size request = _view.Measure(availableSize.Width, availableSize.Height, MeasureFlags.IncludeMargins).Request;
|
||||
|
||||
var result = new Windows.Foundation.Size();
|
||||
|
||||
Windows.Foundation.Size result;
|
||||
if (_view.HorizontalOptions.Alignment == LayoutAlignment.Fill && !double.IsInfinity(availableSize.Width) && availableSize.Width != 0)
|
||||
{
|
||||
result = new Windows.Foundation.Size(availableSize.Width, request.Height);
|
||||
|
@ -86,7 +94,10 @@ namespace Xamarin.Forms.Platform.WinRT
|
|||
result = new Windows.Foundation.Size(request.Width, request.Height);
|
||||
}
|
||||
|
||||
_view.Layout(new Rectangle(0, 0, result.Width, result.Width));
|
||||
_view.Layout(new Rectangle(0, 0, result.Width, result.Height));
|
||||
|
||||
FrameworkElement?.Measure(availableSize);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче