resize cell in xamarin - ios

I have a table view built in Xamarin that is populated with some addresses, but i can't figure out how to resize the cell so that all information will fit.
My TableViewCell Class:
using System;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using System.CodeDom.Compiler;
using System.Drawing;
namespace Vipar
{
public class CustomVegeeeCell : UITableViewCell {
UILabel Title, Addr, CityState;
//UIImageView imageView;
public CustomVegeeeCell (NSString cellId) : base (UITableViewCellStyle.Default, cellId)
{
SelectionStyle = UITableViewCellSelectionStyle.Gray;
ContentView.BackgroundColor = UIColor.Clear;//(84, 84, 85);
//imageView = new UIImageView();
Title = new UILabel () {
Font = UIFont.FromName("Arial-BoldMT", 16f),
TextColor = UIColor.Black,
BackgroundColor = UIColor.Clear
};
Addr = new UILabel () {
Font = UIFont.FromName("ArialMT", 12f),
TextColor = UIColor.Black,
//TextAlignment = UITextAlignment.Center,
BackgroundColor = UIColor.Clear
};
CityState = new UILabel () {
Font = UIFont.FromName("ArialMT", 12f),
TextColor = UIColor.Black,
//TextAlignment = UITextAlignment.Center,
BackgroundColor = UIColor.Clear
};
ContentView.Add (Title);
ContentView.Add (Addr);
ContentView.Add (CityState);
}
public void UpdateCell (string caption, string subtitle, string subtitle1)//, UIImage image)
{
//imageView.Image = image;
Title.Text = caption;
Addr.Text = subtitle;
CityState.Text = subtitle1;
}
public override void LayoutSubviews ()
{
base.LayoutSubviews ();
//imageView.Frame = new RectangleF(ContentView.Bounds.Width - 63, 5, 33, 33);
Title.Frame = new RectangleF(5, 4, ContentView.Bounds.Width - 63, 25);
Addr.Frame = new RectangleF(5, 18, ContentView.Bounds.Width - 63, 25);
CityState.Frame = new RectangleF(5, 30, ContentView.Bounds.Width - 63, 25);
}
}
}

In UITableViewSource, you need to override GetHeightForRow:
public override float GetHeightForRow(UITableView tableView, NSIndexPath indexPath)

Related

Xamarin iOS UINavigationBar weird overlay

I am working in Xamarin 4.5 with iOS 13. I am using Simulator to run the code. Here's how it looks.
I have added the following code to apply red color but its not hiding this white/grey overlay.
UIApplication.SharedApplication.StatusBarStyle = UIStatusBarStyle.LightContent;
UINavigationBar.Appearance.BarTintColor = UIColor.Red;
UINavigationBar.Appearance.TintColor = UIColor.Red;
UINavigationBar.Appearance.TitleTextAttributes = new UIStringAttributes
{
ForegroundColor = UIColor.Red
};
UINavigationBar.Appearance.BackgroundColor = UIColor.FromRGBA(255, 0, 0, 255);
Last line added the Red color.
It will be an expected effect because UINavigationBar has a default CALayer after iOS 11.0. As a workaround , we could create a custom NavigationBar by using custom renderer
in your iOS project
using Foundation;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using xxx;
using xxx.iOS;
using CoreGraphics;
using ObjCRuntime;
[assembly:ExportRenderer(typeof(ContentPage),typeof(MyPageRenderer))]
namespace xxx.iOS
{
public class MyPageRenderer:PageRenderer
{
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
NavigationController.NavigationBar.Hidden = true;
double height = IsiphoneX();
UIView backView = new UIView()
{
BackgroundColor = UIColor.Red,
Frame = new CGRect(0, 20, UIScreen.MainScreen.Bounds.Width, height),
};
// set
UIButton backBtn = new UIButton()
{
Frame = new CGRect(20, height - 44, 40, 44),
Font = UIFont.SystemFontOfSize(18),
};
backBtn.SetTitle("<",UIControlState.Normal);
backBtn.SetTitleColor(UIColor.White,UIControlState.Normal);
backBtn.AddTarget(this, new Selector("GoBack"), UIControlEvent.TouchUpInside);
UILabel titleLabel = new UILabel()
{
Frame = new CGRect(UIScreen.MainScreen.Bounds.Width / 2 - 75, 0, 150, height),
Font = UIFont.SystemFontOfSize(20),
Text = "xxx",
TextColor = UIColor.White,
Lines = 0,
};
UILabel line = new UILabel()
{
Frame = new CGRect(0, height, UIScreen.MainScreen.Bounds.Width, 0.5),
BackgroundColor = UIColor.Black,
};
if (NavigationController.ViewControllers.Length > 1)
{
backView.AddSubview(backBtn);
}
backView.AddSubview(titleLabel);
backView.AddSubview(line);
View.AddSubview(backView);
}
double IsiphoneX()
{
double height = 44;
if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0))
{
if (UIApplication.SharedApplication.Delegate.GetWindow().SafeAreaInsets.Bottom > 0.0)
{
height = 64;
}
}
return height;
}
[Export("GoBack")]
void GoBack()
{
NavigationController.PopViewController(true);
}
public override void ViewWillDisappear(bool animated)
{
base.ViewWillDisappear(animated);
NavigationController.NavigationBar.Hidden = false;
}
}
}
You can set the property of title , backButton and navigationBar as you need (such as text , color ,BackgroundColor ,font e.g.)

Xamarin UICollectionView some cells disappear after scrolling down and back

I have a problem with UICollectionView, exactly with cells... When I'm scrolling down and back so some cells are just empty. They just disappear something like this:
My ViewDidLoad() in OrdersView:
public override void ViewDidLoad()
{
Title = "My Orders..";
base.ViewDidLoad();
ordersCollectionView.Frame = new CGRect(ordersCollectionView.Frame.X, ordersCollectionView.Frame.Y, ordersCollectionView.Frame.Width, ordersCollectionView.Frame.Height);
ordersCollectionView.ScrollEnabled = true;
var layout = new UICollectionViewFlowLayout
{
ItemSize = new CGSize() { Width = ordersCollectionView.Bounds.Width, Height = 80 },
MinimumInteritemSpacing = 0,
MinimumLineSpacing = 2,
ScrollDirection = UICollectionViewScrollDirection.Vertical
};
ordersCollectionView.SetCollectionViewLayout(layout, true);
this.ClearBindings(_source);
_source = new OrdersCollectionViewSource(ordersCollectionView);
this.AddBindings(new Dictionary<object, string>
{
{ _source, "ItemsSource Orders; SelectedItem SelectedOrder; SelectionChangedCommand ShowOrderDetailCommand" }
});
ordersCollectionView.Source = _source;
ordersCollectionView.ReloadData();
Mvx.Resolve<IMvxMessenger>().SubscribeOnMainThread<OrdersLoadedMessage>(mess =>
{
this.ClearBindings(_source);
_source = new OrdersCollectionViewSource(ordersCollectionView);
this.AddBindings(new Dictionary<object, string>
{
{ _source, "ItemsSource Orders; SelectedItem SelectedOrder; SelectionChangedCommand ShowOrderDetailCommand" }
});
ordersCollectionView.Source = _source;
ordersCollectionView.ReloadData();
}, MvxReference.Strong);
InitializeRefreshControl();
ViewMessages.ViewCreatedMessages(this, "OrdersView", ViewModel);
}
OrdersCollectionViewSource:
public class OrdersCollectionViewSource : MvxCollectionViewSource
{
private static readonly NSString CellIdentifier = new NSString("OrdersCollectionViewCell");
public OrdersCollectionViewSource(UICollectionView collectionView) : base(collectionView)
{
collectionView.RegisterClassForCell(typeof(OrdersCollectionViewCell), CellIdentifier);
}
protected override UICollectionViewCell GetOrCreateCellFor(UICollectionView collectionView, NSIndexPath indexPath, object item)
{
var cell = (UICollectionViewCell)collectionView.DequeueReusableCell(CellIdentifier, indexPath);
cell.BackgroundColor = UIColor.FromRGB(237, 237, 237);
return cell;
}
}
OrdersCollectionViewCell:
public class OrdersCollectionViewCell : MvxCollectionViewCell
{
[Export("initWithFrame:")]
public OrdersCollectionViewCell(CGRect frame) : base(frame)
{
Layer.BackgroundColor = new CGColor(220, 25, 25, 255);
//left
var labelName = new UILabel();
labelName.Frame = new CGRect(10f, 15f, (float)(Bounds.Width / 2 + 20), 20f);
labelName.Font = UIFont.PreferredHeadline;
labelName.TextColor = UIColor.FromRGBA(90, 24, 24, 255);
labelName.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleLeftMargin | UIViewAutoresizing.FlexibleRightMargin;
labelName.Text = "Text";
var labelPickupDate = new UILabel();
labelPickupDate.Frame = new CGRect(10f, 45f, (float)(Bounds.Width / 2 - 10), 20f);
labelPickupDate.Font = UIFont.PreferredBody;
labelPickupDate.TextColor = UIColor.Black;
labelPickupDate.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleLeftMargin | UIViewAutoresizing.FlexibleRightMargin;
//right
var labelPrice = new UILabel();
labelPrice.Frame = new CGRect((float)(Bounds.Width / 2), 45f, (float)(Bounds.Width / 2 - 10), 20f);
labelPrice.TextAlignment = UITextAlignment.Right;
labelPrice.Font = UIFont.PreferredBody;
labelPrice.TextColor = UIColor.Black;
labelPrice.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleLeftMargin | UIViewAutoresizing.FlexibleRightMargin;
var labelStatus = new UILabel();
labelStatus.Frame = new CGRect((float)(Bounds.Width / 2), 15f, (float)(Bounds.Width / 2 - 10f), 20f);
labelStatus.TextAlignment = UITextAlignment.Right;
labelStatus.Font = UIFont.PreferredHeadline;
labelStatus.TextColor = UIColor.FromRGBA(15, 113, 10, 255);
labelStatus.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleLeftMargin | UIViewAutoresizing.FlexibleRightMargin;
Add(labelName);
Add(labelPickupDate);
Add(labelStatus);
Add(labelPrice);
this.DelayBind(() =>
{
var set = this.CreateBindingSet<OrdersCollectionViewCell, Order>();
set.Bind(labelPickupDate).For(q => q.Text).To(vm => vm.PickupDate).WithConversion("StringDateTimeConverter");
set.Bind(labelStatus).For(q => q.Text).To(vm => vm.OrderStatus);
set.Bind(labelPrice).To(vm => vm.Sum).WithConversion("CreditConverter");
set.Apply();
});
}
}
I found here some similarly problems but everything in xcode.. so I tried something but it still doesn't work well.
EDIT - MY SOLUTION:
protected override UICollectionViewCell GetOrCreateCellFor(UICollectionView collectionView, NSIndexPath indexPath, object item)
{
var cell = (UICollectionViewCell)collectionView.DequeueReusableCell(CellIdentifier, indexPath);
cell.BackgroundColor = UIColor.FromRGB(237, 237, 237);
var order = (Order) item;
var test = (OrdersCollectionViewCell) cell;
test.labelName.Text = "Name";
test.labelPickupDate.Text = StringConvertor.StringDateTime(order.PickupDate);
test.labelPrice.Text = StringConvertor.PriceConvertor(order.Sum);
test.labelStatus.Text = order.OrderStatus;
return test;
}
I had a very similar problem. It is because your table reuses cells. dequeueReusableCellWithIdentifier will reuse the same cell references when scrolling and it may not preserve the text you intended to display.
Your GetOrCreateCellFor function contains a call to DequeueReusableCell. You should also set the cell's text within this function (e.g. cell.labelName.text = "my text here").
protected override UICollectionViewCell GetOrCreateCellFor(UICollectionView collectionView, NSIndexPath indexPath, object item)
{
var cell = (UICollectionViewCell)collectionView.DequeueReusableCell(CellIdentifier, indexPath);
cell.BackgroundColor = UIColor.FromRGB(237, 237, 237);
cell.labelName.text = "Your label here"
cell.labelPickupDate.text = "Your pickup date here"
cell.labelPrice.text = "Your price here"
cell.labelStatus.text = "Your status here"
return cell;
}
Please see this answer below for the full explanation. Let me know if you have any questions.
https://stackoverflow.com/a/43164656/2179970

Customize Custom Cell further

I have the following class that generate custom cell. It works very well. However, I have a condition where I need to get more space for my InfoLabel than it is defined below. I could not able to handle it?
public WeinerGeneralCellItem (NSString cellId, Short Weiner) : base (UITableViewCellStyle.Default, cellId)
{
this.Weiner = Weiner;
weinerInfoLabel = new UILabel () {
TextColor = UIColor.FromRGB (0, 0, 0),
BackgroundColor = UIColor.Clear,
TextAlignment = UITextAlignment.Left,
};
weinerInfo = new UITextField () {
TextColor = UIColor.FromRGB (0, 0, 0),
TextAlignment = UITextAlignment.Right,
BackgroundColor = UIColor.Clear,
};
ContentView.Add (weinerInfoLabel);
ContentView.Add (weinerInfo);
}
public override void LayoutSubviews ()
{
base.LayoutSubviews ();
weinerInfoLabel.Frame = new CGRect(20, ContentView.Bounds.Height/4, 200, 25);
weinerInfo.Frame = new CGRect(220, ContentView.Bounds.Height/4, 300, 25);
}
}
By default infolabel width is 200, info is 300, but for the last cell, I want infoLabel width is 350, info is 150. I have tried the following but it did not work.
public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
if (indexPath.Row == 5) {
cell.weinerInfoLabel.Frame = new CGRect(20, 20, 350, 25);
cell.weinerInfo.Frame = new CGRect(350, 20, 150, 25);
cell.weinerInfoLabel.Text = "The value calculated from the server";
cell.weinerInfo.Tag = 5;
cell.weinerInfo.Text = "155.00";
}
}
Here is the solution that I have ended up, it is working. I am just checking tag id before setting up the frame for that corresponding cell.
public override void LayoutSubviews ()
{
base.LayoutSubviews ();
if (weinerInfo.Tag == 5)
{
weinerInfoLabel.Frame = new CGRect (20, ContentView.Bounds.Height / 4, 350, 25);
weinerInfo.Frame = new CGRect (350, ContentView.Bounds.Height / 4, 170, 25);
}
else
{
weinerInfoLabel.Frame = new CGRect(20, ContentView.Bounds.Height/4, 200, 25);
weinerInfo.Frame = new CGRect (220, ContentView.Bounds.Height / 4, 300, 25);
}
}

UITableView UITableViewCellStyle.Value1 TextLabel is overlapping the DetailTextLabel

I'm using Xamarin iOS and on iOS 9.2 devices the UITableView cells with cell style of UITableViewCellStyle.Value1 have the TextLabel overlapping the DetailTextLabel.
This doesn't happen on iOS 8. Anybody know what I can do to fix it without rolling my own cell? I just would like the TextLabel to ellipsis instead of overlapping the DetailTextLabel.
I couldn't find a fix. A blank project reproduced it with just a simple TableView so I rolled my own custom cell.
public class CustomTableViewCell : UITableViewCell
{
UILabel headingLabel, subheadingLabel;
public MTableViewCell (NSString cellId) : base (UITableViewCellStyle.Default, cellId)
{
SelectionStyle = UITableViewCellSelectionStyle.Default;
headingLabel = new UILabel ();
subheadingLabel = new UILabel () {
TextColor = UIColor.Gray,
TextAlignment = UITextAlignment.Center
};
ContentView.AddSubviews (new UIView[] { headingLabel, subheadingLabel });
}
public override void LayoutSubviews ()
{
base.LayoutSubviews ();
headingLabel.Frame = new CGRect (15, 0, ContentView.Bounds.Width - 130, ContentView.Bounds.Height);
subheadingLabel.Frame = new CGRect (ContentView.Bounds.Width - 110, 0, 95, ContentView.Bounds.Height);
}
public override UILabel TextLabel {
get {
return headingLabel;
}
}
public override UILabel DetailTextLabel {
get {
return subheadingLabel;
}
}
}
Pasudocode to decide if you want to dequeue value1 or sub type of cell
public static func isVerticalLayout(primary: String, secondary: NSAttributedString,
liveHostView: UIView) -> Bool
{
let csWidth = liveHostView.bounds.width
let headingLabel = UILabel()
let subheadingLabel = UILabel()
headingLabel.text = primary
headingLabel.numberOfLines = 0
headingLabel.lineBreakMode = .byWordWrapping
subheadingLabel.attributedText = secondary
subheadingLabel.textAlignment = .right
subheadingLabel.numberOfLines = 1
subheadingLabel.lineBreakMode = .byWordWrapping
let clipw = csWidth - P97GEL.Constants.leftTextMargin - P97GEL.Constants.rightTextMargin
let bounds = CGRect(x: 0, y: 0, width: clipw, height: CGFloat.greatestFiniteMagnitude)
let psRect = headingLabel.textRect(forBounds: bounds, limitedToNumberOfLines: 1)
let ps = psRect.size
let ssRect = subheadingLabel.textRect(forBounds: bounds, limitedToNumberOfLines: 1)
let ss = ssRect.size
headingLabel.frame.origin = CGPoint(x: P97GEL.Constants.leftTextMargin, y: P97GEL.Constants.verticalMargin)
headingLabel.frame.size = ps
subheadingLabel.frame.size = ss
if csWidth >= ps.width + ss.width + (3 * P97GEL.Constants.horizontalMargin) {
return false
} else {
return true
}
}

How to change SeparatorColor of Selected Item in a UITableView

I've got the following UITableView
_navigationList = new UITableView
{
Source = UINavigationTableViewSource,
BackgroundColor = UIColor.FromRGB(43, 43, 43), // #2b2b2b - same as Android
SeparatorColor = UIColor.FromRGB(27,27,27), // #1b1b1b - same as Android
SeparatorInset = UIEdgeInsets.Zero,
ScrollEnabled = true
};
The UINavigationTableViewSource is using a custom UITableViewCell
public sealed class UINavigationTableViewCell : UITableViewCell
{
public new readonly UILabel TextLabel;
public UINavigationTableViewCell(string cellId)
: base(UITableViewCellStyle.Default, cellId)
{
TextLabel = new UILabel(new RectangleF(10, 0, Bounds.Width, 40)) {TextColor = UIColor.White}; // properly position the label.
SeparatorInset = UIEdgeInsets.Zero; // make the boarder go all the way across the list item
ContentView.BackgroundColor = UIColor.FromRGB(43, 43, 43); // #2b2b2b - same as Android
var activeOrb = new UIImageView(new RectangleF(0,0,10,Bounds.Height))
{
Image = UIImage.FromBundle("Images/active_orb.png"),
ContentMode = UIViewContentMode.ScaleAspectFit
};
SelectedBackgroundView = new UIView { BackgroundColor = UIColor.FromRGB(43, 43, 43) };
SelectedBackgroundView.Add(activeOrb);
ContentView.Add(TextLabel);
}
}
Everything is looking the way we want except for the ugly white line on a selected row.
How do I change the SeparatorColor when a row is selected?
I had never programmed in xamarin, but i worked on ios(5-7) sdk.
I would suggest you to dont use any seperators.Instead add the seperator line as view(height-1pixel;width-cellWidth) to your cell.
edit by ChaseFlorell - working example
_navigationList = new UITableView
{
Source = UINavigationTableViewSource,
BackgroundColor = UIColor.FromRGB(43, 43, 43), // #2b2b2b - same as Android
SeparatorStyle = UITableViewCellSeparatorStyle.None,
ScrollEnabled = true
};
Add(_navigationList);
public sealed class UINavigationTableViewCell : UITableViewCell
{
public new readonly UILabel TextLabel;
public UINavigationTableViewCell(string cellId) : base(UITableViewCellStyle.Default, cellId)
{
// The default state
TextLabel = new UILabel(new RectangleF(10, 0, Bounds.Width, 40)) { TextColor = UIColor.White }; // properly position the label.
ContentView.BackgroundColor = UIColor.FromRGB(43, 43, 43); // #2b2b2b - same as Android
ContentView.Add(Separator(Bounds));
ContentView.Add(TextLabel);
// todo: move colors to a config file.
// The selected state
var activeOrb = new UIImageView(new RectangleF(0, 0, 10, Bounds.Height))
{
Image = UIImage.FromBundle("Images/active_orb.png"),
ContentMode = UIViewContentMode.ScaleAspectFit
};
SelectedBackgroundView = new UIView { BackgroundColor = UIColor.FromRGB(43, 43, 43) };
SelectedBackgroundView.Add(Separator(Bounds));
SelectedBackgroundView.Add(activeOrb);
}
private static UIView Separator(RectangleF bounds)
{
return new UIView(new RectangleF(0, 0, bounds.Width, 1))
{
BackgroundColor = UIColor.FromRGB(27, 27, 27)
};
}
}

Resources