【问题标题】:Height Button in iOS (Xamarin Forms) dont resize when text label wrap word (I want dynamic size)iOS(Xamarin Forms)中的高度按钮在文本标签换行时不调整大小(我想要动态大小)
【发布时间】:2026-02-20 05:05:02
【问题描述】:

我在 Xamarin.Forms 中有一个这样的 ListView:

        this.listView = new ListView();
        this.listView.HasUnevenRows = true;
        var dataTemplate = new DataTemplate(() =>
        {
            return new ViewCell { View = new CustomButtonTemplate()};
        });
        this.listView.ItemTemplate = dataTemplate;

CustomButtonTemplate.xaml

<local:CustomButton
        Margin="6"
        Padding="0"
        HeightRequest="-1"
        WidthRequest="-1"
        Style="{StaticResource Title_LabelStyle}"
        Text="{Binding DisplayText}" />

我也有一个按钮渲染器,但不起作用(没有 HeightRequest、WidthRequest、Padding 也不起作用):

[assembly: ExportRenderer(typeof(CustomButton), typeof(CustomButtonMultilineRenderer))]

namespace SGUK.ClassAction.IOS.Renderers
{
    public class CustomButtonMultilineRenderer : ButtonRenderer
    {
        public CustomButtonMultilineRenderer()
        {
        }

        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
        {
            base.OnElementChanged(e);

            if (this.Control != null)
            {
                this.Control.TitleLabel.LineBreakMode = UILineBreakMode.WordWrap;
                this.Control.TitleEdgeInsets = new UIEdgeInsets(0, 10, 0, 10);
                this.Control.TitleLabel.TextAlignment = UITextAlignment.Center;
                this.Control.HorizontalAlignment = UIControlContentHorizontalAlignment.Center;
            }
        }
    }
}

(使用 MaterialButtonRenderer 也不起作用)

【问题讨论】:

    标签: xamarin.forms xamarin.ios height word-wrap


    【解决方案1】:

    如果不使用自定义渲染器,HasUnevenRows=true 的自动高度在 iOS 上可以正常工作。如果使用自定义渲染器,则由渲染器设置单元格的高度,您必须在自定义渲染器中的GetHeightForRow方法中计算自己的行高。

    [assembly: ExportRenderer(typeof(ListView), typeof(MyLVRenderer))]
    namespace App79.iOS
    {
    public class MyLVRenderer : ListViewRenderer
        {
            //UITableViewSource originalSource;
    
            protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
            {
                base.OnElementChanged(e);
    
                UITableViewSource originalSource = (UIKit.UITableViewSource)Control.Source;
                Control.Source = new MyLVSource(originalSource, e.NewElement);
    
            }
        }
    
        public class MyLVSource : UITableViewSource
        {
            UITableViewSource originalSource;
    
            ListView myListView;
    
    
            public MyLVSource(UITableViewSource origSource, ListView myListV)
            {
                originalSource = origSource;
                myListView = myListV;
            }
    
            public override nint RowsInSection(UITableView tableview, nint section)
            {
                return originalSource.RowsInSection(tableview, section);
            }
    
            public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
            {
                return originalSource.GetCell(tableView, indexPath);
            }
    
            public override nfloat GetHeightForFooter(UITableView tableView, nint section)
            {
                return originalSource.GetHeightForFooter(tableView, section);
            }
    
            public override nfloat GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
            {
                nfloat origHeight = originalSource.GetHeightForRow(tableView, indexPath);
    
                // calculate your own row height here
    
                ObservableCollection<Employee> employees = myListView.ItemsSource as ObservableCollection<Employee>;
    
                string displayName = employees[indexPath.Row].DisplayName;
    
                nfloat height = MeasureTextSize(displayName,UIScreen.MainScreen.Bounds.Size.Width-50,UIFont.SystemFontSize,null);
    
                return height;
            }
    
            public nfloat MeasureTextSize(string text, double width, double fontSize, string fontName = null)
            {
                var nsText = new NSString(text);
                var boundSize = new SizeF((float)width, float.MaxValue);
                var options = NSStringDrawingOptions.UsesFontLeading | NSStringDrawingOptions.UsesLineFragmentOrigin;
    
                if (fontName == null)
                {
                    fontName = "HelveticaNeue";
                }
    
                var attributes = new UIStringAttributes
                {
                    Font = UIFont.FromName(fontName, (float)fontSize)
                };
    
                var sizeF = nsText.GetBoundingRect(boundSize, options, attributes, null).Size;
    
                //return new Xamarin.Forms.Size((double)sizeF.Width, (double)sizeF.Height);
                return sizeF.Height + 5;
            }
        }
    }
    

    结果如下:

    我上传了一个示例here,您可以查看。

    【讨论】:

    • 最后问题不是单元格的高度,而是按钮的高度
    • 好的,你可以在这里分享你的解决方案:)。