NSString boundingRectWithSize bounding not being respected - nsstring

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;

Related

Mathematically scale large elements lesser then small elements

10 elements with the class xxx have different widths and heights. Putting transform: scale(1.1) enlarges the big ones clearly but the small ones barely show difference. This is bad UX. The mathematical question is how to make the bigger elements scale less then the smaller ones:
width 10 should get scale 1.1
width 5 should get scale 1.2
How can i mathematically solve this?
The question lacks context and details, so it is hard to give a generally meaningful answer. However, the given examples indicate the following solution:
x_new = 1 + 1/x_old
Where x_old is the input value, i.e. 10 or 5.
Using logarithmic scaling instead of just 1/x_old might be another option, depending on the context.
To illustrate the scenarios i made these pens:
non logarithmic scale: http://codepen.io/anon/pen/bwRVpj
logarhitmic scale: http://codepen.io/anon/pen/VKWLJK
var inlineStyle = ''
var divs = document.getElementsByTagName('div')
var len = divs.length
while(len--) {
var elWidth = divs[len].offsetWidth
var scale = 1+9/elWidth
inlineStyle += `#${divs[len].id}:hover {
transform: scale(${scale})
}`
}
document.getElementById('lolStyle').innerHTML = inlineStyle

How to make a very large skybox? (babylon.js)

How can I make a very large skybox?
Example:
var skybox = BABYLON.Mesh.CreateBox("skyBox", 15000.0, this.scene);
The result is bad:
The first thing I suggest is to reduce the scale factor of your spaceship and planet models. It seems that having a SkyBox size larger than 10000 causes the ugly texture seams/tearing of the Skybox at particular camera angles and distances. So bring everything down in scale if possible to make more room inside the limits of the Skybox perimeter.
Next try this: set .infiniteDistance = true to keep the Skybox away from the camera, and also set .renderingGroupId = 0 on the Skybox. Lastly, set .renderingGroupId = 1 or more, on all the models and objects to help stop them from disappearing into thin air.
var skybox = BABYLON.MeshBuilder.CreateBox("skyBox", {size:10000.0},
this.scene);
skybox.infiniteDistance = true;
skybox.renderingGroupId = 0;
...and for models and sprite objects...
myModel.renderingGroupId = 1; /* greater than 0 */
These little tricks helped me to achieve a to-scale solar system simulation, but may not work in all cases.
Hello you need to increase camera.maxZ to a value larger than your skybox.

How come sizeHint() is QSize(-1, -1)?

For the following, I get self.page1.sizeHint() and self.page1.minimumSizeHint() both as QSize(-1, -1). Does anyone know why? I was expecting the minimum size hint should be at least the size of the label.
# ...
self.page1 = QtGui.QWidget()
self.page1.setObjectName("page_General")
self.label_Server = QtGui.QLabel(self.page1)
self.label_Server.setGeometry(QtCore.QRect(20, 20, 39, 13))
self.label_Server.setObjectName("label_Server")
print self.page1.sizeHint(), self.page1.minimumSizeHint()
Thanks
The default implementation of sizeHint():
This property holds the recommended size for the widget.
If the value of this property is an invalid size, no size is
recommended.
The default implementation of sizeHint() returns an invalid size if
there is no layout for this widget, and returns the layout's preferred
size otherwise.
Same goes for minimumSizeHint.

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

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)

Flex Charts: Can you use a minimum/maximum point from an IAxis for Cartesian Data Canvas to draw the entire width of the chart?

I have a chart with a DateTime axis as my horizontal and a Linear Axis for my vertical inside a Adobe Flex Line Chart. I want to use a Cartesian Data Canvas as a background element and draw custom set of background graphics mostly rectangles. When I have more than a single data point, the graphics work perfectly since they are supposed to span the width of the entire chart.
When I have only a single data point, however, I can't seem to get the rectangles to draw. Since I want my rectangles to span the entire width of the chart, I was thinking that I could get the x-coordinates from my axis, but this isn't working.
var canvasWidth:Number = chtCanvas.width;
var canvasHeight:Number = chtCanvas.height;
var minPt:Array;
var maxPt:Array;
var minPtDate:Date;
var maxPtDate:Date;
var minPtComplete:Point;
var maxPtComplete:Point;
// This works fine when there is more than 1 data point
minPt = chtCanvas.localToData(new Point(0, 0));
maxPt = chtCanvas.localToData(new Point(canvasWidth,canvasHeight));
//This does return a date object, but wont draw below
minPtDate = axisDate.minimum;
maxPtDate = axisDate.maximum;
//This returns NaN for the x
minPtComplete = chtCanvas.dataToLocal(minPtDate, axisSalary.minimum);
maxPtComplete = chtCanvas.dataToLocal(maxPtDate, axisSalary.maximum);
// Also tried this. Also returns NaN for the x value
//minPtComplete = chtCanvas.dataToLocal(axisDate.minimum, axisSalary.minumum);
//maxPtComplete = chtCanvas.dataToLocal(axisDate.maximum, axisSalary.maximum);
My actual drawing method is as follows:
// Tried this, works with points >2, does not draw with single data point
chtCanvas.drawRect(minPt[0], detail[i].MaxValue, maxPt[0], detail[i].MinValue);
//tried this, no effect with single point
//chtCanvas.drawRect(minPtDate, detail[i].MaxValue, maxPtDate, detail[i].MinValue);
// Tried this, no effect with single point
//chtCanvas.drawRect(minPtDate, minPt[1], maxPtDate, detail[i].MinValue);
// Tried this also
//chtCanvas.drawRect(minPtComplete.x, detail[i].MaxValue, maxPtComplete.x, detail[i].MinValue);
In this example, detail is an array collection of salary values and Im using the data value in the array to determine the vertical bounds of my rectangles.
I need to draw the rectangles the entire width of the chart (even when there is only a single data point). Thanks
Thanks to Heikki for his help. The following code works to use the axis values to draw on your Cartesian Data Canvas:
chtCanvas.drawRect(axisDate.minimum as Date, axisSalary.maximum, axisDate.maximum as Date, axisSalary.minimum);
Casting the values as Date really helped. The rest of the code used above is unecessary.
One thing to note, I was using a DateFormatter to format the date values from my data. What I didn't consider was that when using a DateTimeAxis, Flex will automatically add in extra dates to display on the axis. In my case, I was using a custom parse function to create MY points, but wasnt considering the points Flex was creating and also passing to my parse function (Therefore, they were not getting parsed correctly). Once I corrected this, the values laid out correctly in the case of multiple data points. I'm still having a bit of an issue with single data points and them not filling the chart entirely, but they are now drawing.
UPDATE:
Although there are signs of life, the minimum and maximum are still not drawing the entire width of the chart in some cases depending on the dataUnits and labelUnits combination.
UPDATE #2: SOLVED
Ok, so the axis does work as minimum/maximum values for the Cartesian Data Canvas but there is something important to remember. For a single point (and probably for multiple points as well, I just couldnt visually see the difference), when using a custom DateTimeAxis parse function such as what was in the Adobe Flex ASDoc tutorials:
private function axisDateParseFunction(item:String):Date
{
var inputDate:String = item;
inputDate = fmtDate.format(inputDate);
var newDate:Date = new Date();
if(inputDate)
{
var a:Array = inputDate.split('/');
newDate.fullYear = a[2];
newDate.month = a[0] - 1;
newDate.date = a[1];
newDate.hours = 0;
newDate.hoursUTC = 0;
newDate.minutes = 0;
newDate.minutesUTC = 0;
newDate.seconds = 0;
newDate.secondsUTC = 0;
newDate.milliseconds = 0;
newDate.millisecondsUTC = 0;
}
return newDate;
}
You MUST remember to set the UTC values as shown above also. Since the DateTimeAxis uses date AND time, when you create new Date objects, their time values also get set to the local system time. Remember to set those values to zero also or you will get points that dont exactly line up with your axis labels.

Resources