more implementations
This commit is contained in:
@@ -6,6 +6,10 @@ class ExpoUITextView: ExpoView {
|
||||
|
||||
var tapGestureRecognizer: UITapGestureRecognizer?
|
||||
|
||||
let onTextLayout = EventDispatcher()
|
||||
|
||||
// Props
|
||||
|
||||
public required init(appContext: AppContext? = nil) {
|
||||
if #available(iOS 16.0, *) {
|
||||
textView = UITextView(usingTextLayoutManager: false)
|
||||
@@ -18,8 +22,6 @@ class ExpoUITextView: ExpoView {
|
||||
textView.isEditable = false
|
||||
textView.isScrollEnabled = false
|
||||
textView.backgroundColor = .clear
|
||||
textView.textContainer.lineBreakMode = .byTruncatingTail
|
||||
textView.isSelectable = true
|
||||
|
||||
// Remove all of the padding from the view
|
||||
textView.textContainerInset = UIEdgeInsets.zero
|
||||
@@ -34,6 +36,14 @@ class ExpoUITextView: ExpoView {
|
||||
tapGestureRecognizer.isEnabled = true
|
||||
self.tapGestureRecognizer = tapGestureRecognizer
|
||||
textView.addGestureRecognizer(tapGestureRecognizer)
|
||||
|
||||
// Listen for dynamic type changes
|
||||
NotificationCenter.default.addObserver(
|
||||
self,
|
||||
selector: #selector(preferredContentSizeChanged(_:)),
|
||||
name: UIContentSizeCategory.didChangeNotification,
|
||||
object: nil
|
||||
)
|
||||
}
|
||||
|
||||
// Update children whenever new react subviews are added
|
||||
@@ -66,6 +76,23 @@ class ExpoUITextView: ExpoView {
|
||||
textView.frame.size = size
|
||||
self.appContext?.reactBridge?.uiManager.setSize(size, for: self)
|
||||
|
||||
// Get each line and call onTextLayout
|
||||
var lines: [String] = []
|
||||
textView.layoutManager.enumerateLineFragments(
|
||||
forGlyphRange: NSRange(location: 0, length: textView.attributedText.length))
|
||||
{ (rect, usedRect, textContainer, glyphRange, stop) in
|
||||
let characterRange = self.textView.layoutManager.characterRange(forGlyphRange: glyphRange, actualGlyphRange: nil)
|
||||
let line = (self.textView.text as NSString).substring(with: characterRange)
|
||||
lines.append(line)
|
||||
}
|
||||
|
||||
onTextLayout([
|
||||
"lines": lines
|
||||
])
|
||||
}
|
||||
|
||||
@objc func preferredContentSizeChanged(_ notification: Notification) {
|
||||
self.setText()
|
||||
}
|
||||
|
||||
@IBAction func callOnPress(_ sender: UITapGestureRecognizer) -> Void {
|
||||
@@ -139,10 +166,14 @@ class ExpoUITextView: ExpoView {
|
||||
return
|
||||
}
|
||||
|
||||
let scaledFontSize = self.textView.adjustsFontForContentSizeCategory ?
|
||||
UIFontMetrics.default.scaledValue(for: child.style?.fontSize ?? 12.0) :
|
||||
child.style?.fontSize ?? 12.0
|
||||
|
||||
// Set some generic attributes that don't need ranges
|
||||
let attributes: [NSAttributedString.Key:Any] = [
|
||||
.font: UIFont.systemFont(
|
||||
ofSize: child.style?.fontSize ?? 12.0,
|
||||
ofSize: scaledFontSize,
|
||||
weight: child.style?.fontWeight?.toFontWeight() ?? .regular
|
||||
),
|
||||
.foregroundColor: TextUtil.hexToUIColor(hex: child.style?.color),
|
||||
|
||||
@@ -2,9 +2,47 @@ import ExpoModulesCore
|
||||
|
||||
public class ExpoUITextViewModule: Module {
|
||||
public func definition() -> ModuleDefinition {
|
||||
Name("ExpoSelectableText")
|
||||
Name("ExpoUITextView")
|
||||
|
||||
View(ExpoUITextView.self) {
|
||||
Events("onViewLayout", "onTextLayout")
|
||||
|
||||
Prop("accessibilityHint") { (view: ExpoUITextView, prop: String) in
|
||||
view.textView.accessibilityHint = prop
|
||||
}
|
||||
Prop("accessibilityLanguage") { (view: ExpoUITextView, prop: String) in
|
||||
view.textView.accessibilityLanguage = prop
|
||||
}
|
||||
Prop("accessibilityLabel") { (view: ExpoUITextView, prop: String) in
|
||||
view.textView.accessibilityLabel = prop
|
||||
}
|
||||
Prop("accessibilityRole") { (view: ExpoUITextView, prop: String) in
|
||||
view.textView.accessibilityRole = prop
|
||||
}
|
||||
Prop("accessibilityState") { (view: ExpoUITextView, prop: AccessibilityState) in
|
||||
view.textView.accessibilityState = prop.toAccessibilityState()
|
||||
}
|
||||
Prop("accessibilityValue") { (view: ExpoUITextView, prop: AccessibilityValue) in
|
||||
view.textView.accessibilityValue = prop.text
|
||||
}
|
||||
Prop("accessibilityViewIsModal") { (view: ExpoUITextView, prop: Bool) in
|
||||
view.textView.accessibilityViewIsModal = prop
|
||||
}
|
||||
Prop("accessibilityElementsHidden") { (view: ExpoUITextView, prop: Bool) in
|
||||
view.textView.accessibilityElementsHidden = prop
|
||||
}
|
||||
Prop("allowFontScaling") { (view: ExpoUITextView, prop: Bool) in
|
||||
view.textView.adjustsFontForContentSizeCategory = prop
|
||||
}
|
||||
Prop("numberOfLines") { (view: ExpoUITextView, prop: Int) in
|
||||
view.textView.textContainer.maximumNumberOfLines = prop
|
||||
}
|
||||
Prop("ellipsizeMode") { (view: ExpoUITextView, prop: EllipsizeMode) in
|
||||
view.textView.textContainer.lineBreakMode = prop.toLineBreakMode()
|
||||
}
|
||||
Prop("selectable") { (view: ExpoUITextView, prop: Bool) in
|
||||
view.textView.isSelectable = prop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +53,7 @@ public class ExpoUITextViewModule: Module {
|
||||
*/
|
||||
public class ExpoUITextViewChildModule: Module {
|
||||
public func definition() -> ModuleDefinition {
|
||||
Name("ExpoTextChild")
|
||||
Name("ExpoUITextViewChild")
|
||||
|
||||
View(ExpoUITextViewChild.self) {
|
||||
Events("onTextPress")
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
import ExpoModulesCore
|
||||
|
||||
struct AccessibilityState: Record {
|
||||
@Field
|
||||
var disabled: Bool?
|
||||
@Field
|
||||
var selected: Bool?
|
||||
@Field
|
||||
var checked: Bool?
|
||||
@Field
|
||||
var busy: Bool?
|
||||
@Field
|
||||
var expanded: Bool?
|
||||
|
||||
func toAccessibilityState() -> [String: Any] {
|
||||
return self.toDictionary()
|
||||
}
|
||||
}
|
||||
|
||||
struct AccessibilityValue: Record {
|
||||
@Field
|
||||
var min: Int?
|
||||
@Field
|
||||
var max: Int?
|
||||
@Field
|
||||
var now: Int?
|
||||
@Field
|
||||
var text: String?
|
||||
}
|
||||
|
||||
enum EllipsizeMode: String, Enumerable {
|
||||
case head
|
||||
case middle
|
||||
case tail
|
||||
case clip
|
||||
|
||||
func toLineBreakMode() -> NSLineBreakMode {
|
||||
switch self {
|
||||
case .head:
|
||||
return .byTruncatingHead
|
||||
case .middle:
|
||||
return .byTruncatingMiddle
|
||||
case .tail:
|
||||
return .byTruncatingTail
|
||||
case .clip:
|
||||
return .byClipping
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import ExpoModulesCore
|
||||
|
||||
struct TextSegments: Record {
|
||||
@Field
|
||||
var segments: Array<TextSegment>
|
||||
}
|
||||
|
||||
struct TextSegment: Record {
|
||||
@Field
|
||||
var index: Int
|
||||
@Field
|
||||
var text: String
|
||||
@Field
|
||||
var style: TextStyle?
|
||||
}
|
||||
Reference in New Issue
Block a user