[英]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上實現它,但是要在該機器上實現它要困難得多。
這是重疊文本的屏幕截圖。
這必須是單元無法正確重用的情況。 所以我的直覺是,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.