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
}
}
Related
I want the currency abbreviation uilabel closely follow text being input into UITextField. What's a good way to
calculate where did the text being input ended so
that
func rightViewRect(forBounds bounds: CGRect) -> CGRect
can calculate the label rect properly?
Among other things I've ended up with this helper:
func rightViewRect(bounds: CGRect,
label: UILabel,
field: UITextField
) -> CGRect
{
let measure = UILabel()
measure.font = field.font
if field.text?.isEmpty ?? true {
measure.text = field.placeholder
} else {
measure.text = field.text
}
let cs = measure.intrinsicContentSize
let lcs = label.intrinsicContentSize
guard lcs.width > 0 else {
return .zero
}
let magicSpace = CGFloat(2)
let unclipped = CGRect(x: cs.width + magicSpace, y: 0, width: lcs.width, height: bounds.height)
let clipped = unclipped.intersection(bounds)
return clipped
}
I have UIScrollView with 3x Screen Size width, and i have 3 table view in it. For some reason, content disappear in some point of time when i begin to scroll horizontally. But tables are on screen (i can figure that out because i set tables background colour and can see it). Also, i did print items in number of rows and it exist. Here is my code:
func createTables(){
for i in 0...2 {
var tv : UITableView
var adapter : CDRTableAdapter
var tvVm : MainTableViewModel
let offset = (CGFloat(i) * CGFloat(Helper.ScreenSize.width))
print("offset \(offset)")
/* View model */
tvVm = MainTableViewModel()
/* Table view */
adapter = CDRTableAdapter(model:tvVm as CDTableAdapterViewModel, managedVC: self)
let dct = ["EmptyHeightItem" : "EmptyHeightCell", "MenuItem" : "MenuCell"]
tv = UITableView(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
tv.separatorStyle = .none
if (i == 1){
tv.backgroundColor = .yellow
} else {
tv.backgroundColor = .red
}
tv.showsVerticalScrollIndicator = false
tv.mapTableViewWithCellsDictionary(dictionary: dct)
tv.dataSource = adapter
tv.delegate = adapter
tv.estimatedRowHeight = 80
tv.rowHeight = UITableViewAutomaticDimension
self.mainContainerView.addSubview(tv)
tv.snp.makeConstraints { (make) in
make.top.equalTo(self.segmentioView.snp.bottom)
make.bottom.equalTo(self.mainContainerView)
make.left.equalTo(self.mainContainerView).offset(offset)
make.width.equalTo(Helper.ScreenSize.width)
}
}
}
extension UITableView {
func mapTableViewWithCellsDictionary(dictionary : [String : String]) -> Void {
for (key, _) in dictionary {
let cellClassStr = "\(Helper.appName).\(dictionary[key]!)"
self.register(NSClassFromString(cellClassStr), forCellReuseIdentifier: key)
}
}
}
So, if someone has faced the problem before please help.
Thanks
I'm using the JBChartView library to draw a bar chart in my iOS application. Each Bar should have an identifier, that is shown at the bottom of the bar.
I tried defining a custom barView with an additional label, but do not know how to place the label relative to the bar.
Here's the code:
func barChartView(barChartView: JBBarChartView!, barViewAtIndex index: UInt) -> UIView! {
let barView = UIView()
// setting up the bar
let bar: Float = chartData[Int(index)]
var barColor = UIColorFromRGB(0xE8E8E8)
if bar >= 1 { barColor = UIColorFromRGB(0xFF6259) }
if bar > 33 { barColor = UIColorFromRGB(0xFFC02F) }
if bar > 66 { barColor = UIColorFromRGB(0x28CA41) }
barView.backgroundColor = barColor
// setting up the label
var label = UILabel()
label.textAlignment = NSTextAlignment.Center
label.textColor = barColor
label.text = NSString(format: "%.0f", bar)
barview.addSubview(label)
return barView
}
Your help would be much appreciated!
ok, this is embarassing: label and bar had the same color, so the label was there all the time .
The final code (improved and with an additional Data Label):
func barChartView(barChartView: JBBarChartView!, barViewAtIndex index: UInt) -> UIView! {
let barView = BarChartBarView()
let bar: Float = chartData[Int(index)]
var barColor = UIColorFromRGB(0xE8E8E8)
if bar >= 1 { barColor = UIColorFromRGB(0xFF6259) }
if bar > 33 { barColor = UIColorFromRGB(0xFFC02F) }
if bar > 66 { barColor = UIColorFromRGB(0x28CA41) }
barView.backgroundColor = barColor
barView.dataLabel.text = NSString(format: "%.0f", bar)
barView.legendLabel.text = chartLegend[Int(index)]
return barView
}
class BarChartBarView: UIView {
let labelFont = UIFont(name:"Raleway-Thin", size:8.0)
var padding = CGFloat(0)
var barWidth = CGFloat(27)
var dataLabel = UILabel()
var legendLabel = UILabel()
var legendLabelWidth = CGFloat(50)
var labelHeight = CGFloat(27)
override convenience init() {
self.init(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
}
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColorFromRGB(0xE8E8E8)
// setting up data Label
dataLabel.frame = CGRectMake(0, 0, barWidth, labelHeight)
dataLabel.textAlignment = NSTextAlignment.Center
dataLabel.textColor = UIColor.whiteColor()
dataLabel.font = labelFont
self.addSubview(dataLabel)
// setting up legend Label
legendLabel.frame = CGRectMake(0, self.bounds.height, legendLabelWidth, labelHeight)
legendLabel.textAlignment = NSTextAlignment.Center
legendLabel.textColor = UIColor.blackColor()
legendLabel.font = labelFont
self.addSubview(legendLabel)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
let xOffset = (self.barWidth - self.legendLabelWidth) / 2
let yOffset:CGFloat = self.bounds.height
let width = self.legendLabelWidth
let height = self.labelHeight
self.legendLabel.frame = CGRectMake(xOffset, yOffset, width, height)
}
}
#Armin
I got the clue to implement the following method:
- (UIView *)barChartView:(JBBarChartView *)barChartView barViewAtIndex:(NSUInteger)index
From Armin. Because even though JawBone's JBBarChart library is impressive their Demo is totally done using code, and also it's bit confusing at a glance. However my way of adding the Label view is same old way of creating a UIView and adding the UILabel as a subview and returning it. And it looks like follows:
- (UIView *)barChartView:(JBBarChartView *)barChartView barViewAtIndex:(NSUInteger)index {
UIView *barView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 55, (CGFloat)chartData[(int)index])];
if (index == 0) {
[barView setBackgroundColor:[UIColor grayColor]];
} else if (index == 1) {
[barView setBackgroundColor:[UIColor redColor]];
} else if (index == 2) {
[barView setBackgroundColor:[UIColor orangeColor]];
} else {
[barView setBackgroundColor:[UIColor blueColor]];
}
int roomCount = (int)chartData[(int)index];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(2, 5.0f, 50.0f, 21.0f)];
[label setTextAlignment:NSTextAlignmentCenter];
[label setTextColor:[UIColor blackColor]];
[label setFont:[UIFont fontWithName:#"Raleway-Thin" size:6.0]];
[label setText:[NSString stringWithFormat:#"%d/56", roomCount]];
[barView addSubview:label];
return barView;
}
Please consider that chartData is contains my data, as integers. So I need the height of each Bar View according to that integer in each position.
Hope this answer would be helpful to someone out there, specially who is juggling to do this implementation in Objective-C.
Cheers!
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)
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)
};
}
}