2016-04-14 5 views
0

私はMonotouch.Dialogフレームワークを使用して、ユーザー入力用のフォームをビルドしています。私はUITableViewCellをサブクラス化すると、画面に重複するテキストが表示されるという奇妙な問題に遭遇しました。私がテキストが重なっていると言うと、ラベルが一緒に押されたり間違って配置されたりするのではなく、1つのセル全体が別のセルの上に置かれているかのように見えます。XamarinカスタムUITableViewCell再利用時にテキストが重複する

この例は、XamarinのWebサイトhereに従っています。

基本的に私は、このセルは、この要素から使用されます。この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; 
} 

これら要素の集合は、その後DialogViewControllerの一部としてRootElementに追加されるので、

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; 
} 

ようMTDセクションに追加されます。ルート要素には他に3つのセクションが追加されています。これらのセクションはすべて、独自のカスタムUITableViewCellを持つカスタム要素を持ち、すべて非常に似ています。それらは基本的に、ラベルとラベルに入るデータの配置が異なります。

スクロールが発生するまで、またはNavigationControllerにビューをプッシュしてからこのビューにポップバックするまで、テキストは重複しません。新しいiPadでも再現することは難しい(このアプリはiPadのみ)。この問題は、古いiPad 2ではずっと頻繁に起こります。ときに私はそれが私の空気で起こることができますが、それはそのマシンで起こるようにはるかに困難です。

重複するテキストのスクリーンショットです。

IOS UITableViewCell Overlapping Text

+0

問題を再現するのは難しいと言われていますが、セルをデキューしないで、すぐに新しいテストを作成してみたことがありますか?あるいは、ツールバーに 'UITableView.ReloadData()'ボタンを追加すると、強制的なリフレッシュはテーブルビューを適切にペイントしますか? – SushiHangover

+0

'TableView.ReloadData()'と 'this.ReloadData()'を試しましたが、テーブルビューを正しく再描画しませんでした。 –

+0

hmmm、メインUIスレッドで 'ReloadData()'を呼び出しましたか?( 'InvokeOnMainThread'または' BeginInvokeOnMainThread'を介して) – SushiHangover

答えて

0

OK私は自分の質問に答えを見つけました。 LayoutSubviewsがセルのリサイクルにどのように作用するかに問題があるようです。基本的に私が行ったのは、カスタムセルを取り除いて、すべてのdisplay 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のいずれかであるトラックを追跡してください。はい、私はラベルを要素のプライベートメンバーにしようとしましたが、うまくいかないように更新しようとしました。

0

それは適切に再使用され得ていないセルの場合にする必要があります。だから私の直感は、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メソッドを変更できますか?それはそれを修正するかもしれません...

+0

のUITableViewCellはエレメントと呼ばれるプロパティを含むものUITableViewCellを継承SAFutureAdCellをしません。 –

関連する問題