Creating a label using NSTextField is blurry - objective-c

I'm trying to create a label programmatically using NSTextField, but it comes out blurry: screenshot
This is my code so far:
NSTextfield *textfield = [[NSTextField alloc] initWithFrame:NSMakeRect(5,5,150,20)];
[texField setStringValue:#"some text here"];
[textField setEditable:NO];
[textField setSelectable:NO];
[textField setBordered:NO]
[textField setDrawsBackground:NO]
I've traced the problem down to the setDrawsBackground line. I've also tried using [textField setBackgroundColor:[NSColor clearColor] as well, but no luck.
By the way, I've adding to a textField to the subview of a view that is a subview of a scrollview. I've also playing with isOpaque on all the view levels, but no luck there again.
Any help is greatly appreciated.

If you have no background (including clear) and your text is a subview of any layer-backed superview (you've turned on "wants layer" in code or in IB to allow animations/transitions), you'll get blurry text. You have to choose either no layer backed view or a label with a solid background color.

I had the same problem, but I have solved it by:
textfield.canDrawSubviewsIntoLayer = true

Make sure you're setting the frame of your NSTextField to something with all integer values.
Use roundf() if necessary.
I was getting a blurry NSTextField, and neither adding a solid background nor removing Core Animation layers from my view hierarchy were options for me. I noticed I was setting the frame of this text field to something with a Y value of 4.5, so the following changes fixed the issue for me:
Blurry label:
_label.frame = NSOffsetRect(_labelFrame,
-0.5 * (someRect.size.width + someConstant),
0.0);
No blur:
_label.frame = NSOffsetRect(_labelFrame,
roundf(-0.5 * (someRect.size.width + someConstant)),
0.0);
(In the above examples, _labelFrame and someRect are NSRects, and someConstant is a CGFloat. As you can see, the calculation I was doing in the second line of the first example was passing a non-integer value to NSOffsetRect).

Since this was my first time subclassing NSView, I had put the above code in the drawRect method instead of the initWithFrame method. I did this because I was following one of the sample applications from Apple's Dev site.
This was also causing my CPU usage to spike when I was scrolling

If you created it via an XIB and it is blurry, I found the fix:
[textField setStringValue:#""];
If I comment this out it goes blurry; if put back it's crystal clear.

Try this below:
textField.drawsBackground = true
textField.backgroundColor = NSColor.white.withAlphaComponent(.leastNormalMagnitude)

Out of the box, but worth to mention. I have wasted by entire day debugging the issue. I am using a non-apple external monitor and this is where the issue is identified. Once i open the app in Mac book pro, it is perfectly fine.
So, the Samsung monitor which i am using might be non-retina.

Simply, add
CanDrawConcurrently = true
property from InterfaceBuilder

Related

Setting UITextView frame to content size no longer works in Xcode 5

The code snippet below worked to resize a UITextView frame to it's content height, before installing Xcode 5 but it doesn't work since the upgrade:
CGRect frame = _textView.frame;
frame.size.height = _textView.contentSize.height;
_textView.frame = frame;
I've searched and haven't found the fix. Any thoughts?
There's new stuff for this on iOS 7.
To get the "fitted" size used by the text view after it's updated its text, call usedRectForTextContainer: on the textView's layoutManager property, passing the textView's textContainer property as an argument.
Word of warning about scrolling: Be advised, though, that changing the frame size of a text view after it has updated it's text can have unexpected visual bugs if scrolling is disabled on your text view. If this happens, set scrolling enabled before editing the text of the text view, then disabling it after it's updated (if you need scrolling to remain disabled).
To work in iOS 7 (Xcode 5), just:
Give the entire space to receive the text, by setting:
[myTextView setScrollEnabled:YES];
Pass the real text:
myTextView.text = theTextVariable; or myTextView.text = #"The text...";
Autoresize textView:
[myTextView sizeToFit];
Disable scroll:
[myTextView setScrollEnabled:NO];
P.S: myTextView can be use also as self.myTextView or _myTextView
And have fun!
I believe the correct way to force a textView to update its contentSize is by calling
[textView layoutIfNeeded]
However, in iOS 7.0 and 7.1 this seems still not to work reliably unless you first set
textView.layoutManager.allowsNonContiguousLayout = false;
It's not clear to me whether this is a bug or not since I can't really find a good explanation of what "non-contiguous layout" even means.
(My personal use case is updating textView.text = newValue programmatically, then trying to resize the textView appropriately.)
[textView sizeToFit];
Is what you need.
All you need to do is make sure that:
[textView setScrollEnabled:YES];
BEFORE you set the UITextView text content.
You can then:
[textView sizeToFit];
[textView setScrollEnabled:NO];
After you've set the text. Same as writing your own bling function or employing complicated bounding rect methods. Why use something so complicated when the solution is as simple as three lines?
That said, wrap those functions like so:
- (void) setText:(NSString *)theTextToAdd andResizeTheDamnTextView:(UITextView *)textView {
[textView setScrollEnabled:YES];
[textView setText:theTextToAdd];
[textView sizeToFit];
[textView setScrollEnabled:NO];
}
And define it in a per-file or global basis to avoid having to manually write or copy/paste the four lines and call it every time. Just call it as:
[yourTextViewIvar setText:#"DUMMY STRING" andResizeTheDamnTextView:yourTextViewIvar];
If that doesn't work:
[yourTextViewIvar setText:[self setText:#"DUMMY STRING" andResizeTheDamnTextView:yourTextViewIvar]];
And you'll be golden.
I think..
That's Pseudocode. Just FYI.
A easier solution is use that:
[textViewExample sizeToFit];
This work for me.

UITextView setTextColor changes layout in UITableViewCell

I am trying to use the solution on the following page:
UITextView highlightedTextColor or similar option?
However, I am finding that when I call setTextColor on my UITextView and set the color to anything other than Color blackColor, the content in the UITextView appears shifted, and the color I do set it to doesn't take.
Playing around, I can repeat this behaviour by modifying the following initialization code in my UITableViewCell:
_notesTextView = [[UITextView alloc] initWithFrame:CGRectZero];
[_notesTextView setFont:[UIFont systemFontOfSize:12.0]];
[_notesTextView setTextColor:[UIColor redColor]];
[_notesTextView setUserInteractionEnabled:NO];
[self.contentView addSubview:_notesTextView];
The code above will cause the textView to display offset from what I expect, as compared to when I leave the color defaulted or set to blackColor, and the text doesn't show as red either.
This is so weird - any idea what could be wrong?
Do Not Use CGRectZero as it initiates the frame to some value you might know depending upon situation so if you have created a custom UITableViewCell then just set the frames in init or
-(void)layoutSubViews
{
}
I've confirmed that the textColor does indeed shift the text position (up and down for me). I've also tried it with initWithFrame(50, 20, 250, 31), and still experience the same problem.
What I've discovered fixes this issue is using the property textAlignment and setting it to one of the values: UITextAlignmentCenter, UITextAlignmentLeft, UITextAlignmentRight.

Overriding layoutSubViews: causes "CGAffineTransformInvert: singular matrix" randomly

I'm overriding layoutSubViews: in a UIScrollView and from time to time I get "CGAffineTransformInvert: singular matrix" for every subview I reposition. The layout looks totally okay however.
The app does not crash either.
Does anybody know what causes this?
I once had this error cause by mistake was setting a font with size 0 when using
[UIFont fontWithName:size:]
for a UILabel.
In case anyone else is struggling with this (and in case it's not because of setting the label font size to 0), "CGAffineTransformInvert: singular matrix" seems to come up when layoutSubViews: runs on a view (such as UIScrollView or UILabel) that has a frame of size (0,0).
Took me forever to figure out because if your container view (e.g. the scroll view) is not set up to clip subviews, the layout will still look fine.
I was seeing this problem too when I added a UIWebView to my self.view.
The offending code was:
UIWebView *wv = [[UIWebView alloc]init];
and the solution is:
UIWebView *wv = [[UIWebView alloc]initwithFrame:[[UIScreen mainScreen]bounds]];
or any framesize except 0.0.
In my application I got this error as I forget to call the -layoutSubViews of the superClass in the overridden -layoutSubViews method,
so make a call [super layoutSubViews] at any point in your overridden method

Custom Keyboard: inputView: how to change the Keyboard size?

I implemented the textfield with a custom keyboard with the "setInputView" function.
But i have a problem: my keyboard frame is not a standard iphone keybord frame.
The question is:
How can i change the size of my custom keyboard?
I know some functions like: UIKeyboardFrameBeginUserInfoKey, ..etc.
Please Note:
The iPhone keyboard frame is = 0,264,320,216
My custom keyboard frame is = 0,0,320,460
Hoping for your kind collaboration,
Best regards...
P
It turns out that the default behaviour of the custom input view that you assign to the UITextField's property is to resize the view to the same frame as the default keyboard. Try setting (I use the name InputViewController for my input view, but you can use whatever you want):
inputViewController = [[InputViewController alloc] initWithNibName:#"InputViewController" bundle:nil];
inputViewController.delegate = self;
inputViewController.view.autoresizingMask = UIViewAutoresizingNone; // This is the code that will make sure the view does not get resized to the keyboards frame.
For more detailed information, you can look at this link, which is provided by Apple.:
If UIKit encounters an input view with an UIViewAutoresizingFlexibleHeight value in its autoresizing mask, it changes the height to match the keyboard.
Hope that Helps!
To set the keyboard inputView with the same size as the native keyboard just do this:
inputView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
To set your own frame do this:
inputView.autoresizingMask = UIViewAutoresizingNone;
From Apple:
You have a lot of flexibility in defining the size and content of an input view or input accessory view. Although the height of these views can be what you’d like, they should be the same width as the system keyboard. If UIKit encounters an input view with a UIViewAutoresizingFlexibleHeight value in its autoresizing mask, it changes the height to match the keyboard. There are no restrictions on the number of subviews (such as controls) that input views and input accessory views may have. For more guidance on input views and input accessory views, see iOS Human Interface Guidelines.
I had the same problem. I solved it by registering for UIKeyboardDidShowNotification (UIKeyboardWillShowNotification did not work, unfortunately) and then changing the view size after the keyboard was shown. However, it still had the white box on top of the keyboard when it was moving up. This worked fine for me because it is coming in over a UITextView with a white background. If you were coming in over any other colored objects, however, it would look a little ugly before the view was properly resized. You can solve that by setting the background color to clearColor.
// Add this while initializing your view
self.backgroundColor = [UIColor clearColor]; // Needed because we can't resize BEFORE showing the view. Otherwise you will see an ugly white box moving up w/ the keyboard
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
CGRect rect = self.frame;
rect.size.height = 164;
self.frame = rect;
}
Also if you're using a UIViewController to design your inputView, don't use the UIViewController.view... it seems to have a lot of problems getting resized incorrectly on rotate regardless of the AutoresizeMask.
What worked for me was to take my existing UI and use Editor > Embed In > View. Then create a new outlet, and pass that outlet as the inputView. Suddenly the resize on rotate bugs disappeared.
For me msgambel's solution didn't work. But the approach right, I was playing with the inputView's autoresizingMask. Former I had different setting, but the right way to avoid white extra space over the custom keyboard is:
I applied this just for the outermost view.

Resizable UILabel which scrolls across the screen

Right, I'm trying to get a label with text in it (done already obviously), which scrolls across the screen.
The text that is input into the label is done by a UITextField and a UIButton. This updates fine.
But I'm trying to get the UILabel to resize accordingly to the amount of text input, so that the WHOLE lot of text scrolls across the screen.
This is the code I have at the moment for the scrolling label:
[lblMessage setText: txtEnter.text];
CABasicAnimation *scrollText;
scrollText=[CABasicAnimation animationWithKeyPath:#"position.x"];
scrollText.duration = 3.0;
scrollText.repeatCount = 10000;
scrollText.autoreverses = NO;
scrollText.fromValue = [NSNumber numberWithFloat:500];
scrollText.toValue = [NSNumber numberWithFloat:-120.0];
[[lblMessage layer] addAnimation:scrollText forKey:#"scrollTextKey"];
The problem is, sometimes is starts scrolling in the middle of the screen, and sometimes vanishes before it has fully gone acrosss.
It also cuts of text due to the label being one size.. I don't know how to change this.
Thanks in advance.
Dom
I believe something similar to the solution for this question would work for this case.
You could embed the UILabel in a UIScrollView, with the UIScrollView set to the max size of the label that you want to display on the screen at one time. The UIScrollView would need to have its scroll indicators turned off using its showsHorizontalScrollIndicator and showsVerticalScrollIndicator properties. On a change of text, you could do the following:
[lblMessage setText: txtEnter.text];
[lblMessage sizeToFit];
scrollView.contentSize = lblMessage.frame.size;
followed by the panning animation code as described in the above-linked question, with the frame to be panned to being the far right of the UILabel. This would cause the text to scroll at a constant rate across the label. If you want the label to scroll back to the beginning, you could use the UIView setAnimationRepeatAutoreverses: and setAnimationRepeatCount: methods in the beginning of your animation block.
The label resize worked great thanks!
Now, i've put the label into the scrollview and i've got that showing up.. but I'm now not sure of the exact animations to add to that. I tried some of the ones on the link you gave me, but they're not working.
EDIT: Nevermind, I've got it all working now.
CGPointMake(x, x) is what i needed for the contentOffset.