| ... | @@ -12,6 +12,7 @@ import android.text.Editable | ... | @@ -12,6 +12,7 @@ import android.text.Editable |
| 12 | import android.text.InputType | 12 | import android.text.InputType |
| 13 | import android.text.InputFilter | 13 | import android.text.InputFilter |
| 14 | import android.text.Spanned | 14 | import android.text.Spanned |
| | 15 | import android.text.TextUtils |
| 15 | import android.text.TextWatcher | 16 | import android.text.TextWatcher |
| 16 | import android.text.style.ReplacementSpan | 17 | import android.text.style.ReplacementSpan |
| 17 | import android.util.TypedValue | 18 | import android.util.TypedValue |
| ... | @@ -254,7 +255,7 @@ class T3ComposerEditorView(context: Context, appContext: AppContext) : ExpoView( | ... | @@ -254,7 +255,7 @@ class T3ComposerEditorView(context: Context, appContext: AppContext) : ExpoView( |
| 254 | } | 255 | } |
| 255 | | 256 | |
| 256 | fun setPlaceholder(placeholder: String) { | 257 | fun setPlaceholder(placeholder: String) { |
| 257 | editor.hint = placeholder | 258 | editor.placeholder = placeholder |
| 258 | } | 259 | } |
| 259 | | 260 | |
| 260 | fun setClipboardFragment(fragment: String) { | 261 | fun setClipboardFragment(fragment: String) { |
| ... | @@ -267,12 +268,14 @@ class T3ComposerEditorView(context: Context, appContext: AppContext) : ExpoView( | ... | @@ -267,12 +268,14 @@ class T3ComposerEditorView(context: Context, appContext: AppContext) : ExpoView( |
| 267 | } else { | 268 | } else { |
| 268 | Typeface.DEFAULT | 269 | Typeface.DEFAULT |
| 269 | } | 270 | } |
| | 271 | editor.applyPlaceholder() |
| 270 | } | 272 | } |
| 271 | | 273 | |
| 272 | fun setFontSize(fontSize: Float) { | 274 | fun setFontSize(fontSize: Float) { |
| 273 | editor.textSize = fontSize | 275 | editor.textSize = fontSize |
| 274 | applyLineHeight() | 276 | applyLineHeight() |
| 275 | applyTokenSpans() | 277 | applyTokenSpans() |
| | 278 | editor.applyPlaceholder() |
| 276 | } | 279 | } |
| 277 | | 280 | |
| 278 | fun setLineHeight(lineHeight: Float) { | 281 | fun setLineHeight(lineHeight: Float) { |
| ... | @@ -587,6 +590,37 @@ internal class SelectionAwareEditText(context: Context) : EditText(context) { | ... | @@ -587,6 +590,37 @@ internal class SelectionAwareEditText(context: Context) : EditText(context) { |
| 587 | var maxInputChars = Int.MAX_VALUE | 590 | var maxInputChars = Int.MAX_VALUE |
| 588 | var clipboardFragment = "" | 591 | var clipboardFragment = "" |
| 589 | | 592 | |
| | 593 | /** |
| | 594 | * Placeholder shown while the draft is empty. An editable TextView never ellipsizes its hint, |
| | 595 | * so a long placeholder wraps once a wide system font or a large font scale (Samsung defaults) |
| | 596 | * runs out of width, and the resting composer grows to two lines. The hint is instead cut to |
| | 597 | * one line with an ellipsis for whatever width the editor is measured at. |
| | 598 | */ |
| | 599 | var placeholder = "" |
| | 600 | set(value) { |
| | 601 | field = value |
| | 602 | applyPlaceholder() |
| | 603 | } |
| | 604 | |
| | 605 | fun applyPlaceholder(availableWidth: Int = width - compoundPaddingLeft - compoundPaddingRight) { |
| | 606 | val next = |
| | 607 | if (availableWidth > 0) { |
| | 608 | TextUtils.ellipsize(placeholder, paint, availableWidth.toFloat(), TextUtils.TruncateAt.END) |
| | 609 | } else { |
| | 610 | placeholder |
| | 611 | } |
| | 612 | if (hint?.toString() != next.toString()) hint = next |
| | 613 | } |
| | 614 | |
| | 615 | override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { |
| | 616 | if (MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED) { |
| | 617 | applyPlaceholder( |
| | 618 | MeasureSpec.getSize(widthMeasureSpec) - compoundPaddingLeft - compoundPaddingRight |
| | 619 | ) |
| | 620 | } |
| | 621 | super.onMeasure(widthMeasureSpec, heightMeasureSpec) |
| | 622 | } |
| | 623 | |
| 590 | private fun deleteChip(backwards: Boolean): Boolean { | 624 | private fun deleteChip(backwards: Boolean): Boolean { |
| 591 | val content = text | 625 | val content = text |
| 592 | val start = minOf(selectionStart, selectionEnd) | 626 | val start = minOf(selectionStart, selectionEnd) |