I have a UITextView and I am inserting images into using NSTextAttachment. The problem is that when the user moves the cursor after the image and begins to type text, instead of using the font used everywhere else in the UITextView, it resets to a smaller font.
How can I make sure that the font that is typed after an image is the same font as the one typed elsewhere?
I ended up reseting the typingAttributes after each time the cursor is changed. I have not found any cases where this doesn't work as expected.
extension ViewController: UITextViewDelegate {
func textViewDidChangeSelection(textView: UITextView) {
textView.typingAttributes = defaultAttributes
}
}
Related
I'm trying to set the background color of the text field in my search bar to a custom color. I looked at the answer here to no avail:
Cannot change search bar background color
See how that search bar has a red text field? I followed the code and can even verify that the UISearchBarTextField object was found and the background color of it is being set to UIColor.red, but the color does not change.
I've messed around with all the background colors of the superviews with hopes that it might help but I cannot get that color to change. Maybe there's some new trick or someone can shed some light on something that may be overriding the color somehow.
extension UISearchBar {
var textField: UITextField? {
return subviews.first?.subviews.first(where: { $0.isKind(of: UITextField.self) }) as? UITextField
}
}
searchBar.textField?.backgroundColor = UIColor.red // <-- Not working
let textFieldInsideUISearchBarLabel = searchBar.textField?.value(forKey: "placeholderLabel") as? UILabel
textFieldInsideUISearchBarLabel?.textColor = UIColor.lightGray
Note that the text inside the UITextField object is changing to the lightGray like I want it, just not the UITextField background color.
After a long wait for an answer, I decided to try some experiments. I created a new project, dragged a search bar, connected it to the ViewController, added the UISearchBar extension, and set the color - exactly the same as I did in my main project.
Voila! It does set the background color as it should, and as it shows in the linked topic in the main question.
So, I put the projects side by side, opened the storyboard in each of them and started setting the properties of the searchBar, one at a time, until I could see why the bar is not being set like it should in the main project.
The very first thing I tried was, search style. My project has it set to "Minimal". I changed it to "Minimal" in the test project and noticed right away that the color was no longer set.
So, setting the "Search Style" property of the searchBar in the main project to "Default" allowed that background color to be set.
I would appreciate it greatly if anyone could comment and say why it is that I can't use "Minimal" if I want to customize the background color, or how I could make it work.
I have a Cocoa app that shows a "quick search" window similar to Spotlight. The window contains a visual effect view and inside a NSTextField. The text field stretches across the full width of the window.
I would like to be able to move the window by dragging inside the empty area of the text field. When dragging across text in the text field, the normal editing (i.e. selection) behavior should be used instead.
In theory, moving a window by its background is easy:
window.isMovableByWindowBackground = true
However, this behavior does not work with NSTextField, because it intercepts dragging and attempts to select text instead.
Spotlight does it somehow. Here's an example:
A couple of options that I considered without success:
Tried overriding hitTest: returning nil
Tried overriding mouseDown|Up|Dragging: and forwarding to superview
Tried to use autolayout to have text field shrink to tightly wrap around its text (could not figure this one out)
For reference, I finally found a way:
Part 1: get NSTextField to grow/shrink with its content
Override intrinsicContentSize and measure its content:
private func measure(_ string:NSAttributedString) -> NSSize
{
let cell = NSTextFieldCell(textCell: stringValue)
cell.attributedStringValue = string
return cell.cellSize
}
Part 2: view setup
Add a placeholder view right after the text field
Set up auto layout to have the placeholder view to grow and shrink
Part3: all about the details
Set up the placeholder view to use the iBeam cursor to make it appear like a text field
If the user clicks in the placeholder view, make the text field the first responder
That's it.
UPDATE:
I've added a sample project for testing, see at the bottom of the post.
ORIGINAL QUESTION:
I've got an NSWindow and I change its background when some other parameters change.
The window background is a gradient I'm drawing by overriding drawRect in a subclass of the window's view.
class MainWindowView: NSView {
override func drawRect(dirtyRect: NSRect) {
var rect = dirtyRect
let gradient = NSGradient(startingColor: backgroundColor, endingColor: darkerBackgroundColor)
gradient.drawInRect(rect, relativeCenterPosition: NSPoint(x: 0, y: 0))
super.drawRect(rect)
}
}
And I've got two NSTextFields on this window.
The NSTextFields are both set to drawsBackground = false in awakeFromNib and set to borderless in IB.
I'm not using NSAttributedStrings here, only changing the stringValue of the NSTextFields, and of course their textColor.
Everything is working... except that sometimes, the text fields have an unexpected slightly dark semi-transparent background.
(It's hard to see on some screens but it's there.)
Question: why does this darker background appear?
And of course: what could I do to fix it?
I'm pretty sure it's the gradient that breaks something but I can't find what...
Note: the project is in Swift but I can read an Objective-C answer.
EDIT:
So indeed it seems to be coming from the gradient that's behind, see this other screenshot from a test window. This time the gradient is drawn in a Custom View under an NSTextView, and the same undesired effect happens: parts of the text field background are visible but shouldn't.
UPDATE:
I have made a very simple example in a project for testing, with a gradient that shows the phenomenon more visibly. There's only a window, my gradient class and a text field. You can get it (30ko only) in this ZIP file.
You always draw the gradient in the dirty rect. When the text changes, that rect is only the size of the textfield, not of the whole view. Your drawRect function then draws the full gradient in the textfield's background rect, rather than just the portion of the background-view-wide gradient you'd see through the textfield.
If you redraw using your view's frame, and ignore the dirty rect argument, you should get the desired appearance.
I'm guessing your text field isn't layer-backed. If not, turn on layers (in IB or via -wantsLayer for the view in code) for at least the text field. If that alone doesn't work, try turning on layers for the gradient-hosting view as well.
I have 2 sets of images. One set contains draggable ones and other is a static set. I have implemented drag-drop functionality for the draggable images. This is because the images needs to be dragged to static ones which contains matches. Now after placing the dragged image on the static one, there is nothing to do with it, hence I want to disable user interaction for image (since it's still draggable).
I have explored several solutions and SO questions here and there , but none of the solutions helped!
Can some one please help me how to remove dragging or user interaction for NSImageView?
Thanks everyone in advance :)
Create custom class of NSImageView and implement mouse entered and mouse exit method with empty definition
The easiest solution in my opinion is subclassing NSView. Your custom view should just contain an image variable you want to draw inside. After that you can use your custom view instead of default NSImageView, it will pass mouse events through.
Example:
class ImageView: NSView {
var image: NSImage?
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
if let image = image {
image.draw(in: bounds)
}
}
}
Be noted that the target image will be scaled non-proportionally to your ImageView instance size.
I have a custom view in a .xib file, which I use as the contentViewController for an MAAttachedWindow. The view has several NSTextFields in it.
When I open the MAAttachedWindow first time, everything is fine. Text shows up in all relevant text fields. Then, if I close the window (which sets it to nil) and then call it again (which reinitializes, using the same custom view as the contentViewController), the last firstResponder text field is now blank.
The strange thing is that if I click the "empty" text field, it shows the correct text. This can be edited, and behaves appropriately as long as this text field has focus. As soon as something else becomes firstResponder, the text vanishes again.
Updates:
Changing the color did not change the aforementioned behavior.
The text color does not change at any time during this process.
Placeholder text also is subject to the aforementioned behavior.
No errors are occurring at any time during this process.
This does not happen to NSSecureTextFields.
I first encountered this problem about 5 years ago with accessory view of a NSSavePanel.
The solution that I've found was to move the first responder to the panel itself, before it's closed. Here's my exact method:
- (void)windowDidEndSheet:(NSNotification *)notification
NSSavePanel *savePanel = [(XSDocument *)[self document] savePanel];
if (!savePanel)
return;
// this fixes a bug where on next opening one of accessory view's text field will be blank and behave strangely
[savePanel makeFirstResponder:savePanel];
}
Try changing color of textfield text to red color (or any other color) you may get what happens here.
I got it!
I simply needed to explicitly remove the viewController from its superview before closing (and subsequently deallocating) the MAAttachedWindow.
Try resigning all first responders before setting the window to nil.