Height required for UILabel dependent on string length (Swift, iOS 8) - nsstring

I am struggling to get the height that is required for a UILabel based on variable sized text that it could accept. From hours of research, I have not yet discovered a viable way of achieving this. Currently my code is as follows:
func getHeightForTitle(postTitle: NSString) -> CGFloat {
// Get the height of the font
let constraintSize = CGSizeMake(self.cellTextWidth, CGFloat.max)
let attributes = [NSFontAttributeName: [UIFont.systemFontOfSize(16.0)]]
let labelSize = postTitle.boundingRectWithSize(constraintSize,
options: NSStringDrawingOptions.UsesLineFragmentOrigin,
attributes: attributes,
context: nil)
return labelSize.height
}
This however throws the following error:
2014-08-02 12:09:37.370 Testing App[8365:351906] - [_TtCSs23_ContiguousArrayStorage00007FD26C15F708 pointSize]: unrecognized selector sent to instance 0x11e640050
This is always thrown at the let labelSize = postTitle... method and I believe it is down to the attributes variable. I however maybe wrong. Any help is appreciated, and much thanked!
Please note: This is for an iOS 8, Swift development project.

Two observations. First, what's wrong with your code is that this line is not Swift:
let attributes = [NSFontAttributeName: [UIFont.systemFontOfSize(16.0)]]
The stuff after the equals sign is Objective-C, and Swift is having trouble interpreting it. Remove the square brackets from around the UIFont call; you have turned this into an array, which is the source of the error you're seeing.
Second, and more important, there are many much simpler ways to do this, by letting the label tell you its size for the desired text:
Put the text into the label and call sizeToFit() on the label.
Put the text into the label and call sizeThatFits() on the label with the desired width and large height.
Under auto layout, set the label's preferredMaxLayoutWidth to the desired width and put the text into the label; it will size itself.
However, I would urge you not to do this if you don't have to. A label is already self-sizing under auto layout, and in iOS 8 there's a new feature where a table cell will self-adjust its height to its contents, so there is now very rarely a need to pre-measure a label's dimensions.

Put the text into the label and call sizeThatFits() on the label with the desired width and large height.
sub_label=UILabel(frame: CGRectMake(0, 0, self.view.bounds.width, 50))
sub_label.numberOfLines=0;
sub_label.textAlignment=NSTextAlignment.Left
sub_label.lineBreakMode=NSLineBreakMode.ByWordWrapping
let subfont = UIFont(name: "Helvetica", size: 20.0)
sub_label.font=subfont
sub_label.text="his is just a load of texthis is just a load of texthis is just a load of texthis is just a load of texthis is just a load of texthis is just a load of text"
sub_label.backgroundColor=UIColor.clearColor()
var textViewSizesub=sub_label.sizeThatFits(CGSizeMake(self.view.bounds.width, CGFloat.max))
sub_label.frame=CGRectMake(0, textViewSize.height, self.view.bounds.width-5, textViewSizesub.height)

Related

webdriver print with desired pageWidth pageHeight

I was searching and trying many things to change page size of generated PDF with webdriver.
I already read and studied those following links
https://w3c.github.io/webdriver/#print-page
https://webdriver.io/docs/api/webdriver/#printpage
https://github.com/jlipps/simple-wd-spec
as so far I was able to succesuflly use {"background": true} but when I try to change page size with using {"pageWidth": 29.70, "pageHeight": 42.00} (desired A3 format) then I have no success, I mean generated PDF is still 8,50x11,00 inches but I wanted A3 format which should be 11,69x16,54 inches.
Size of page in PDF I check using AcrobatReader:
So I wanted to ask if I pass {"pageWidth": 29.70, "pageHeight": 42.00} incorectly or there is another issue which I do not understand.
I just went through the spec and I see that it mentions this regarding page dimensions:
Let pageWidth be the result of getting a property with default named width and with a default of 21.59 from page.
Let pageHeight be the result of getting a property with default named height and with a default of 27.94 from page.
The wording is a bit misleading, but I interpret it as "get page height from a property called height", pageHeight seems to be an internal name used in the spec, the actual name of the property in the options object is simply height. (vice-a-versa for width)
So can you try this?: {"width": 29.70, "height": 42.00}
I finally was able find the proper way
{
"page":{
"width": 29.70
,"height": 42.00
}
,"margin":{
"top": 2
,"bottom": 2
,"left": 2
,"right": 2
}
,"scale": 0.5
,"orientation":"landscape"
,"shrinkToFit": true
,"background": true
,"pageRanges": ["1", "1-1"]
}

Selectively removing node labels in D3 force directed diagram

Overall context: I have a db of cross-references among pages in a wiki space, and want an incrementally-growing visualization of links.
I have working code that shows clusters of labels as you mouseover. But when you move away, rather than hiding all the labels, I want to keep certain key labels (e.g. the centers of clusters).
I forked an existing example and got it roughly working.
info is at http://webseitz.fluxent.com/wiki/WikiGraphBrowser
near the bottom of that or any other page in that space, in the block that starts with "BackLinks:", at the end you'll find "Click here for WikiGraphBrowser" which will launch a window with the interface
equivalent static subset example visible at http://www.wikigraph.net/static/d3/cgmartin/WikiGraphBrowser/:
code for that example is at https://github.com/BillSeitz/WikiGraphBrowser/blob/master/js/wiki_graph.js
Code that works at removing all labels:
i = j = 0;
if (!bo) { //bo=False - from mouseout
//labels.select('text.label').remove();
labels.filter(function(o) {
return !(o.name in clicked_names);
})
.text(function(o) { return ""; });
j++;
}
Code attempting to leave behind some labels, which does not work:
labels.forEach(function(o) {
if (!(d.name in clicked_names)) {
d.text.label.remove();
}
I know I'm just not grokking the d3 model at all....
thx
The problem comes down to your use of in to search for a name in an array. The Javascript in keyword searches object keys not object values. For an array, the keys are the index values. So testing (d.name in clicked_names) will always return false.
Try
i = j = 0;
if (!bo) { //bo=False - from mouseout
//labels.select('text.label').remove();
labels.filter(function(o) {
return (clicked_names.indexOf(o.name) < 0);
})
.text(function(o) { return ""; });
j++;
}
The array .indexOf(object) method returns -1 if none of the elements in the array are equal (by triple-equals standards) to the parameter. Alternatively, if you are trying to support IE8 (I'm assuming not, since you're using SVG), you could use a .some(function) test.
By the way, there's a difference between removing a label and just setting it's text content to the empty string. Which one to use will depend on whether you want to show the text again later. Either way, just be sure you don't end up with a proliferation of empty labels clogging up your browser.

NSString boundingRectWithSize bounding not being respected

Does anyone know of a work around or what I am currently doing wrong here.
CGSize boundingSize = CGSizeMake(288, 9999);
CGRect boundingRect = [text boundingRectWithSize:boundingSize
options:NSStringDrawingUsesLineFragmentOrigin
attributes:[NSDictionary dictionaryWithObjectsAndKeys:theFont, NSFontAttributeName, nil]
context:nil];
When the code runs on iOS7 (both on the phone and sim) the size returned is 416.3 wide with a height of 15.5. Clearly the boundingRectWithSize is just being ignored. Has anyone else come across this and if so has anyone an idea on how to fix it or can someone point me to where I am going wrong.
As per the Apple documentation:
You can use this method to compute the space required to draw the
string. The constraints you specify in the size parameter are a guide
for the renderer for how to size the string. However, the actual
bounding rectangle returned by this method can be larger than the
constraints if additional space is needed to render the entire string.
Typically, the renderer preserves the width constraint and adjusts the
height constraint as needed.
If you specify a fixed font and too small a space, something has to give. In this case, it's the bounding space. I'm guessing you expected line wrapping. Does a width of 288 allow any reasonable wraps?
I knows that this is old question, but I found a workaround for your problem. below is the code example
1) First create a macro for minimum height
#define MIN_HEIGHT 10.0f
2) After that use below code to give variable height based on your text specified. But for this you need to specify the frame for UILabel OR whatever you are using for displaying the text.
// Initialize UILabel with initial frame.
UILabel *lblMakeModel = [[UILabel alloc] initWithFrame:CGRectMake(5, 0, 180, 50)];
// Set numberOfLines as zero
lblMakeModel.numberOfLines = 0;
// Set text here
lblMakeModel.text = #"sdbsbdjhsbdhjsbdhjasd bhbdhjasbdsahjdbahjsdbjhsd bdhjsabdhjsbdhsbdhsad dhbsadbasdhbsajhdbsadyogi";
// create a constraint for fixed width and maximum 20000 height.
CGSize constraint = CGSizeMake(lblMakeModel.frame.size.width, 20000.0f);
// Get the CGRect with the given constraint for the text of UILabel
CGRect textRect = [lblMakeModel.text boundingRectWithSize:constraint
options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
attributes:#{NSFontAttributeName:lblMakeModel.font}
context:nil];
// Set LineBreakMode for UIlabel
[lblMakeModel setLineBreakMode:NSLineBreakByWordWrapping];
[lblMakeModel setAdjustsFontSizeToFitWidth:NO];
// Again set the frame from the height you get from CGRect object.
[lblMakeModel setFrame:CGRectMake(lblMakeModel.frame.origin.x, lblMakeModel.frame.origin.y, lblMakeModel.frame.size.width, MAX(textRect.size.height, MIN_HEIGHT))];
There is a real bug still exist in the method "boundingRectWithSize", sometimes it gives wrong width greater than the limited width, i solved it by this work around and get the label height after the method "sizeToFit"
UILabel *textLabel=[[UILabel alloc] initWithFrame:CGRectMake(0, 0,maxTextWidth, CGFLOAT_MAX)];
[textLabel setNumberOfLines:0];
[textLabel setFont:Font];
[textLabel setLineBreakMode:NSLineBreakByWordWrapping];
[textLabel setText:#"Text bla bla bla"];
[textLabel sizeToFit];
float height = textLabel.frame.size.height;

Sizing a spark list

I'm using spark Lists and PopupAnchors to build a drop down menu system, but I'm having trouble getting it to size reliably - the list always seems to want to take up 5 itemRenderers worth of space, but some of the menus I need to implement can be 3 or less items long. How can I have the list dynamically size to the number of elements in it, and no larger?
This is a fun one. You need to set the property on the VerticalLayout of the spark list.
Try this snippet:
(yourSparkList.layout as VerticalLayout).requestedRowCount = yourDataProvider.length;
This assumes you've got a list named yourSparkList and a dataprovider called yourDataProvider which is populating the list.
If your lists get long, you should set a MAXIMUM constant like so:
public static const MAXIMUM:int = 5;
if(yourDataProvider.length <= MAXIMUM){
(yourSparkList.layout as VerticalLayout).requestedRowCount = yourDataProvider.length;
}else{
(yourSparkList.layout as VerticalLayout).requestedRowCount = MAXIMUM;
}
BTW, there's also a requestedMaxRowCount and a requestedMinRowCount property.

Flex Rich Text Editor - Limiting the number of characters

Is there a way to restrict the number
of characters in the Flex Rich Text Editor?
I guess there should be, since it's possible
in a textarea. So, if I could get hold
of the textarea contained in the rich
text editor, I would be able to do it
I think this would be fairly easy in actionscript, although I'm not exactly sure how one would do it in mxml. It appears that there are two children that are contained in the RichTextEditor, one of them being TextArea. According to the documentation (http://livedocs.adobe.com/flex/3/langref/mx/controls/RichTextEditor.html#propertySummary), you can access the subcontrols like so:
myRTE.toolBar2.setStyle("backgroundColor", 0xCC6633);
With myRTE being the instance of your text editor. So my guess would be something like this would work:
myRTE.textArea.maxChars = 125;
With 125 being the number a characters you would want restricted to.
i just ran into this.
setting your maxChars on the textArea will provide a limit to the text area, but that won't be representative of the number of characters the user can type.
as the user is typing, markup is added behind the scenes, and that greatly increases the char count.
for example, if i type the letter 'a' into a RichTextEditor, i get a char count of 142 and this htmlText:
<TEXTFORMAT LEADING="2"><P ALIGN="LEFT"><FONT FACE="Verdana" SIZE="10" COLOR="#0B333C" LETTERSPACING="0" KERNING="0">a</FONT></P></TEXTFORMAT>
i could not see a straightforward way to get a proper maxChar to work out of the box, so i extended RichTextEditor and gave it a maxChar. if maxChar > 0, i added a listener to "change" and did something like this in the event handler:
protected function handleTextChange(event:Event) : void
{
var htmlCount:int = htmlText.length;
// if we're within limits, ensure we reset
if (htmlCount < maxChars)
{
textArea.maxChars = 0;
this.errorString = null;
}
// otherwise, produce an error string and set the component so the user
// can't keep typing.
else
{
var textCount:int = textArea.text.length;
textArea.maxChars = textCount;
var msg:String = "Maximum character count exceeded. " +
"You are using " + htmlCount + " of " + maxChars + " characters.";
this.errorString = msg;
}
}
the idea is to apply a maxChars to the text area only when in the error state, so the user cannot type anything additional and will be prompted to erase some chars. once we leave the error state, we need to set the textArea.maxChars to zero so they can continue.

Resources