How to change shape of the UITextField? - ios

I want to implement custom text fields. Here is a screenshot of what I want to implement:
So I have a UITableView with cells, and in each cell I have several text fields: one for date, one for name, one for theme, and one for text. But the UI requires theme and text to be next to each other (as can you see in the picture). I wanted to implement this as a single UITextField, but as far as I know, UITextField supports only one type of font. So maybe someone will give me a piece of advice how to implement the design shown in the screenshot — do I have to draw custom text fields, or are there simpler solutions? Any code samples or propositions would be helpful.

For iOS 6:
You can set a UITextField's attributed string:
#property(nonatomic,copy) NSAttributedString *attributedText;
I suggest to use a NSMutableAttributedString and to exploit polymorphism.
A mutable attributed string can hold vary attributes for each piece of the string. So you can add an attribute only for a certain range of the string with this method:
- (void)setAttributes:(NSDictionary *)attributes range:(NSRange)aRange;
For iOS 5:
Use directly this UITextField's property:
- (void)setAttributes:(NSDictionary *)attributes range:(NSRange)aRange;

Related

UITextField inside UITextView?

Is there a way to attach a UITextField inside inside the range of an NSAttributedString that is inside a UITextView?
I want to recreate something like this:
Where the user would be able to press the empty lines to type text.
You could calculate a frame for the UITextField like so:
- (CGRect)textFieldFrameForCharacterRange:(NSRange)charRange inTextView:(UITextView *)textView {
NSRange glyphRange = [textView.layoutManager glyphRangeForCharacterRange:charRange actualCharacterRange:NULL];
CGRect boundingRect = [textView.layoutManager boundingRectForGlyphRange:glyphRange inTextContainer:textView.textContainer];
return boundingRect;
}
and then add it as a subview of the UITextView. Determining a character range to pass to the above method can be easy too - just search for a run of underlines, or maybe a custom attribute using - enumerateAttribute:inRange:options:usingBlock:.
The catch is this won't work properly if the underlines are split into more than one line, but UITextField wouldn't fit that case anyway. So you need a way to make sure the underline remains unbroken. The U+2060 unicode character may help, see Prevent line break in a NSAttributedString for more. An NSTextAttachment with the underline represented as an image would also be guaranteed not to get word wrapped.
Alternatively, you could implement a UITextViewDelegate, or possibly even a UITextView subclass, that disallows selection and editing outside of the underline ranges. That way you can avoid the weirdness of UITextFields within UITextViews. But the drawback with this method is even if you deleted an underline character every time the user types a character, the user would still see the overall length of the underline fluctuating slightly.

Insert attributed string NSAttributedString at current selection or cursor position in UITextField in swift

I am using swift for iOS. I am trying to insert an NSAttributedString at the current cursor position or selection in a UITextField.
I use the function shouldChangeCharactersInRange on UITextFieldDelegate to manage different situations of inserting, deleting, copying and pasting text. That part works well.
If I use UIPasteboard with a standard string it calls shouldChangeCharactersInRange and works fine. I want to do the same with an attributed string.
Is there another way to do this by calling the paste selector directly on the UITextField? Any other ways?
I know that I can save the paste board items and restore them for a good user experience. That is not the crux of the matter.
Thanks
func insertWord(word: NSAttributedString) {
// I really want to copy paste the attributed string
UIPasteboard.generalPasteboard().string = word.string
myTextField.paste(self)
}
Going through the Pasteboard to try and fake the system into doing this for you is not a winning solution.
A UITextField is a subclass of UITextInput. You should be able to use that fact to get the selected range of text. From there you should be able to get the attributed string from the text field and replace the range of the selection with the your new attributed text, and set the resulting attributed string back into the text field.

UITextField with partial edit

I want to use a UITextField so that only part of it will be editable.
I know about the delegation and shouldChangeCharactersInRange but for some reason, copying the ranged part is allowed.
My goal is to get similar result to this (the 'subject' text part) without being able to copy it.
Should i use a different UITextField with textFieldDidBeginEditing returning false all the time?
Is there a better solution?
In the screenshot, a UILabel placed next to the UITextField is used. I'd recommend doing this as it will give you more options when you decide to style the text.

Accessibility (VoiceOver) on NSAttributedString

I have a block of text in a UITextView built using NSAttributedString. I require VoiceOver to say something extra when certain portions of the text is touched.
Is it possible to add accessibility attributes to NSAttributedString?
I think one solution to this would be a custom subclass of UITextView. Then you can return an array of UIAccessibilityCustomAction in an override of accessibilityCustomActions. These objects not only describe the actions taken by the text view, but they also allow VoiceOver to execute them.

How do I bind an NSString to a UITextView in Reactive Cocoa?

I'm building an iOS social client, and in the "compose" view, I've got a UITextView where the user enters text. I'd like to use ReactiveCocoa to bind the text of the UITextView to the NSString of the data model, to follow MVVM.
However, I'm running into several issues, all related to a single thing: the RACObserve block doesn't get called when the UITextView's text is changed programmatically.
(An example: I change the text into an attributed string to highlight #hashtags, #usernames, etc, but this attributed string doesn't get created when the view is programmatically changed.)
In my previous question on this topic, I got some helpful advice that I should bind the textview to the model - and vice versa - but it's not clear to me how I should do it with the current version of Reactive Cocoa. The sample code that I've managed to find calls APIs that are now deprecated.
What's the appropriate way to bind the rac_textSignal of a UITextView to an NSString (and vice versa) so that I can reliably call a block of code when the contents of the UITextView are changed (whether programmatically or by the user)?
The answer depends on whether the binding between the view model's text and the UITextViews text needs to be bidirectional. Generally we try to stay away from bidirectional bindings because they become harder to reason about. Ideally only one direction is driving the data.
So in that case, you'd write something like:
RAC(self.viewModel, text) = [RACSignal merge:#[
[self.textView rac_textSignal],
RACObserve(self.textView, text),
]];
That way you're picking up on changes to both the UITextViews text property directly, and text changes that come from the user typing.

Resources