Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Xamarin表单iOS自定义UITableViewCell动态高度_C#_Ios_Xamarin.forms - Fatal编程技术网

C# Xamarin表单iOS自定义UITableViewCell动态高度

C# Xamarin表单iOS自定义UITableViewCell动态高度,c#,ios,xamarin.forms,C#,Ios,Xamarin.forms,我正在尝试为Xamarin表单创建自定义UITableViewCell,它将根据包含的文本自动调整其高度 我已经找到了通过Designer制作的解决方案,但我需要在代码中这样做 这是我在分析Designer解决方案后得到的结果,但它不起作用: public class FormLabelCellView : UITableViewCell, INativeElementView { public UILabel Label { get; private set; } public

我正在尝试为Xamarin表单创建自定义UITableViewCell,它将根据包含的文本自动调整其高度

我已经找到了通过Designer制作的解决方案,但我需要在代码中这样做

这是我在分析Designer解决方案后得到的结果,但它不起作用:

public class FormLabelCellView : UITableViewCell, INativeElementView
{
    public UILabel Label { get; private set; }
    public FormLabelCell Cell { get; set; }
    public Element Element => Cell;

    public FormLabelCellView(FormLabelCell cell) : base(UITableViewCellStyle.Default, cell.GetType().FullName)
    {
        Cell = cell;
        // in the custom ContentView solution I can't set the cell to expand and contract according to the text it contains
        Label = new UILabel();

        Label.TranslatesAutoresizingMaskIntoConstraints = false;
        Label.SetContentCompressionResistancePriority(751, UILayoutConstraintAxis.Vertical);
        Label.SetContentHuggingPriority(251, UILayoutConstraintAxis.Vertical);

        this.ContentView.AddSubview(Label);

        this.ContentView.AddConstraint(NSLayoutConstraint.Create(Label, NSLayoutAttribute.Left, NSLayoutRelation.Equal, this.ContentView, NSLayoutAttribute.Left, 1, 0));
        this.ContentView.AddConstraint(NSLayoutConstraint.Create(Label, NSLayoutAttribute.Right, NSLayoutRelation.Equal, this.ContentView, NSLayoutAttribute.Right, 1, 0));
        this.ContentView.AddConstraint(NSLayoutConstraint.Create(Label, NSLayoutAttribute.Top, NSLayoutRelation.Equal, this.ContentView, NSLayoutAttribute.Top, 1, 0));
        this.ContentView.AddConstraint(NSLayoutConstraint.Create(Label, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, this.ContentView, NSLayoutAttribute.Bottom, 1, 0));
    }
}
这是结果(行高可能是默认的行高44):

在任何人询问赛艇高度和估计高度之前。是,我已设置行高=UITableView.AutomaticDimension估计值为24在我的自定义ListViewRenderer中

当我将自定义UITableViewCell修改为以下内容时,我还可以验证它是否有效:

public class FormLabelCellView : UITableViewCell, INativeElementView
{
    public UILabel Label { get; private set; }
    public FormLabelCell Cell { get; set; }
    public Element Element => Cell;

    public FormLabelCellView(FormLabelCell cell) : base(UITableViewCellStyle.Default, cell.GetType().FullName)
    {
        Cell = cell;
        // this solution works, but I can't remove the margins / padding and set background color
        Label = this.TextLabel;
    }
}
结果如下所示:

我认为我没有正确地创建约束。有人能帮我吗


编辑:在尝试为测试目的创建自定义UITableViewSource后,我发现问题出在ListViewDataSourceListViewDataSource的Xamarin实现中。这是不幸的,因为这些类是内部类,所以我无法扩展它们并重写GetHeightForRow函数。

在我的测试中,如果我设置
RowHeight=UITableView.AutomaticDimension和<代码>估计值为24在listViewRenderer中,我将获得与您显示的相同的效果:TableView的行高似乎相等

但当我尝试使用另一种方法时:在tableView的源代码中使用override方法,如:

public override nfloat GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
{
    return UITableView.AutomaticDimension;
}

public override nfloat EstimatedHeight(UITableView tableView, NSIndexPath indexPath)
{
    return 24;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
    MyListViewCell cell = tableView.DequeueReusableCell("Cell") as MyListViewCell;

    if (cell == null)
    {
        cell = new MyListViewCell(new NSString("Cell"));
    }

    //Update your data

    return Cell;
}
它工作正常(单元格将在运行时自动调整其行高)

此外,我真的建议您使用此方法来构建单元格:

public MyListViewCell(NSString cellId) : base(UITableViewCellStyle.Default, cellId)
{
     //add your controls in the cell's ContentView
}
然后我们可以在源代码中使用它,如:

public override nfloat GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
{
    return UITableView.AutomaticDimension;
}

public override nfloat EstimatedHeight(UITableView tableView, NSIndexPath indexPath)
{
    return 24;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
    MyListViewCell cell = tableView.DequeueReusableCell("Cell") as MyListViewCell;

    if (cell == null)
    {
        cell = new MyListViewCell(new NSString("Cell"));
    }

    //Update your data

    return Cell;
}
当我调用
cell.SetUpCell()
时,我在上面演示的构造函数内部实例化的
participantnamelab
上得到一个空引用

public MyListViewCell(NSString cellId) : base(UITableViewCellStyle.Default, cellId)
{
     //add your controls in the cell's ContentView
}
如果我把实例化放在下面的构造函数中,我就不会得到这个空引用

public PeopleCell(IntPtr handle) : base(handle)
        {
        }

我遗漏了什么?

因此,请回答我自己的问题。问题在于Xamarin实现内部类ListViewDataSourceListViewDataSource。因为我们不能扩展这些类,所以ListView中的动态行高有两种可能的解决方案

  • 创建自己的UITableViewSource实现
  • 使用ViewCell创建自定义单元格
  • 我使用了第二个选项,因为我正在做多平台应用程序,我不想创建复杂的UITableViewSource实现

    这是自定义ViewCell的示例实现:

    public class CustomLabelCell : ViewCell
    {
        private Label label;
    
        public static readonly BindableProperty TextProperty = BindableProperty.Create("Text", typeof(string), typeof(CustomLabelCell), null);
    
        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }
    
        // disable public set on View property
        public new View View
        {
            get { return base.View; }
            private set { base.View = value; }
        }
    
        public CustomLabelCell()
        {
            this.label = new Label()
            {
                Text = this.Text
            };
            ContentView frame = new ContentView()
            {
                Padding = new Thickness(4.0),
                Content = label
            };
            this.View = frame;
        }
    
        protected override void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            base.OnPropertyChanged(propertyName);
    
            if (propertyName == TextProperty.PropertyName)
            {
                this.label.Text = this.Text;
                ForceUpdateSize();
            }
        }
    }
    
    下面是在ListView中使用它的方式:

    ListView listView = new ListView(ListViewCachingStrategy.RecycleElement)
    {
        HasUnevenRows = true,
        ItemsSource = new ObservableCollection<TestObj> { new TestObj("one - example text that will reach s e c o n d row"), new TestObj("two"), new TestObj("three - longer example text with more words for third row that will span across three rows"), new TestObj("four"), new TestObj("five") },
        ItemTemplate = new DataTemplate(typeof(CustomLabelCell))
    };
    listView.ItemTemplate.SetBinding(CustomLabelCell.TextProperty, "Name");
    

    正如您所见,没有必要在特定于平台的代码中创建自定义渲染器和自定义单元格。

    可能是VisualStudio或symulator的问题。我对iOS上的自定义渲染器有问题。直到我重新启动VS和模拟器,它才开始工作。不幸的是,没有。我为此挣扎了很长一段时间。我尝试了很多东西,但没有任何东西能给我想要的结果。我想我一定是做错了什么,但我不知道是什么。我没有提到这一点,但我没有使用自定义UITableViewSource。我使用的是xamarin在ListView中填充ItemsSource属性时创建的默认数据源。我只想扩展默认的ListView,而不是重新创建已经存在的所有功能。但我尝试了你的建议,创建了非常基本的自定义UITableViewSource,它很管用。另外,我也不必重写GetHeightForRow并估计其正确工作的高度。也许您应该发布PeopleCell类的实现,这样我们就可以看到问题所在。我放弃了创建自定义UITableViewCell和自定义UITableViewSource的方法,而是使用ViewCell创建自定义单元格。