I'm using the Monotouch.Dialog framework to build forms for user input my app. I have run into an odd problem where the screen displays overlapping text when I subclass UITableViewCell. When I say text overlapping I mean it looks as if one entire cell is placed on top of another, not just labels being pushed together or misplaced.
I followed this example on the Xamarin website here.
Basically I have this UITableViewCell class
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;
}
}
This cell gets used from this Element.
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;
}
A collection of these elements are added to an MTD Section like so
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;
}
Which is then added to a RootElement as a part of a DialogViewController. The root element has 3 other sections added to it, all with custom elements that have their own custom UITableViewCells and they are all very similar. They basically differ in the placement of the labels and the data that goes into the labels.
The text doesn't overlap until scrolling occurs or until you push a view onto the NavigationController and then pop back to this view. It is often difficult to reproduce on newer iPads as well (this app is iPad only). This issue happens much more frequently on older iPad 2s. Sometimes i can get it to happen on my Air but it is much more difficult to make it happen on that machine.
Here is a screenshot of the overlapping text.