Adjust UILabel height by content in xamarin.ios - ios

i have 3 types of string labels, "loading...", "loading, please wait" and "it's taking more than we expected, sorry...". I want to adjust the height of the IULabel and center in the frame. I'm using this:
labelTitle = new UILabel (new CGRect (
frame.Width / 4,
frame.Height / 2 + Dimensions.margin_small,
frame.Width/2,
40
));
labelTitle.StyleTitle ();
labelTitle.TextAlignment = UITextAlignment.Center;
labelTitle.LineBreakMode = UILineBreakMode.WordWrap;
labelTitle.Lines = 0;
But don't know how to resize the height

try this.
labelTitle = new UILabel ();
labelTitle.StyleTitle ();
labelTitle.TextAlignment = UITextAlignment.Center;
labelTitle.LineBreakMode = UILineBreakMode.WordWrap;
labelTitle.Lines = 0;
And now give the label center point.

Related

How do I get text to wrap and add another line below in a Xamarin Forms iOS custom renderer?

I am creating a custom renderer to display a title and description in a translucent white space on an image. The title should wrap to the second line if wider than the image, and an optional description may appear below if there is room. In Android I am able to do this using a StaticLayout:
// Create text rectangle
var height = Height / 3;
canvas.Save();
canvas.ClipRect(0, Height - height, Width, Height);
canvas.DrawARGB(191, 255, 255, 255);
canvas.Restore();
var item = ((ImageTile) Element).Item;
var textSize = (height - 15) / 2;
var textPaint = new TextPaint
{
StrokeWidth = 5,
TextSize = textSize,
FakeBoldText = true,
};
if (Build.VERSION.SdkInt >= BuildVersionCodes.Honeycomb)
SetLayerType(LayerType.Software, textPaint);
textPaint.SetStyle(Paint.Style.Fill);
textPaint.Color = global::Android.Graphics.Color.Black;
// init StaticLayout for text
var titleLayout = new StaticLayout(
item.Title, textPaint, Width - 10, Android.Text.Layout.Alignment.AlignNormal, 1.0f, 0.0f, false);
canvas.Translate(5, Height - height + 5);
titleLayout.Draw(canvas);
canvas.Restore();
textPaint = new TextPaint
{
StrokeWidth = 4,
TextSize = textSize - 10,
};
if (Build.VERSION.SdkInt >= BuildVersionCodes.Honeycomb)
SetLayerType(LayerType.Software, textPaint);
var descLayout = new StaticLayout(
item.Description, textPaint, Width - 10, Android.Text.Layout.Alignment.AlignNormal, 1.0f, 0.0f, false);
canvas.Translate(5, Height - height + titleLayout.Height + 5);
descLayout.Draw(canvas);
canvas.Restore();
in iOS I am using CATextLayers, but I am unable to get the text to wrap even thought I define the frame and set both Wrapped to true and TextTruncationMode to None. I also don't know how to get the actual height of the tilteLayer so I can position the descLayer below it. This is what I have so far, which draws the title and description on top of each other without wraping.
var textLayer = new CALayer();
var textRec = new CGRect(0, element.HeightRequest - textheight, element.WidthRequest,
textheight);
textLayer.Frame = textRec;
var backgroundcolor = Color.FromRgba(255, 255, 255, .25).ToCGColor();
textLayer.BackgroundColor = backgroundcolor;
Control.Layer.AddSublayer(textLayer);
var titleLayer = new CATextLayer
{
String = element.Item.Title,
ForegroundColor = Color.Black.ToCGColor(),
FontSize = 14,
Wrapped = true,
TextTruncationMode = CATextLayerTruncationMode.None,
TextAlignmentMode = CATextLayerAlignmentMode.Left,
//Bounds = new CGRect(2, element.HeightRequest - textheight + 2, element.WidthRequest - 4,
// textheight - 4),
};
var titleRec = new CGRect(2, element.HeightRequest - textheight + 2, element.WidthRequest - 4,
textheight - 4);
titleLayer.Frame = titleRec;
Control.Layer.AddSublayer(titleLayer);
var descLayer = new CATextLayer
{
String = element.Item.Description,
ForegroundColor = Color.Black.ToCGColor(),
FontSize = 12,
Wrapped = true,
TextTruncationMode = CATextLayerTruncationMode.None,
};
var descRec = new CGRect(2, element.HeightRequest - textheight + 2, element.WidthRequest - 4,
textheight - 4);
descLayer.ContentsRect = descRec;
Control.Layer.AddSublayer(descLayer);
Why not try autoLayout? You want to add a background view and two types of text on the original image. CALayer may achieve your effect, but it can't use autoLayout so that you need to use hard code(calculate the text height and the layer's position) to construct that. Also you said
I am unable to get the text to wrap. And I also don't know how to get
the actual height of the tilteLayer so I can position the descLayer
below it.
In the image's custom renderer, since this control has not been rendered, its Frame and HeightRequest are also unknown. Then you won't get the correct frame neither the layer, so the text will not be shown. I think the best way to do that is using AutoLayout:
// Create a view to hold content just like your textLayer
UIView bgView = new UIView();
bgView.BackgroundColor = UIColor.FromRGBA(1, 1, 1, 0.25f);
bgView.TranslatesAutoresizingMaskIntoConstraints = false;
Control.AddSubview(bgView);
bgView.LeadingAnchor.ConstraintEqualTo(Control.LeadingAnchor).Active = true;
bgView.TopAnchor.ConstraintGreaterThanOrEqualTo(Control.TopAnchor).Active = true;
bgView.TrailingAnchor.ConstraintEqualTo(Control.TrailingAnchor).Active = true;
bgView.BottomAnchor.ConstraintEqualTo(Control.BottomAnchor).Active = true;
UILabel titleLabel = new UILabel();
bgView.AddSubview(titleLabel);
titleLabel.TranslatesAutoresizingMaskIntoConstraints = false;
// Set this property to 0, then your label will move to several lines if your text is too large.
titleLabel.Lines = 0;
titleLabel.Font = UIFont.SystemFontOfSize(14);
titleLabel.Text = Element.Item.Title;
titleLabel.LeadingAnchor.ConstraintEqualTo(bgView.LeadingAnchor).Active = true;
titleLabel.TopAnchor.ConstraintEqualTo(bgView.TopAnchor).Active = true;
titleLabel.TrailingAnchor.ConstraintEqualTo(bgView.TrailingAnchor).Active = true;
// This constraint will show the titleLabel's content at high priority. It means show the descLabel if the image has enough place.
titleLabel.SetContentHuggingPriority(249, UILayoutConstraintAxis.Vertical);
UILabel descLabel = new UILabel();
bgView.AddSubview(descLabel);
descLabel.TranslatesAutoresizingMaskIntoConstraints = false;
descLabel.Lines = 0;
descLabel.Text = Element.Item.Description;
descLabel.Font = UIFont.SystemFontOfSize(12);
descLabel.LeadingAnchor.ConstraintEqualTo(bgView.LeadingAnchor).Active = true;
descLabel.TopAnchor.ConstraintEqualTo(titleLabel.BottomAnchor).Active = true;
descLabel.TrailingAnchor.ConstraintEqualTo(bgView.TrailingAnchor).Active = true;
descLabel.BottomAnchor.ConstraintEqualTo(bgView.BottomAnchor).Active = true;
In this way, bgView will expand its height depending on the titleLabel and descLabel. The largest height will be the original image's height. Moreover titleLabel will auto calculate its size depending on its content. Also the descLabel will always lies below the titleLabel if the room allows.
You can adjust these constraints to fit your own requirement.

Calculate width and height of AttributeText does not correct

I'm making an app chat and I have a problem with the chat message's size.
I've calculate my message's height like this and I've got the correct height
maximumMessageWidth = 300.0
let size = CGSize(width: maximumMessageWidth, height: 1000.0)
let messageAttributeText = messageBody.attributedText
let height = messageAttributeText?.boundingRect(with: size, options: .usesLineFragmentOrigin, context: nil).height
To avoid the special case like this image. I have to calculate the width
It has the big space after my message
I want it to look like this:
This is the code I use to calculate the message width (I used the correct height which I've calculated the width)
let size = CGSize(width: 1000.0, height: height)
let messageAttributeText = messageBody.attributedText
var width = messageAttributeText?.boundingRect(with: size, options: .usesLineFragmentOrigin, context: nil).width
but width in this code seem not right. Because I think it does care about my height property. It assume that my text is in only 1 line.
But I want to calculate the width, so that my text will `fill the whole label' just like the second image
Does anyone know how to calculate the width in my case ?
You can do that by casting String to NSString
var string = "Hello, World"
let nsString = string as NSString
let size = nsString.size(attributes: [NSFontAttributeName: UIFont.systemFont(ofSize: 14)])
The size will give you width and height of the string.
You can apply this to your NSAttributedStrings string property.
After a bit of research, I find out this:
The calculate width code doesn't work right because it do not care about the height property.
If height = 100 or height = 1000 it will return the same result because it assume to draw all the text in just one line.
So to calculate the width, I used binary search
var minWidth:CGFloat = 0.0
var maxWidth = maxWidth
while true {
if (minWidth >= maxWidth) {
width = minWidth
break
}
let testWidth = (maxWidth + minWidth) / 2.0
if calculateMessageHeight(width: testWidth) > messageHeight {
minWidth = testWidth + 2.0
continue
} else {
maxWidth = testWidth - 2.0
continue
}

UILabel with Image and text in iOS(Xamarin)

I am making UILabel with Image and text inside that.I try many thing like below.
Try 1 :
Using this code
var textAttchment = new NSTextAttachment();
textAttchment.Image = UIImage.FromBundle("location_grey_icon");
var attachmentString = NSAttributedString.FromAttachment(textAttchment);
var attributedString = new NSMutableAttributedString(lbl_inr.Text.ToString());
this.lbl_inr.AttributedText = attributedString;
But it only display the Text not the image.
Try 2:
using this code
var attchment = new NSTextAttachment();
attchment.Image = UIImage.FromBundle("location_grey_icon");
attchment.Bounds = new CGRect(0, -1, 13, 13);
var intiliazeText = this.text_inr.AttributedText;
var newText = new NSMutableAttributedString(intiliazeText);
newText.Append(NSAttributedString.CreateFrom(attchment));
this.text_inr.AttributedText = newText;
it is display the Image and Text both.
Output :
What I want :
but my requirement is to I want to set image before the Text so first Image and then Text.
Any help be Appreciated.
Your requirement is very specific, the best way to do this would be with a custom control.
UIView + Label + UIImageView
and there you could set your bounds to your needs. With the designer this is a simple task.
Or you could try with a UITextField, removing the borders and disabling it. Then adding a UIImageView as the RightView (or LeftView as you wish).
var textEdit = new UITextField (new CGRect (15, 100, 200, 30));
textEdit.Enabled = false;
textEdit.Text = "Hello from Xamarin";
var xamImageView = new UIImageView (new CGRect (0,0, 25, 25));
xamImageView.Image = UIImage.FromBundle ("xamagon");
textEdit.RightView = xamImageView;
textEdit.TextAlignment = UITextAlignment.Right;
textEdit.RightViewMode = UITextFieldViewMode.Always;
textEdit.BorderStyle = UITextBorderStyle.None;
Result:
Hope this helps!
Using below code I manage
var attchment = new NSTextAttachment();
attchment.Image = UIImage.FromBundle("location_grey_icon");
attchment.Bounds = new CGRect(0, -2, 14, 14);
var newText = new NSMutableAttributedString();
newText.Append(NSAttributedString.CreateFrom(attchment));
NSAttributedString s = new NSAttributedString(item.Total.ToString());
newText.Append(s);
this.lbl_inr.AttributedText = newText;
Output :

Corona widget.newButton passing data to function

I have scoured the documentation and google for a solution but none was found.
Simply: I want to pass data to a function, when a button is pressed.
Issue: The buttons are dynamically created, so the data must be presented when the button is built.
The code looks like this;
myButton = widget.newButton({
x = width * 0.875,
y = height * heightChange,
width = width * 0.18,
height = height * 0.09,
defaultFile = "Assets/Images/button_up.png",
overFile = "Assets/Images/button_down.png",
onEvent = func_myFunction
})
But I want to do something like;
onEvent = func_myFunction("My Data")
or
onEvent = func_myFunction, myData
neither of which work. Any ideas?
It's simple you just need to add an eventlistener to the end of your code so when it's clicked your data would execute.
myButton = widget.newButton({
x = width * 0.875,
y = height * heightChange,
width = width * 0.18,
height = height * 0.09,
defaultFile = "Assets/Images/button_up.png",
overFile = "Assets/Images/button_down.png",
onEvent = func_myFunction
})
myButton:addEventListener("touch",onEvent);
I hope this fixes your problem.

Creating Variable Constraints for a UIImageView in Swift?

I'm trying to make some UIImageViews in Xcode that fill the screen based on different conditions. For example, I might have a 3x3 square of images that have to fill the screen, or a 4x4 square that must fill the screen, based on different initial conditions. Every time I try to accomplish this, the ImageViews just end up being the same size for both conditions. I've tried many different solutions but the one I'm currently trying is:
if fieldDimensions == 3 {
let spacing = screenWidth / 16
let boxsize = screenWidth / 4
let xadjust = spacing / 2 //Value to help align view
let interval = spacing + boxsize
Button1Image.translatesAutoresizingMaskIntoConstraints = false
button1height.constant = boxsize
button1width.constant = boxsize
button2height.constant = boxsize
button2width.constant = boxsize
}
else if fieldDimensions == 4 {
let spacing = screenWidth / 20
let boxsize = screenWidth * 3/16
let interval = spacing + boxsize
button1height.constant = boxsize
button1width.constant = boxsize
button2height.constant = boxsize
button2width.constant = box size
All of the button heights and widths are linked to the height and width constraints in the storyboard (I just control-dragged them). Any help would be really appreciated, I've been working on this problem for almost a week now, thanks!!

Resources