{"id":13611007,"url":"https://github.com/slackhq/SlackTextViewController","last_synced_at":"2025-04-13T01:34:09.923Z","repository":{"id":19821476,"uuid":"23082332","full_name":"slackhq/SlackTextViewController","owner":"slackhq","description":"⛔️**DEPRECATED** ⛔️ A drop-in UIViewController subclass with a growing text input view and other useful messaging features","archived":true,"fork":false,"pushed_at":"2018-10-29T18:56:03.000Z","size":16262,"stargazers_count":8330,"open_issues_count":79,"forks_count":1085,"subscribers_count":229,"default_branch":"master","last_synced_at":"2024-05-29T19:30:19.960Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://slack.com/","language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/slackhq.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-08-18T18:46:06.000Z","updated_at":"2024-05-29T19:30:19.961Z","dependencies_parsed_at":"2022-08-25T06:50:22.409Z","dependency_job_id":null,"html_url":"https://github.com/slackhq/SlackTextViewController","commit_stats":null,"previous_names":[],"tags_count":35,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slackhq%2FSlackTextViewController","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slackhq%2FSlackTextViewController/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slackhq%2FSlackTextViewController/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slackhq%2FSlackTextViewController/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/slackhq","download_url":"https://codeload.github.com/slackhq/SlackTextViewController/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223558474,"owners_count":17165137,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T19:01:50.817Z","updated_at":"2024-11-07T17:31:07.509Z","avatar_url":"https://github.com/slackhq.png","language":"Objective-C","readme":"# Deprecation\n\nWe 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.\n\n# SlackTextViewController\n\n**IMPORTANT NOTICE: Please update to \u003e= `1.9` to avoid any risk of app rejection.\nMore details in [#361](https://github.com/slackhq/SlackTextViewController/issues/361)**\n\n[![License](http://img.shields.io/badge/license-MIT-blue.svg)](http://opensource.org/licenses/MIT)\n[![Pod Version](https://img.shields.io/cocoapods/v/SlackTextViewController.svg)](http://cocoadocs.org/docsets/SlackTextViewController/1.9/)\n[![Carthage compatible](https://img.shields.io/badge/carthage-compatible-F5B369.svg)](https://github.com/Carthage/Carthage)\n[![BuddyBuild](https://dashboard.buddybuild.com/api/statusImage?appID=59f2234423c5f600018bb24b\u0026branch=master\u0026build=latest)](https://dashboard.buddybuild.com/apps/59f2234423c5f600018bb24b/build/latest?branch=master)\n\nA drop-in UIViewController subclass with a growing text input view and other useful messaging features. Meant to be a replacement for UITableViewController \u0026 UICollectionViewController.\n\n![Demo Gif](Screenshots/slacktextviewcontroller_demo.gif)\n\nThis 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.\n\n## Feature List\n\n### Core\n- Works out of the box with [UITableView or UICollectionView or UIScrollView](https://github.com/slackhq/SlackTextViewController#subclassing)\n- [Growing Text View](https://github.com/slackhq/SlackTextViewController#growing-text-view), with line count limit support\n- Flexible UI built with Auto Layout\n- Customizable: provides left and right button, and toolbar outlets\n- Tap Gesture for dismissing the keyboard\n- [External keyboard](https://github.com/slackhq/SlackTextViewController#external-keyboard) commands support\n- Undo/Redo (with keyboard commands and UIMenuController)\n- Text Appending APIs\n\n### Additional\n- [Autocomplete Mode](https://github.com/slackhq/SlackTextViewController#autocompletion) by registering any prefix key (`@`, `#`, `/`)\n- [Edit Mode](https://github.com/slackhq/SlackTextViewController#edit-mode)\n- [Markdown Formatting](https://github.com/slackhq/SlackTextViewController#markdown-formatting)\n- [Typing Indicator](https://github.com/slackhq/SlackTextViewController#typing-indicator) display\n- [Shake Gesture](https://github.com/slackhq/SlackTextViewController#shake-gesture) for clearing text view\n- Multimedia Pasting (png, gif, mov, etc.)\n- [Inverted Mode](https://github.com/slackhq/SlackTextViewController#inverted-mode) for displaying cells upside-down (using CATransform) -- a necessary hack for some messaging apps. `YES`/`true` by default, so beware, your entire cells might be flipped!\n- Tap Gesture for dismissing the keyboard\n- [Panning Gesture](https://github.com/slackhq/SlackTextViewController#panning-gesture) for sliding down/up the keyboard\n- [Hideable TextInputbar](https://github.com/slackhq/SlackTextViewController#hideable-textinputbar)\n- [Dynamic Type](https://github.com/slackhq/SlackTextViewController#dynamic-type) for adjusting automatically the text input bar height based on the font size.\n- Bouncy Animations\n\n### Compatibility\n- Carthage \u0026 CocoaPods\n- Objective-C \u0026 Swift\n- iOS 7, 8 \u0026 9\n- iPhone \u0026 iPad\n- [Storyboard](https://github.com/slackhq/SlackTextViewController#storyboard)\n- UIPopOverController \u0026 UITabBarController\n- Container View Controller\n- Auto-Rotation\n- iPad Multitasking (iOS 9 only)\n- Localization\n\n## Installation\n\n###### With [CocoaPods](https://cocoapods.org/):\n```ruby\npod \"SlackTextViewController\"\n```\n\n###### With [Carthage](https://github.com/Carthage/Carthage):\n```swift\ngithub \"slackhq/SlackTextViewController\"\n```\n\n###### Manually:\nThere are two ways to do this:\n- Copy and drag the `Source/` folder to your project.\n- or compile the project located in `Builder/SlackTextViewController.xcodeproj` to create a `SlackTextViewController.framework` package. You could also [link the library into your project](https://developer.apple.com/library/ios/recipes/xcode_help-project_editor/Articles/AddingaLibrarytoaTarget.html#//apple_ref/doc/uid/TP40010155-CH17-SW1).\n\n\n## How to use\n\n### Subclassing\n`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.\n\nStart by creating a new subclass of `SLKTextViewController`.\n\nIn the init overriding method, if you wish to use the `UITableView` version, call:\n##### Obj-C\n```objc\n[super initWithTableViewStyle:UITableViewStylePlain]\n```\n##### Swift\n```swift\nsuper.init(tableViewStyle: .Plain)\n```\n\nor the `UICollectionView` version:\n##### Obj-C\n```objc\n[super initWithCollectionViewLayout:[UICollectionViewFlowLayout new]]\n```\n##### Swift\n```swift\nsuper.init(collectionViewLayout: UICollectionViewFlowLayout())\n```\n\nor the `UIScrollView` version:\n##### Obj-C\n```objc\n[super initWithScrollView:self.myStrongScrollView]\n```\n##### Swift\n```swift\nsuper.init(scrollView: self.myStrongScrollView)\n```\n\nProtocols 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.\n\nCalling `[super init]` will call `[super initWithTableViewStyle:UITableViewStylePlain]` by default.\n\n### Storyboard\n\nWhen 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).\n\nif you wish to use the `UITableView` version, call:\n##### Obj-C\n```objc\n+ (UITableViewStyle)tableViewStyleForCoder:(NSCoder *)decoder\n{\n    return UITableViewStylePlain;\n}\n```\n##### Swift\n```swift\noverride class func tableViewStyleForCoder(decoder: NSCoder) -\u003e UITableViewStyle {\n    return .Plain\n}\n```\n\nor the `UICollectionView` version:\n##### Obj-C\n```objc\n+ (UICollectionViewLayout *)collectionViewLayoutForCoder:(NSCoder *)decoder\n{\n    return [UICollectionViewFlowLayout new];\n}\n```\n##### Swift\n```swift\noverride class func collectionViewLayoutForCoder(decoder: NSCoder) -\u003e UICollectionViewLayout {\n    return UICollectionViewFlowLayout()\n}\n```\n\n### Sample Project\n\nCheck out the sample project,  everything is demo'd there.\nThere 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.\n\nFeel free to contribute!\n\n\n## Features\n\n\n### Growing Text View\n\n![Growing](Screenshots/screenshot_auto-expanding.png)\n\nThe text view expands automatically when a new line is required, until it reaches its `maxNumberOfLines`value. You may change this property's value in the textView.\n\nBy default, the number of lines is set to best fit each device dimensions:\n- iPhone 4      (\u003c=480pts): 4 lines\n- iPhone 5/6    (\u003e=568pts): 6 lines\n- iPad          (\u003e=768pts): 8 lines\n\nOn iPhone devices, in landscape orientation, the maximum number of lines is changed to fit the available space.\n\n\n### Inverted Mode\n\nSome 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:\n##### Obj-C\n```objc\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:kCellIdentifier];\n    cell.transform = self.tableView.transform;\n}\n```\n##### Swift\n```swift\noverride func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -\u003e UITableViewCell {\n        \n    if let cell = tableView.dequeueReusableCellWithIdentifier(kCellIdentifier) {\n        cell.transform = self.tableView.transform\n    }\n}\n```\n\n\n### Autocompletion\n\nWe use autocompletion for many things: names, channels, emoji, and more.\n\n![Autocompletion](Screenshots/screenshot_auto-completion.png)\n\nTo set up autocompletion in your app, follow these simple steps:\n\n#### 1. Registration\nYou must first register all the prefixes you'd like to support for autocompletion detection:\n##### Obj-C\n```objc\n[self registerPrefixesForAutoCompletion:@[@\"#\"]];\n```\n##### Swift\n```swift\nself.registerPrefixesForAutoCompletion([\"@\", \"#\"])\n```\n\n#### 2. Processing\nEvery 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.\n\nOnce 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.\n##### Obj-C\n```objc\n- (void)didChangeAutoCompletionPrefix:(NSString *)prefix andWord:(NSString *)word\n{\n    NSArray *array = [NSArray arrayWithArray:self.channels];\n    \n    if ([prefix isEqualToString:@\"#\"] \u0026\u0026 word.length \u003e 0) {\n        self.searchResult = [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@\"self BEGINSWITH[c]\", word]];\n    }\n    \n    BOOL show = (self.searchResult.count \u003e 0);\n    \n    [self showAutoCompletionView:show];\n}\n```\n##### Swift\n```swift\noverride func didChangeAutoCompletionPrefix(prefix: String, andWord word: String) {\n    \n    let array: NSArray = self.channels\n    \n    if prefix == \"#\" \u0026\u0026 word.characters.count \u003e 0 {\n        self.searchResult = array.filteredArrayUsingPredicate(NSPredicate(format: \"self BEGINSWITH[c] %@\", word))\n    }\n    \n    let show = (self.searchResult.count \u003e 0)\n    \n    self.showAutoCompletionView(show)\n}\n```\n\nThe autocompletion view is a `UITableView` instance, so you will need to use `UITableViewDataSource` to populate its cells. You have complete freedom for customizing the cells.\n\nYou don't need to call `reloadData` yourself, since it will be invoked automatically right after calling the `showAutoCompletionView` method.\n\n#### 3. Layout\n\nThe maximum height of the autocompletion view is set to 140 pts by default. You can update this value anytime, so the view automatically adjusts based on the amount of displayed cells.\n##### Obj-C\n```objc\n- (CGFloat)heightForAutoCompletionView\n{\n    CGFloat cellHeight = 34.0;\n    return cellHeight*self.searchResult.count;\n}\n```\n##### Swift\n```swift\noverride func heightForAutoCompletionView() -\u003e CGFloat {\n    let cellHeight:CGFloat = 34\n    return cellHeight * CGFloat(self.searchResult.count)\n}\n```\n\n#### 4. Confirmation\n\nIf 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.\n##### Obj-C\n```objc\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath\n{\n    if ([tableView isEqual:self.autoCompletionView]) {\n        \n        NSMutableString *item = [self.searchResult[indexPath.row] mutableCopy];\n        [item appendString:@\" \"]; // Adding a space helps dismissing the auto-completion view\n        \n        [self acceptAutoCompletionWithString:item keepPrefix:YES];\n    }\n}\n```\n##### Swift\n```swift\noverride func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {\n        \n    if tableView.isEqual(self.autoCompletionView) {\n        var item = self.searchResult[indexPath.row]\n        item += \" \"  // Adding a space helps dismissing the auto-completion view\n            \n        self.acceptAutoCompletionWithString(item)\n    }\n}\n```\n\nThe autocompletion view will automatically be dismissed and the chosen string will be inserted in the text view, replacing the detected prefix and word.\n\nYou can always call `cancelAutoCompletion` to exit the autocompletion mode and refresh the UI.\n\n\n### Edit Mode\n\n![Edit Mode](Screenshots/screenshot_edit-mode.png)\n\nTo 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.\n\nTo capture the \"Accept\" or \"Cancel\" events, you must override the following methods.\n##### Obj-C\n```objc\n- (void)didCommitTextEditing:(id)sender\n{\n    NSString *message = [self.textView.text copy];\n    \n    [self.messages removeObjectAtIndex:0];\n    [self.messages insertObject:message atIndex:0];\n    [self.tableView reloadData];\n    \n    [super didCommitTextEditing:sender];\n}\n\n- (void)didCancelTextEditing:(id)sender\n{\n    [super didCancelTextEditing:sender];\n}\n```\n##### Swift\n```swift\noverride func didCommitTextEditing(sender: AnyObject) {\n    \n    let message:String = self.textView.text\n    \n    self.messages.removeAtIndex(0)\n    self.messages.insert(message, atIndex: 0)\n    \n    self.tableView!.reloadData()\n    \n    super.didCommitTextEditing(sender)\n}\n \noverride func didCancelTextEditing(sender: AnyObject) {\n        \n    super.didCancelTextEditing(sender)\n}\n```\n\nNotice 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.\nUse the `editing` property to know if the editing mode is on.\n\n\n### Markdown Formatting\n\n![Markdown Formatting](Screenshots/screenshot_markdown-formatting.png)\n\nYou 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.\nOptionally, 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.\n\n![Markdown Formatting Animated](Screenshots/screenshot_markdown-formatting.gif)\n\n\n#### 1. Registration\n\nYou must first register the formatting symbol and assign a title string to be used in the menu controller item.\n##### Obj-C\n```objc\n[self.textView registerMarkdownFormattingSymbol:@\"*\" withTitle:@\"Bold\"];\n```\n##### Swift\n```swift\nself.textView.registerMarkdownFormattingSymbol(\"*\", withTitle: \"Bold\")\n```\n\n#### 2. Customisation\n\nFuther more, you can customise some of the behavior for special formatting cases, using the `UITextViewDelegate` methods.\nIn the following example, we don't present the Quote formatting in the contextual menu when the text selection isn't a paragraph.\n##### Obj-C\n```objc\n- (BOOL)textView:(SLKTextView *)textView shouldOfferFormattingForSymbol:(NSString *)symbol\n{\n    if ([symbol isEqualToString:@\"\u003e\"]) {\n        \n        NSRange selection = textView.selectedRange;\n        \n        // The Quote formatting only applies new paragraphs\n        if (selection.location == 0 \u0026\u0026 selection.length \u003e 0) {\n            return YES;\n        }\n        \n        // or older paragraphs too\n        NSString *prevString = [textView.text substringWithRange:NSMakeRange(selection.location-1, 1)];\n        \n        if ([[NSCharacterSet newlineCharacterSet] characterIsMember:[prevString characterAtIndex:0]]) {\n            return YES;\n        }\n\n        return NO;\n    }\n    \n    return [super textView:textView shouldOfferFormattingForSymbol:symbol];\n}\n```\n\nIn this other method implementation, we don't want to allow auto-completion for the Quote formatting since it doesn't require a closure.\n##### Obj-C\n```objc\n- (BOOL)textView:(SLKTextView *)textView shouldInsertSuffixForFormattingWithSymbol:(NSString *)symbol prefixRange:(NSRange)prefixRange\n{\n    if ([symbol isEqualToString:@\"\u003e\"]) {\n        return NO;\n    }\n    \n    return [super textView:textView shouldInsertSuffixForFormattingWithSymbol:symbol prefixRange:prefixRange];\n}\n```\n\n\n### Typing Indicator\n\n![Typing Indicator](Screenshots/screenshot_typing-indicator.png)\n\nOptionally, 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.\n\nTo enable the typing indicator, just call:\n##### Obj-C\n```objc\n[self.typingIndicatorView insertUsername:@\"John\"];\n```\n##### Swift\n```swift\nself.typingIndicatorView?.insertUsername(\"John\")\n```\n\nand 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.\n\nYou can remove names from the list by calling:\n##### Obj-C\n```objc\n[self.typingIndicatorView removeUsername:@\"John\"];\n```\n##### Swift\n```swift\nself.typingIndicatorView?.removeUsername(\"John\")\n```\n\nYou can also dismiss it by calling:\n##### Obj-C\n```objc\n[self.typingIndicatorView dismissIndicator];\n```\n##### Swift\n```swift\nself.typingIndicatorView?.dismissIndicator()\n```\n\n### Panning Gesture\n\nDismissing 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.\n\n\n### Hideable TextInputbar\n\nSometimes you may need to hide the text input bar.\nVery similar to `UINavigationViewController`'s API, simply do:\n##### Obj-C\n```objc\n[self setTextInputbarHidden:YES animated:YES];\n```\n##### Swift\n```swift\nself.setTextInputbarHidden(true, animated: true)\n```\n\n\n### Shake Gesture\n\n![Shake Gesture](Screenshots/screenshot_shake-undo.png)\n\nA shake gesture to clear text is enabled by default with the `undoShakingEnabled` property.\n\nYou 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.\n\nIf you don't override `willRequestUndo` and `undoShakingEnabled` is set to `YES`/`true`, a system alert will be shown.\n\n\n### External Keyboard\n\nThere a few basic key commands enabled by default:\n- cmd + z -\u003e undo\n- shift + cmd + z -\u003e redo\n- return key -\u003e calls `didPressRightButton:`, or `didCommitTextEditing:` if in edit mode\n- shift/cmd + return key -\u003e line break\n- escape key -\u003e exits edit mode, or auto-completion mode, or dismisses the keyboard\n- up \u0026 down arrows -\u003e vertical cursor movement\n\nTo add additional key commands, simply override `keyCommands` and append `super`'s array.\n##### Obj-C\n```objc\n- (NSArray *)keyCommands\n{\n    NSMutableArray *commands = [NSMutableArray arrayWithArray:[super keyCommands]];\n    \n    // Edit last message\n    [commands addObject:[UIKeyCommand keyCommandWithInput:UIKeyInputUpArrow\n                                           modifierFlags:0\n                                                   action:@selector(editLastMessage:)]];\n    \n    return commands;\n}\n```\n##### Swift\n```swift\noverride var keyCommands: [UIKeyCommand]? {\n        \n    var commands = super.keyCommands\n        \n    // Edit last message\n    let command = UIKeyCommand(input: UIKeyInputUpArrow, modifierFlags: .Command, action: \"editLastMessage:\")\n    commands?.append(command)\n        \n    return commands\n}\n```\n\nThere are also a set of useful flags for keyboard special detections such as `isExternalKeyboardDetected`, `isKeyboardUndocked`, `typingSuggestionEnabled` and `isTrackpadEnabled` (iOS 9 only)\n\n\n### Dynamic Type\n\nDynamic Type is enabled by default with the `dynamicTypeEnabled` property. You can always disable it if you'd like, but the text input bar would still adjust to best fit the font size of the text view.\n\n![Dynamic-Type](Screenshots/screenshot_dynamic-type.png)\n\n\n### Xcode Templates\n\n![Template](Screenshots/screenshot_template.png)\n\nWe have prepared a set of useful Xcode templates so you can quickly start using SlackTextViewController.\n\nTo install them, open up your terminal and type:\n```bash\nsh ./SlackTextViewController/File\\ Templates/install.sh\n```\n\nThese templates are also available in [Alcatraz](https://github.com/alcatraz/Alcatraz).\n","funding_links":[],"categories":["TableView","Objective-C  Stars 1000以内排名整理","Objective-C","HarmonyOS","etc","**Index**","Messaging"],"sub_categories":["Windows Manager","Recently I've done a few projects that involve Payments, iBeacons, and PassKit. Make sure to check these links out:"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslackhq%2FSlackTextViewController","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fslackhq%2FSlackTextViewController","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslackhq%2FSlackTextViewController/lists"}