[英]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.