Disabling UITextView Keyboard input but enable user interaction swift 2 - swift2

Hi I am new to swift and I have implemented a picker view that alter the text in my UITextField.
However the keyboard cursor will still show up, is there any way to remove the keyboard cursor?

Simple
Go to storyboard -> Select textfield -> properties -> set tint color to clear color
Or UITextField.appearance().tintColor = UIColor.clear

Implement this method in your UITextFieldDelegate:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
return false
}
This disables typing, copy&pasting and deleting.
If you prefer to not show the keyboard or cursor at all, you can avoid the textfield to become the first responder and show your custom picker instead:
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
// Show your picker here, and return false to avoid showing keyboard
return false
}

Related

I want to use it as a UIButton when I tap UITextField

I created a custom keyboard screen on tvOS.
If possible, tap on UITextField as it is, I want to transition to the custom keyboard view.
But tapping the UITextField always displays the system keyboard.
What should I do now?
1) Make the view controller implement this delegate: UITextFieldDelegate
class YourViewController: UIViewController, UITextFieldDelegate {
// ...
yourTextField.delegate = self
// ...
}
2) Return false in textFieldShouldBeginEditing, so the text field doesn't respond and the keyboard doesn't open. Instead, open yours or do whatever you want.
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
// HERE, open your keyboard or do whatever you want
return false
}
textField.inputView = UIView()
class YourViewController: UIViewController,UITextFieldDelegate { }
First set your delegate for textfieldtextField.delegate = self, Then
func textFieldDidBeginEditing(_ textField: UITextField) {
textField.addTarget(self, action: #selector(gettextFieldFunction), for: UIControlEvents.touchDown)
}

View based NSTableView: Empty/white labels on dragging

I setup a trivial view based NSTableView, the view is a simple NSTextField used as a label:
func tableView(_ tv: NSTableView, viewFor tc: NSTableColumn?, row: Int)
-> NSView?
{
let v = (tv.makeView(withIdentifier: viewID, owner: nil) as? NSTextField)
?? NSTextField()
v.isSelectable = false
v.isEditable = false
v.stringValue = data[row] // [String]
v.identifier = viewID
return v
}
and then I enable dragging of the items using this delegate method:
func tableView(_ tableView: NSTableView, pasteboardWriterForRow row: Int)
-> NSPasteboardWriting?
{
return MyPasteboardItem(value: data[row])
}
This works, but when I drag the row, I get an empty representation of the textfield:
(in a different setup things like image views and buttons get drawn, but the NSTextField also ends up white).
I highly suspect this is due to the NSTextField being backed by a TextLayer which doesn't get drawn if the tableview captures an image of the view hierarchy being dragged.
What is a good way to fix this? I considered implementing draw(), but well.
Update: If I do an own NSTextField subclass and override draw(), it indeed starts to work:
final class MyTextField : NSTextField {
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
}
}
Looking at the thing in the view debugger shows that the Layer switches from NSTextLayer to _NSViewBackingLayer when draw is overridden.
But I assume this is not exactly desirable? Is there a better way to accomplish this?
Complete sample: https://gist.github.com/helje5/48728983951ab3362af43b967c554475
Setting drawsBackground=false on the textfield fixed it for me.
If you are using xib file then untick "Draws Background" on the Text Field or in your viewFor: method something like:
v.drawsBackground = false;
I ended up with this in an NSTextField subclass, not sure whether it is a good idea:
override public func draw(_ dirtyRect: NSRect) {
// This switches from the UXLabel being backed by `NSTextLayer` to
// `_NSViewBackingLayer`, which may not be desirable.
// BUT: This enables proper drawing of the Drag&Drop cell.
super.draw(dirtyRect)
}

Programmatically collapse a group row in NSOutlineView

I have an NSOutlineView with an action (see code) that collapse a row when the user clicks anywhere on that row. However it is not working for group.
Some rows are defined as group via the "shouldShowOutlineCellForItem" delegate method.
I can expand a group row programmatically, but not collapse it. Any suggestions?
isExpanded is correctly set via the notifications.
#IBAction func didClick(sender: AnyObject?)
{
assert(self.root != nil)
let selectedRow = outlineView.clickedRow
let proposedItem = (selectedRow == -1) ? self.root! : outlineView.itemAtRow(selectedRow) as! thOutlineNode
if proposedItem.isExpanded
{
self.outlineView.collapseItem(proposedItem)
}
else
{
self.outlineView.expandItem(proposedItem)
}
}
Possibly duplicate. Based on this existing SO question covering Objective-C, try adding the NSOutlineViewDelegate delegate method
func outlineView(_ outlineView: NSOutlineView, shouldShowOutlineCellForItem item: AnyObject) -> Bool {
return true
}
to the view controller of your NSOutlineView. From the Apple documentation for the NSOutlineViewDelegate, we see that this is expected behaviour:
optional func outlineView(_ outlineView: NSOutlineView,
shouldShowOutlineCellForItem item: AnyObject) -> Bool
...
Discussion
Returning NO causes frameOfOutlineCellAtRow: to return NSZeroRect,
hiding the cell. In addition, the row will not be collapsible by
keyboard shortcuts.

How do i dismiss the keyboard on return key from a UITextView

How do I dismiss the keyboard by pressing the return key on device? I know how to dismiss keyboard, but not when using the UITextView:
resignFirstResponder
I have tried this, but it does not work:
self.messageTextView.delegate = self
And with this function:
func messageTextViewShouldReturn(textView: UITextView) -> Bool
{
self.messageTextView.resignFirstResponder()
return true
}
Remember to add the UITextDelegate into ViewDidLoad()
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
if text == "\n"
{
textView.resignFirstResponder()
return false
}
return true
}
Swift 5
unlike a textField where IBActions are available, there are no actions available for text views.
create your textViewOutlet
If you are using a tableview:
identify where your textView row is located:
let textViewIndex = IndexPath(row: 0, section: 1)
then in (_:didSelectRowAt:) dismiss the keyboard if any row other than your textView
if indexPath != textViewIndex {
textViewOutlet.resignFirstResponder()
}
if you are not using a tableview: In your SB viewcontroller, drag a UITapGestureRecognizer to your view. Then create an IBAction from that Tap Gesture Recognizer by control dragging it to your view. In the action dismiss your keyboard from your textViewOutlet:
#IBAction func tapGestureRecognizer(_ sender: Any) {
notesField.resignFirstResponder()
}

Growing NSTableView Row Height

I have a view-based NSTableView in a MacOSX app that structures data nicely. I would like to implement the NSTableView to have row heights which grow with the content of the data entered into one of the NSTextViews. I've subclassed an NSTextView to "grow" with the user text but the issue is that having the field embedded in the TableView causes the field to be clipped.
Does anyone have any suggestions as to how to go about implementing a growing row size?
You need to implement -tableView:heightOfRow: in your table view delegate and return the appropriate height for the row. Furthermore, you need to monitor the text views for changes in their height and call -noteHeightOfRowsWithIndexesChanged: on the table view when any of them changes. To monitor the height of the text views, it should suffice to observe the NSViewFrameDidChangeNotification that they will post.
(If you're using auto layout generally in your UI, I think you will have to leave the text views with translatesAutoresizingMaskIntoConstraints on, place them manually, and set their autoresizing masks as appropriate. Then, you would avoid setting any other constraints on them. This is because you need the frame to be set by the text layout manager but not by auto layout.)
I've managed to implement this in Swift 3 (with the help of this great tip and this and this SO answer):
Make sure the table view cell in the NSTableView has a delegate connection to your subclass/view controller which adopts the NSTextFieldDelegate protocol.
Also give it these constraints to make sure it resizes according to the height of the row:
In the delegate use this code:
var editedString: String? = nil
var textCellForHeight: NSTextFieldCell = NSTextFieldCell.init()
func control(_ control: NSControl, textShouldBeginEditing fieldEditor: NSText) -> Bool {
editedString = fieldEditor.string ?? ""
return true
}
func control(_ control: NSControl, textShouldEndEditing fieldEditor: NSText) -> Bool {
editedString = nil
return true
}
func control(_ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
if commandSelector == #selector(insertNewline(_:)) {
textView.insertNewlineIgnoringFieldEditor(self)
editedString = textView.string ?? ""
//The NSAnimationContext lines get rid of the animation that normally happens when the height changes
NSAnimationContext.beginGrouping()
NSAnimationContext.current().duration = 0
myTableView.noteHeightOfRows(withIndexesChanged: IndexSet.init(integer: selected))
NSAnimationContext.endGrouping()
myTable.needsDisplay = true
return true
}
return false
}
func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
if let temp = editedString { //we know it’s currently being edited if it’s not nil
textCellForHeight.stringValue = temp
//in my case, there was a specific table column that I knew would be edited
//you might need to decide on the column width another way.
let column = myTable.tableColumns[myTable.column(withIdentifier: “TheColumnThatsBeingEdited”)]
let frame: NSRect = NSMakeRect(0, 0, column.width, CGFloat.greatestFiniteMagnitude)
return textCellForHeight.cellSize(forBounds: frame).height
}
return yourStandardHeightCGFloat
}

Resources