繁体   English   中英

Xamarin自定义UITableViewCell重复使用时重叠文本

[英]Xamarin custom UITableViewCell overlapping text on reuse

我正在使用Monotouch.Dialog框架来构建供用户输入应用程序的表单。 我遇到一个奇怪的问题,当我继承UITableViewCell时,屏幕显示重叠的文本。 当我说文本重叠时,我的意思是好像整个单元格都放在另一个单元格之上,而不仅仅是标签被推到一起或放错位置。

我跟着Xamarin网站上的这个例子在这里

基本上我有这个UITableViewCell类

public class SAFutureAdCell : UITableViewCell
{
    private UILabel issueAndSizeLabel, mailDateLabel, orderDateLabel, miscLabel, totalLabel;
    private UIImage monthlyImage, ccoImage;

    public SAFutureAdCell(IntPtr p) : base(p) 
    {
        init ();
    }
    public SAFutureAdCell(string resuseIdentifier) : base(UITableViewCellStyle.Default, resuseIdentifier)
    {
        init ();
    }
    public SAFutureAdCell(NSString cellKey): base(UITableViewCellStyle.Default, cellKey)
    {
        init ();
    }

    private void init()
    {
        issueAndSizeLabel = new UILabel() {
            TextColor = UIColor.Black,
            Font = UIFont.BoldSystemFontOfSize(15),
            BackgroundColor = UIColor.Clear,
            ShadowColor = UIColor.Clear,
            TextAlignment = UITextAlignment.Left,
            ClipsToBounds = true
        };

        mailDateLabel = new UILabel() {
            TextColor = UIColor.Black,
            Font = UIFont.BoldSystemFontOfSize(15),
            BackgroundColor = UIColor.Clear,
            ShadowColor = UIColor.Clear,
            TextAlignment = UITextAlignment.Left,
            ClipsToBounds = true
        };

        orderDateLabel = new UILabel() {
            TextColor = UIColor.Gray,
            Font = UIFont.SystemFontOfSize(13),
            BackgroundColor = UIColor.Clear,
            ShadowColor = UIColor.Clear,
            TextAlignment = UITextAlignment.Left,
            ClipsToBounds = true
        };

        miscLabel = new UILabel() {
            TextColor = UIColor.Gray,
            Font = UIFont.SystemFontOfSize(13),
            BackgroundColor = UIColor.Clear,
            ShadowColor = UIColor.Clear,
            TextAlignment = UITextAlignment.Right,
            ClipsToBounds = true
        };

        totalLabel = new UILabel() {
            TextColor = UIColor.Black,
            Font = UIFont.BoldSystemFontOfSize(15),
            BackgroundColor = UIColor.Clear,
            ShadowColor = UIColor.Clear,
            TextAlignment = UITextAlignment.Right,
            ClipsToBounds = true
        };

        monthlyImage = AppearanceManager.MonthlyIndicator; // small blue circle
        ccoImage = AppearanceManager.CcoIndicator; // small red circle
        ImageView.Image = monthlyImage;
        ImageView.ContentMode = UIViewContentMode.ScaleAspectFit;

        ContentView.AddSubviews(issueAndSizeLabel, mailDateLabel, orderDateLabel, miscLabel, totalLabel);

    }

    public override void LayoutSubviews()
    {
        base.LayoutSubviews();

        Accessory = UITableViewCellAccessory.DisclosureIndicator;

        var b = ContentView.Bounds;
        b.Width -= 30;
        var x = 24;

        issueAndSizeLabel.Frame = new RectangleF(x, 5, b.Width / 2, b.Height / 2 - 5).RoundFloats();
        mailDateLabel.Frame = new RectangleF(issueAndSizeLabel.Frame.Right, 5, b.Width / 4, b.Height / 2 - 5).RoundFloats();
        totalLabel.Frame = new RectangleF(mailDateLabel.Frame.Right, 5, b.Width / 4, b.Height / 2 - 5).RoundFloats();
        orderDateLabel.Frame = new RectangleF(x, b.Height / 2 + 5, b.Width / 3, b.Height / 2 - 10).RoundFloats();
        miscLabel.Frame = new RectangleF(totalLabel.Frame.Left, b.Height / 2 + 5, b.Width / 4, b.Height / 2 - 10).RoundFloats();
        ImageView.Frame = new RectangleF(5, 0, AppearanceManager.MonthlyIndicator.Size.Width, ContentView.Frame.Height);
    }

    public void Update(Ad ad)
    {
        issueAndSizeLabel.Text = string.Format("{0} - {1}", ad.IssueCode, ad.AdvertSize);
        mailDateLabel.Text = string.Format("Mail: {0}", ad.MailDate.ToShortDateString());
        orderDateLabel.Text = string.Format("Order: {0}", ad.OrderDate.ToShortDateString());
        miscLabel.Text = string.Format("Misc: {0}", ad.Misc.ToCurrency());
        totalLabel.Text = string.Format("Total: {0}", ad.Total.ToCurrency());

        if (ad.IsCCOPackage)
            ImageView.Image = ccoImage;
        else
            ImageView.Image = monthlyImage;

        ImageView.Alpha = (ad.IsMonthlyBilling || ad.IsCCOPackage) ? 1f : 0f;
    }
}

此单元格从此元素中使用。

public class SAFutureAdDetailElement : Element, IElementSizing
{
    public SAFutureAdDetailElement(Ad ad, NSAction tapped) : base("FutureAdDetail")
    {
        this.ad = ad;
        Tapped += tapped;
    }

    public SAFutureAdDetailElement(Ad ad) : base("FutureAdDetail")
    {
        this.ad = ad;
    }

    private static NSString cellKey = new NSString("SAFutureAdDetailElement");
    protected override NSString CellKey
    {
        get
        {
            return cellKey;
        }
    }

    public override UITableViewCell GetCell(UITableView tv)
    {
        var cell = tv.DequeueReusableCell (cellKey) as SAFutureAdCell;
        if (cell == null) {
            cell = new SAFutureAdCell(cellKey);
        }

        cell.Update (ad);

        return cell;
    }

    public override void Selected(DialogViewController dvc, UITableView tableView, NSIndexPath path)
    {
        if (Tapped != null)
            Tapped ();

        tableView.DeselectRow (path, true);
    }

    public float GetHeight(UITableView tableView, NSIndexPath indexPath)
    {
        return cellHeight;
    }

    private Ad ad;
    public event NSAction Tapped;

    private int cellHeight = 60;
}

这些元素的集合像这样添加到MTD部分

Section CreateOnPageSection()
{
    var onPageSection = new Section ("Future On Page Ads");
    onPageSection.AddAll (
        from ad in orderInfo.AdsFuture
        where !Settings.offPageAdSizes.Contains (ad.AdvertSizeID)
        select new SAFutureAdDetailElement (
            ad, 
            () => {
                NavigationController.PushViewController (new FutureAdDetailController (customer.CustID, ad, this), true);
            }
        )
    );
    return onPageSection;
 }

然后将其作为DialogViewController的一部分添加到RootElement中。 根元素还添加了其他3个部分,所有部分都包含具有自己的自定义UITableViewCells的自定义元素,并且它们都非常相似。 它们在标签的位置和放入标签的数据上基本上有所不同。

直到发生滚动或将视图推到NavigationController上然后弹出回到该视图之前,文本不会重叠。 通常也很难在较新的iPad上进行复制(此应用程序仅适用于iPad)。 在较旧的iPad 2s上,此问题的发生频率更高。 有时我可以在Air上实现它,但是要在该机器上实现它要困难得多。

这是重叠文本的屏幕截图。

iOS UITableViewCell重叠文本

这必须是单元无法正确重用的情况。 所以我的直觉是,GetCell方法的更改将完成此工作。

public override UITableViewCell GetCell(UITableView tv)
{
    var cell = tv.DequeueReusableCell (cellKey);// as SAFutureAdCell;
    if (cell == null) {
        cell = new SAFutureAdCell(cellKey);
    }
    else
        {
            cell.Element = this;
        }

    cell.Update (ad);

    return cell;
}

您可以尝试更改这样的GetCell方法吗? 它可能会解决...

好的,所以我找到了自己的问题的答案。 看起来LayoutSubviews如何与单元回收一起工作时存在问题。 基本上,我要做的是摆脱自定义单元,并将所有显示loginc移到自定义元素中的GetCell方法中。 元素类看起来像这样。

public class SAFutureAdDetailElement : Element, IElementSizing
{
    public SAFutureAdDetailElement(Ad ad, NSAction tapped) : base("FutureAdDetail")
    {
        this.ad = ad;
        Tapped += tapped;
    }

    public SAFutureAdDetailElement(Ad ad) : base("FutureAdDetail")
    {
        this.ad = ad;
    }

    private static NSString cellKey = new NSString("SAFutureAdDetailElement");
    protected override NSString CellKey
    {
        get
        {
            return cellKey;
        }
    }

    public override UITableViewCell GetCell(UITableView tv)
    {
        var cell = tv.DequeueReusableCell (cellKey);
        if (cell == null) {
            cell = new UITableViewCell (UITableViewCellStyle.Default, cellKey);

            cell.IndentationLevel = 0;
            var x = 24;
            var contentWidth = tv.Bounds.Width - 30 - x;
            var issueAndSizeLabel = new UILabel (new RectangleF (x, 5, contentWidth / 2, cellHeight / 2 - 5).RoundFloats ()) {
                TextColor = UIColor.Black,
                Font = UIFont.BoldSystemFontOfSize (15),
                BackgroundColor = UIColor.Clear,
                ShadowColor = UIColor.Clear,
                TextAlignment = UITextAlignment.Left,
                ClipsToBounds = true,
                Text = string.Format ("{0} - {1}", ad.IssueCode, ad.AdvertSize)
            };

            var mailDateLabel = new UILabel (new RectangleF (issueAndSizeLabel.Frame.Right, 5, contentWidth / 4, cellHeight / 2 - 5).RoundFloats ()) {
                TextColor = UIColor.Black,
                Font = UIFont.BoldSystemFontOfSize (15),
                BackgroundColor = UIColor.Clear,
                ShadowColor = UIColor.Clear,
                TextAlignment = UITextAlignment.Left,
                ClipsToBounds = true,
                Text = string.Format ("Mail: {0}", ad.MailDate.ToShortDateString ())
            };

            var orderDateLabel = new UILabel (new RectangleF (x, cellHeight / 2 + 5, contentWidth / 3, cellHeight / 2 - 10).RoundFloats ()) {
                TextColor = UIColor.Gray,
                Font = UIFont.SystemFontOfSize (13),
                BackgroundColor = UIColor.Clear,
                ShadowColor = UIColor.Clear,
                TextAlignment = UITextAlignment.Left,
                ClipsToBounds = true,
                Text = string.Format ("Order: {0}", ad.OrderDate.ToShortDateString ())
            };

            var totalLabel = new UILabel (new RectangleF (mailDateLabel.Frame.Right, 5, contentWidth / 4, cellHeight / 2 - 5).RoundFloats ()) {
                TextColor = UIColor.Black,
                Font = UIFont.BoldSystemFontOfSize (15),
                BackgroundColor = UIColor.Clear,
                ShadowColor = UIColor.Clear,
                TextAlignment = UITextAlignment.Right,
                ClipsToBounds = true,
                Text = string.Format ("Total: {0}", ad.Total.ToCurrency ())
            };

            var miscLabel = new UILabel (new RectangleF (totalLabel.Frame.Left, cellHeight / 2 + 5, contentWidth / 4, cellHeight / 2 - 10).RoundFloats ()) {
                TextColor = UIColor.Gray,
                Font = UIFont.SystemFontOfSize (13),
                BackgroundColor = UIColor.Clear,
                ShadowColor = UIColor.Clear,
                TextAlignment = UITextAlignment.Right,
                ClipsToBounds = true,
                Text = string.Format ("Misc: {0}", ad.Misc.ToCurrency ())
            };

            var indicator = new UIImageView (new RectangleF (5, 0, AppearanceManager.MonthlyIndicator.Size.Width, cellHeight));
            indicator.ContentMode = UIViewContentMode.ScaleAspectFit;
            if (ad.IsCCOPackage) {
                indicator.Image = AppearanceManager.CcoIndicator;
            } else if (ad.IsMonthlyBilling) {
                indicator.Image = AppearanceManager.MonthlyIndicator;
            }

            cell.Accessory = UITableViewCellAccessory.DisclosureIndicator;

            cell.ContentView.AddSubviews (indicator, issueAndSizeLabel, mailDateLabel, orderDateLabel, miscLabel, totalLabel);
        }

        ((UILabel)cell.ContentView.Subviews[1]).Text = string.Format("{0} - {1}", ad.IssueCode, ad.AdvertSize);
        ((UILabel)cell.ContentView.Subviews[2]).Text = string.Format("Mail: {0}", ad.MailDate.ToShortDateString());
        ((UILabel)cell.ContentView.Subviews[3]).Text = string.Format("Order: {0}", ad.OrderDate.ToShortDateString());
        ((UILabel)cell.ContentView.Subviews[4]).Text = string.Format("Misc: {0}", ad.Misc.ToCurrency());
        ((UILabel)cell.ContentView.Subviews[5]).Text = string.Format("Total: {0}", ad.Total.ToCurrency());
        if (ad.IsCCOPackage) {
            ((UIImageView)cell.ContentView.Subviews [0]).Image = AppearanceManager.CcoIndicator;
        } else if (ad.IsMonthlyBilling) {
            ((UIImageView)cell.ContentView.Subviews [0]).Image = AppearanceManager.MonthlyIndicator;
        } else {
            ((UIImageView)cell.ContentView.Subviews [0]).Image = null;
        }
        return cell;
    }

    public override void Selected(DialogViewController dvc, UITableView tableView, NSIndexPath path)
    {
        if (Tapped != null)
            Tapped ();

        tableView.DeselectRow (path, true);
    }

    public float GetHeight(UITableView tableView, NSIndexPath indexPath)
    {
        return cellHeight;
    }

    private Ad ad;
    public event NSAction Tapped;

    private int cellHeight = 60;
}

我唯一不喜欢的就是更新单元格值,这有点痛苦,因为我必须从UIView数组中获取UILabel并像这样((UILabel)cell.ContentView.Subviews[1])其中,好运保持跟踪UILabel是因为你现在已经不能用一个变量名来引用UILabel 是的,我确实尝试过将标签设置为元素的私有成员,并尝试以这种方式进行更新,但这是行不通的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM