0

我想在使用原生 android RecyclerView 作为渲染器的 Xamarin.Forms 中创建控件。

当我尝试创建包含标签或其他控件的单元格时,我的问题发生了,其 Horizo​​ntalOptions 不同于:Default、Fill 和 FillAndExpand。该标签只是不呈现自己(截图)。这是我的 .xaml 单元格代码

<?xml version="1.0" encoding="utf-8" ?>
<self:FormsRecyclerCell xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:self="clr-namespace:FormsRecyclerViewApp;assembly:FormsRecyclerViewApp" x:Class="FormsRecyclerViewApp.FormsRecyclerCellTemplate">
  <Grid>
    <Label Grid.Row="0" Text="{Binding .}" BackgroundColor="Blue" />
    <Label Grid.Row="1" HorizontalOptions="Start" Text="Horizontal Start"  BackgroundColor="AliceBlue"/>
    <Label Grid.Row="2" HorizontalOptions="StartAndExpand" Text="Horizontal StartAndExpand" BackgroundColor="AliceBlue" />
    <Label Grid.Row="3" HorizontalOptions="Fill" Text="Horizontal Fill" BackgroundColor="Aqua" />
    <Label Grid.Row="4" HorizontalOptions="FillAndExpand" Text="Horizontal FillAndExpand" BackgroundColor="Aqua" />
    <Label Grid.Row="5" HorizontalOptions="Center" Text="Horizontal Center" BackgroundColor="Bisque" />
    <Label Grid.Row="6" HorizontalOptions="CenterAndExpand" Text="Horizontal CenterAndExpand" BackgroundColor="Bisque" />
    <Label Grid.Row="7" HorizontalOptions="End" Text="Horizontal End" BackgroundColor="BlanchedAlmond" />
    <Label Grid.Row="8" HorizontalOptions="EndAndExpand" Text="Horizontal EndAndExpand" BackgroundColor="BlanchedAlmond" />
    <Label Grid.Row="9" Text="Horizontal Default" BackgroundColor="Azure"/>
    <BoxView Grid.Row="10" BackgroundColor="Green" />
  </Grid>
</self:FormsRecyclerCell>

为了在 RecyclerView 中渲染东西,我使用 CellContainer 创建 PlatformRenderer 并覆盖方法 OnLayout 和 OnMeasure

FormsRecyclerViewCellContainer.cs

 protected override void OnLayout(bool changed, int l, int t, int r, int b)
    {
        using (var handler = new Handler(Looper.MainLooper))
        {
            handler.Post(() =>
            {
                double width = Context.FromPixels(r - l);
                double height = Context.FromPixels(b - t);

                Xamarin.Forms.Layout.LayoutChildIntoBoundingRegion(this.view.Element, new XForms.Rectangle(0, 0, width, height));
                this.view.UpdateLayout();
            });
        }
    }

    protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        if (this.view == null || this.view.Element == null)
        {
            base.SetMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
            return;
        }

        XForms.SizeRequest measure = this.view.Element.Measure(this.initialWidth, double.PositiveInfinity, XForms.MeasureFlags.IncludeMargins);
        int height = (int)Context.ToPixels(this.fastCell.Height > 0 ? this.fastCell.Height : measure.Request.Height);
        this.SetMeasuredDimension((int)Context.ToPixels(this.initialWidth), height);
    }

我的问题:
- 从表单 .xaml 获取本机对象的最佳方法是什么?
- 为什么有些标签不呈现自己?
- 我应该怎么做才能正确渲染所有 VisualElemts?

随意下载我的示例项目

4

2 回答 2

1

我找到了答案。我的问题确实与 Horizo​​ntalOptions 有关,您的注释很有用。

(...) 此外,它还指定元素是否应占用布局中 X 轴上的剩余空间。(...)

我刚刚将父级添加到我的 viewHolder 的 XF 版本。在这里你可以看到我改变了什么:

public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
    {
        FormsRecyclerCell fastCell;

        fastCell = this.Element.ItemTemplate.CreateContent() as FormsRecyclerCell;

        var view = new FormsRecyclerViewCellContainer(parent.Context, fastCell, parent, this.Element.ItemWidth, this.Element);
        if (this.SelectionEnabled)
        {
            view.Click += MainView_Click;
        }

        //--------------**-----------------
        //Here i added XF parent to XF cell
        fastCell.Parent = this.Element;

        var dpW = this.ConvertDpToPixels(this.Element.ItemWidth);
        var dpH = this.ConvertDpToPixels(this.Element.ItemHeight);
        view.SetMinimumWidth(dpW);
        view.SetMinimumHeight(dpH);
        view.LayoutParameters = new GridLayoutManager.LayoutParams(dpW, GridLayoutManager.LayoutParams.WrapContent);
        return new FormsRecyclerViewCell(view);
    }

这只是 1 行代码,现在标签与 Horizo​​ntalOptions 的每个设置都完美配合。这很难找到,因为原生(android) ViewHolder 有原生父级,所以我认为 XF VievHolder 立即获得相同的父级,但与 XF 版本(来自渲染器)相同。我弄错了,我必须自己设置。

我现在知道,来自 .xaml 的所有计算都在 Xamarin.Forms 的核心中实现,并且要正确计算孩子必须有他们的父母。

于 2017-05-24T09:04:16.187 回答
0

我个人认为这是HorizontalOptions一个LabelGrid. 不确定,您可以尝试在 Bugzilla 中提交此问题。

默认情况下, Horizo​​ntalOptions设置为LayoutOptions.Fill,当此属性默认设置为 时,它起作用FillAndExpand,其他不同HorizontalOptions的在我身边的宽度为 0,这就是为什么只显示一些标签的原因。

解决此问题的一种解决方法是WidthRequest为这些标签提供 0 宽度,但请注意

当父布局沿 X 轴有多余的可用空间时,分配 Horizo​​ntalOptions 会修改元素的布局方式。此外,它指定元素是否应该消耗父布局中 X 轴上的剩余空间。如果布局的多个子级设置为展开,则额外空间按比例分配。

你这里的宽度应该比父级这里的要小才能看到不同的结果LayoutOptions

于 2017-05-23T09:47:40.333 回答