为什么 ListView.Header 中的这个标签不能显示所有文本?

Why can't this label in ListView.Header show all text?

Android: 6.0
Xamarin.Forms: 2.1.0.6529

创建一个新的 Xamarin.Forms 项目并粘贴:

class Model
{
    public string Text
    {
        get;
        set;
    }
}

public class App : Application
{
    public App()
    {
        var label = new Label
        {
            BackgroundColor = Color.Yellow,
            Text = genLongText(),
            HeightRequest = 10000, // force height
        };

        var list = new List<Model>();
        for (int i = 0; i < 10; i++)
        {
            list.Add(new Model { Text = i + " list item" });
        }

        var template = new DataTemplate(typeof(TextCell));
        template.SetBinding(TextCell.TextProperty, nameof(Model.Text));

        var listview = new ListView
        {
            Header = label,
            ItemsSource = list,
            ItemTemplate = template,
            BackgroundColor = Color.Blue,
        };

        var content = new ContentPage
        {
            Title = "test",
            Content = listview
        };

        MainPage = new NavigationPage(content);
    }

    private string genLongText()
    {
        var t = " Welcome to Xamarin Forms!\n";
        var s = "";
        for (int i = 0; i < 2000; i++)
        {
            s += i.ToString() + t;
        }
        return s;
    }
}

结果是这样的:

如您所见,文本被裁剪并且只显示前 100 行。标签本身(黄色背景)很好,因为我强制高度很大,否则标签的高度也会是同样的长度

所以,基本上如果你在标签上设置一个很长的文本,它只会展开显示前 100 行,如果你通过 HeightRequest 手动改变它的高度,那么标签会很好,但文本仍然是剪掉了。

这必须与 ListView.Header 实施有关。

在 Android 上,表单的 ListViewandroid.widget.ListView,其中 ListView 的 header 被设置为包含您的选择的 ContainerVisualElement

由于您使用的表单 Label 是 Android TextView,因此 100 行文本是在 Android 小部件 class.尝试通过 Forms 的 ListViewRenderer.cs Container OnMeasure 方法设置高度不会覆盖它。

来自ListViewRenderer.cs

int heightSpec = MeasureSpecFactory.MakeMeasureSpec((int)ctx.ToPixels(request.Request.Height), MeasureSpecMode.Exactly);
_child.ViewGroup.Measure(widthMeasureSpec, heightMeasureSpec);

如果您真的需要在 ListView 中显示那么多文本 Header 无需 创建自定义 ListViewRender 并手动操作该 Container 中 TextView 的 SetLines、SetMinLines 和 SetMaxLines,使用 Forms' Editor(禁用)代替 header 的 VisualElement:

var label = new Editor
{
    BackgroundColor = Color.Yellow,
    Text = genLongText(),
    MinimumHeightRequest = 10000,
    IsEnabled = false
};

您还可以将 header 已禁用 Editor 嵌入 ScrollView 并将其指定为 ListView Header,这样您就可以在其中滚动文本Editor:

var scrollViewHeader = new ScrollView
{
    HeightRequest = 200,
    Content = label
};