语言构成

README

Deprecation

We are no longer providing support for SlackTextViewController. This project satisfied all of our iOS messaging needs in the past and we are proud to have contributed it to the open-source community. Today, in order to delight our users with a solution that is highly tailored and rapidly iterated-upon, we have shifted focus to our internal projects. Unfortunately, this renders us lacking the capacity to support our past projects in addition to our newer, internal projects. This project has been deprecated as a result.

SlackTextViewController

IMPORTANT NOTICE: Please update to >= 1.9 to avoid any risk of app rejection.
More details in #361

A drop-in UIViewController subclass with a growing text input view and other useful messaging features. Meant to be a replacement for UITableViewController & UICollectionViewController.

This library was historically used in our iOS app. At its inception, the library satisfied our product needs and was flexible enough to be reused by others wanting to build great messaging apps for iOS.

Installation

Manually:

or compile the project located in Builder/SlackTextViewController.xcodeproj to create a SlackTextViewController.framework package. You could also link the library into your project.

How to use

Subclassing

SLKTextViewController is meant to be subclassed, like you would normally do with UITableViewController or UICollectionViewController or UIScrollView. This pattern is a convenient way of extending UIViewController. SlackTextViewController manages a lot behind the scenes while still providing the ability to add custom behaviours. You may override methods, and decide to call super and perform additional logic, or not to call super and override default logic.

Start by creating a new subclass of SLKTextViewController.

In the init overriding method, if you wish to use the UITableView version, call:

Obj-C

[superinitWithTableViewStyle:UITableViewStylePlain]

Swift

super.init(tableViewStyle: .Plain)

or the UICollectionView version:

Obj-C

[superinitWithCollectionViewLayout:[UICollectionViewFlowLayout new]]

Swift

super.init(collectionViewLayout: UICollectionViewFlowLayout())

or the UIScrollView version:

Obj-C

[superinitWithScrollView:self.myStrongScrollView]

Swift

super.init(scrollView: self.myStrongScrollView)

Protocols like UITableViewDelegate and UITableViewDataSource are already setup for you. You will be able to call whatever delegate and data source methods you need for customising your control.

Storyboard

When using SlackTextViewController with storyboards, instead of overriding the traditional initWithCoder: you will need to override any of the two custom methods below. This approach helps preserving the exact same features from the programatic approach, but also limits the edition of the nib of your SLKTextViewController subclass since it doesn't layout subviews from the nib (subviews are still initialized and layed out programatically).

Swift

Sample Project

Check out the sample project, everything is demo'd there.
There are 2 main examples (different targets) for testing the programatic and storyboard approaches, and a Swift example. Most of the features are implemented for you to quickly start using them.

Feel free to contribute!

Features

Growing Text View

The text view expands automatically when a new line is required, until it reaches its maxNumberOfLinesvalue. You may change this property's value in the textView.

By default, the number of lines is set to best fit each device dimensions:

iPhone 4 (<=480pts): 4 lines

iPhone 5/6 (>=568pts): 6 lines

iPad (>=768pts): 8 lines

On iPhone devices, in landscape orientation, the maximum number of lines is changed to fit the available space.

Inverted Mode

Some layouts may require to show from bottom to top and new subviews are inserted from the bottom. To enable this, you must use the inverted flag property (default is YES/true). This will actually invert the entire ScrollView object. Make sure to apply the same transformation to every subview. In the case of UITableView, the best place for adjusting the transformation is in its data source methods like:

Autocompletion

We use autocompletion for many things: names, channels, emoji, and more.

To set up autocompletion in your app, follow these simple steps:

1. Registration

You must first register all the prefixes you'd like to support for autocompletion detection:

Obj-C

[selfregisterPrefixesForAutoCompletion:@[@"#"]];

Swift

self.registerPrefixesForAutoCompletion(["@", "#"])

2. Processing

Every time a new character is inserted in the text view, the nearest word to the caret will be processed and verified if it contains any of the registered prefixes.

Once the prefix has been detected, didChangeAutoCompletionPrefix:andWord: will be called. This is the perfect place to populate your data source and show/hide the autocompletion view. So you must override it in your subclass, to be able to perform additional tasks. Default returns NO.

Swift

4. Confirmation

If the user selects any autocompletion view cell on tableView:didSelectRowAtIndexPath:, you must call acceptAutoCompletionWithString: to commit autocompletion. That method expects a string matching the selected item, that you would like to be inserted in the text view.

The autocompletion view will automatically be dismissed and the chosen string will be inserted in the text view, replacing the detected prefix and word.

You can always call cancelAutoCompletion to exit the autocompletion mode and refresh the UI.

Edit Mode

To enable edit mode, you simply need to call editText:, and the text input will switch to edit mode, removing both left and right buttons, extending the input bar a bit higher with "Accept" and "Cancel" buttons. Both of this buttons are accessible in the SLKTextInputbar instance for customisation.

To capture the "Accept" or "Cancel" events, you must override the following methods.

Notice that you must call super at some point, so the text input exits the edit mode, re-adjusting the layout and clearing the text view.
Use the editing property to know if the editing mode is on.

Markdown Formatting

You can register markdown formatting symbols so they can easily be used to wrap a text selection, with the help of the native contextual menu, aka UIMenuController. This feature doesn't take care of the rendering of the markdown: it's sole purpose is to ease the formatting tools to the user.
Optionally, you can enable autoCompleteFormatting so any pending markdown closure symbol can be added automatically after double tapping on the keyboard spacebar, just like the native gesture to add a sentence period. The sentence period is still being added as a fallback.

1. Registration

You must first register the formatting symbol and assign a title string to be used in the menu controller item.

Obj-C

Swift

2. Customisation

Futher more, you can customise some of the behavior for special formatting cases, using the UITextViewDelegate methods.
In the following example, we don't present the Quote formatting in the contextual menu when the text selection isn't a paragraph.

Typing Indicator

Optionally, you can enable a simple typing indicator, which will be displayed right above the text input. It shows the name of the people that are typing, and if more than 2, it will display "Several are typing" message.

To enable the typing indicator, just call:

Obj-C

[self.typingIndicatorView insertUsername:@"John"];

Swift

self.typingIndicatorView?.insertUsername("John")

and the view will automatically be animated on top of the text input. After a default interval of 6 seconds, if the same name hasn't been assigned once more, the view will be dismissed with animation.

You can remove names from the list by calling:

Obj-C

[self.typingIndicatorView removeUsername:@"John"];

Swift

self.typingIndicatorView?.removeUsername("John")

You can also dismiss it by calling:

Obj-C

[self.typingIndicatorView dismissIndicator];

Swift

self.typingIndicatorView?.dismissIndicator()

Panning Gesture

Dismissing the keyboard with a panning gesture is enabled by default with the keyboardPanningEnabled property. You can always disable it if you'd like. You can extend the verticalPanGesture behaviors with the UIGestureRecognizerDelegate methods.

Hideable TextInputbar

Sometimes you may need to hide the text input bar.
Very similar to UINavigationViewController's API, simply do:

Obj-C

[selfsetTextInputbarHidden:YESanimated:YES];

Swift

self.setTextInputbarHidden(true, animated: true)

Shake Gesture

A shake gesture to clear text is enabled by default with the undoShakingEnabled property.

You can optionally override willRequestUndo, to implement your UI to ask the users if he would like to clean the text view's text. If there is not text entered, the method will not be called.

If you don't override willRequestUndo and undoShakingEnabled is set to YES/true, a system alert will be shown.