簡體   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