【问题标题】:Xamarin forms, RecyclerView, cell rendering from xamlXamarin 表单、RecyclerView、来自 xaml 的单元格渲染
【发布时间】:2017-10-21 18:47:43
【问题描述】:

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

我的问题发生在我尝试创建包含标签或其他控件的单元格时,其 Horizo​​ntalOptions 不同于:Default、Fill 和 FillAndExpand。那些标签不会自己呈现 (Screenshot)。这是我的 .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?

欢迎下载我的sample project

【问题讨论】:

    标签: android android-recyclerview xamarin.forms custom-renderer cellrenderer


    【解决方案1】:

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

    (...) 此外,它指定元素是否应该占用 parent 布局中 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 的核心中实现,并且要正确计算,孩子必须有他们的父母。

    【讨论】:

      【解决方案2】:

      我个人认为这是在Grid 中使用LabelHorizontalOptions 的错误。不确定,您可以尝试在 Bugzilla 中提交此问题。

      默认HorizontalOptions 设置为LayoutOptions.Fill,当此属性默认设置为FillAndExpand 时,它可以工作,其他具有不同HorizontalOptions 的在我身边的宽度为0,这就是为什么只有一些显示您的标签。

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

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

      你这里的宽度应该小于父级这里看到不同LayoutOptions的结果。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-09-24
        • 2018-08-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-24
        相关资源
        最近更新 更多