@momo-kits/calculator-keyboard 0.150.2-beta.22 → 0.150.2-beta.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -3
- package/android/src/main/java/com/calculatorkeyboard/CalculatorKeyboardPackage.kt +1 -1
- package/android/src/main/java/com/calculatorkeyboard/CustomKeyboardView.kt +68 -77
- package/android/src/main/java/com/calculatorkeyboard/Event.kt +36 -0
- package/android/src/main/java/com/calculatorkeyboard/{RCTInputCalculator.kt → InputCalculatorViewManager.kt} +100 -27
- package/ios/CalculatorKeyboardView.h +30 -0
- package/ios/CalculatorKeyboardView.mm +231 -0
- package/ios/NativeInputCalculator.h +11 -0
- package/ios/NativeInputCalculator.mm +230 -0
- package/package.json +17 -4
- package/react-native-calculator-keyboard.podspec +5 -4
- package/src/InputCalculatorNativeComponent.ts +62 -0
- package/src/index.tsx +58 -30
- package/ios/CalculatorKeyboardView.swift +0 -153
- package/ios/InputCalculator-Bridging-Header.h +0 -23
- package/ios/InputCalculator.m +0 -85
- package/ios/InputCalculator.swift +0 -158
- package/ios/extension.swift +0 -23
package/README.md
CHANGED
|
@@ -10,15 +10,57 @@ npm install react-native-calculator-keyboard
|
|
|
10
10
|
|
|
11
11
|
## Usage
|
|
12
12
|
|
|
13
|
-
|
|
14
13
|
```js
|
|
15
|
-
import
|
|
14
|
+
import InputCalculator from '@momo-kits/calculator-keyboard';
|
|
16
15
|
|
|
17
16
|
// ...
|
|
18
17
|
|
|
19
|
-
<
|
|
18
|
+
<InputCalculator
|
|
19
|
+
mode="NumDefault"
|
|
20
|
+
customKeyText="Next"
|
|
21
|
+
onCustomKeyEvent={() => console.log('Custom key pressed')}
|
|
22
|
+
/>;
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Requirements
|
|
26
|
+
|
|
27
|
+
**React Native 0.80+** with **Fabric (New Architecture) enabled**.
|
|
28
|
+
|
|
29
|
+
This library is **pure Fabric** implementation with:
|
|
30
|
+
|
|
31
|
+
- ✅ Zero RCTBridge dependencies
|
|
32
|
+
- ✅ Native C++ ComponentView on iOS
|
|
33
|
+
- ✅ Fabric ViewManager with codegen delegates on Android
|
|
34
|
+
- ✅ All Props, Events, Commands auto-generated by codegen
|
|
35
|
+
- ❌ No Paper (old architecture) support
|
|
36
|
+
|
|
37
|
+
### Android Setup
|
|
38
|
+
|
|
39
|
+
Add to your `gradle.properties`:
|
|
40
|
+
|
|
41
|
+
```properties
|
|
42
|
+
newArchEnabled=true
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Then rebuild:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
cd android && ./gradlew clean && cd ..
|
|
49
|
+
npx react-native run-android
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### iOS Setup
|
|
53
|
+
|
|
54
|
+
**Required**: Set the environment variable before installing pods:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
cd ios
|
|
58
|
+
RCT_NEW_ARCH_ENABLED=1 pod install
|
|
59
|
+
cd ..
|
|
60
|
+
npx react-native run-ios
|
|
20
61
|
```
|
|
21
62
|
|
|
63
|
+
**Note**: This library uses Fabric ComponentView (`.mm` files) and will not work without `RCT_NEW_ARCH_ENABLED=1`.
|
|
22
64
|
|
|
23
65
|
## Contributing
|
|
24
66
|
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
package com.calculatorkeyboard
|
|
2
2
|
|
|
3
3
|
import android.annotation.SuppressLint
|
|
4
|
+
import android.content.Context
|
|
4
5
|
import android.content.res.ColorStateList
|
|
5
6
|
import android.graphics.Color
|
|
6
7
|
import android.graphics.drawable.GradientDrawable
|
|
7
8
|
import android.view.Gravity
|
|
8
9
|
import android.widget.Button
|
|
9
10
|
import android.widget.ImageButton
|
|
10
|
-
import androidx.appcompat.app.AppCompatActivity
|
|
11
11
|
import androidx.constraintlayout.widget.ConstraintLayout
|
|
12
12
|
import com.facebook.react.uimanager.ThemedReactContext
|
|
13
13
|
import org.mariuszgromada.math.mxparser.Expression
|
|
14
14
|
import androidx.core.graphics.toColorInt
|
|
15
|
-
import com.calculatorkeyboard.
|
|
15
|
+
import com.calculatorkeyboard.InputCalculatorViewManager.Companion.calculatorHeight
|
|
16
16
|
import com.facebook.react.bridge.Arguments
|
|
17
|
+
import com.facebook.react.bridge.ReactContext
|
|
18
|
+
import com.facebook.react.uimanager.UIManagerHelper
|
|
17
19
|
import com.facebook.react.uimanager.events.RCTEventEmitter
|
|
18
20
|
|
|
19
21
|
@SuppressLint("SetTextI18n", "ViewConstructor")
|
|
@@ -21,53 +23,57 @@ class CustomKeyboardView(
|
|
|
21
23
|
context: ThemedReactContext,
|
|
22
24
|
private val editText: CalculatorEditText
|
|
23
25
|
) : ConstraintLayout(context) {
|
|
24
|
-
private val
|
|
26
|
+
private val numWithCTAKeys = listOf(
|
|
25
27
|
listOf("1", "2", "3", "÷", "back"),
|
|
26
28
|
listOf("4", "5", "6", "×", "="),
|
|
27
|
-
listOf("7", "8", "9", "-", "
|
|
29
|
+
listOf("7", "8", "9", "-", "Tiếp"),
|
|
28
30
|
listOf("000", "0", "+")
|
|
29
31
|
)
|
|
30
|
-
private val
|
|
32
|
+
private val defaultKeys = listOf(
|
|
33
|
+
listOf("1", "2", "3", "÷", "AC"),
|
|
34
|
+
listOf("4", "5", "6", "×", "back"),
|
|
35
|
+
listOf("7", "8", "9", "-", "="),
|
|
36
|
+
listOf("000", "0", "+")
|
|
37
|
+
)
|
|
38
|
+
private val specialKeys = listOf("=", "-", "×", "÷", "back", "+", "AC")
|
|
31
39
|
private val separatorWidth = 8f
|
|
32
40
|
private var specialButtonColor: Int = "#D8D8D8".toColorInt()
|
|
33
41
|
|
|
42
|
+
private var keyboardMode: String = "NumDefault"
|
|
43
|
+
|
|
34
44
|
private var customKeyButton: Button? = null
|
|
35
45
|
private var customKeyButtonBackground: Int = "#D8D8D8".toColorInt()
|
|
36
46
|
private var customKeyButtonTextColor: Int = Color.BLACK
|
|
37
47
|
private var customKeyButtonState: String = "default"
|
|
38
48
|
|
|
39
49
|
init {
|
|
40
|
-
val activity = context.currentActivity as? AppCompatActivity
|
|
41
|
-
if (activity != null) {
|
|
42
|
-
val displayMetrics = resources.displayMetrics
|
|
43
|
-
val widthButton = (displayMetrics.widthPixels - separatorWidth * 2 - 4 * separatorWidth) / 5f
|
|
44
|
-
val heightButton = (calculatorHeight - separatorWidth * 2 - 3 * separatorWidth) / 4
|
|
45
|
-
|
|
46
50
|
isClickable = false
|
|
47
51
|
isFocusable = false
|
|
48
52
|
isFocusableInTouchMode = false
|
|
49
53
|
clipToPadding = false
|
|
50
54
|
clipChildren = false
|
|
51
|
-
|
|
52
|
-
renderUI(widthButton, heightButton)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
private fun renderUI(
|
|
57
|
+
private fun renderUI() {
|
|
58
|
+
val displayMetrics = resources.displayMetrics
|
|
59
|
+
val buttonWidth = (displayMetrics.widthPixels - separatorWidth * 2 - 4 * separatorWidth) / 5f
|
|
60
|
+
val buttonHeight = (calculatorHeight - separatorWidth * 2 - 3 * separatorWidth) / 4
|
|
61
|
+
|
|
58
62
|
var yOffset = separatorWidth
|
|
63
|
+
val keys = if (keyboardMode == "NumWithCTA") numWithCTAKeys else defaultKeys
|
|
59
64
|
for ((rowIndex, row) in keys.withIndex()) {
|
|
60
65
|
var xOffset = separatorWidth
|
|
61
66
|
for ((colIndex, key) in row.withIndex()) {
|
|
62
|
-
val
|
|
67
|
+
val isMainKey = rowIndex == 2 && colIndex == 4
|
|
68
|
+
val isMainCTAKey = isMainKey && keyboardMode == "NumWithCTA"
|
|
63
69
|
val width = if (key == "000") buttonWidth * 2 + separatorWidth else buttonWidth
|
|
64
|
-
val height = if (
|
|
70
|
+
val height = if (isMainKey) buttonHeight * 2 + separatorWidth else buttonHeight
|
|
65
71
|
|
|
66
72
|
val button = if (key == "back") {
|
|
67
73
|
createImageButton(key, xOffset, yOffset, buttonWidth.toInt(), buttonHeight.toInt())
|
|
68
74
|
} else {
|
|
69
|
-
createButton(key, xOffset, yOffset, width.toInt(), height.toInt(),
|
|
70
|
-
if (
|
|
75
|
+
createButton(key, xOffset, yOffset, width.toInt(), height.toInt(), isMainKey, isMainCTAKey).also { b ->
|
|
76
|
+
if (isMainCTAKey) customKeyButton = b
|
|
71
77
|
}
|
|
72
78
|
}
|
|
73
79
|
|
|
@@ -85,7 +91,8 @@ class CustomKeyboardView(
|
|
|
85
91
|
yOffset: Float,
|
|
86
92
|
buttonWidth: Int,
|
|
87
93
|
buttonHeight: Int,
|
|
88
|
-
|
|
94
|
+
isMainKey: Boolean,
|
|
95
|
+
isMainCTAKey: Boolean
|
|
89
96
|
): Button {
|
|
90
97
|
return Button(context).apply {
|
|
91
98
|
val shapeInit = GradientDrawable().apply {
|
|
@@ -98,7 +105,7 @@ class CustomKeyboardView(
|
|
|
98
105
|
background = shapeInit
|
|
99
106
|
text = key
|
|
100
107
|
setTypeface(typeface)
|
|
101
|
-
textSize = (if (
|
|
108
|
+
textSize = (if (isMainCTAKey) 18 else 24).toFloat()
|
|
102
109
|
setTextColor(Color.BLACK)
|
|
103
110
|
stateListAnimator = null
|
|
104
111
|
maxLines = 1
|
|
@@ -110,7 +117,7 @@ class CustomKeyboardView(
|
|
|
110
117
|
constrainedWidth = false
|
|
111
118
|
}
|
|
112
119
|
|
|
113
|
-
if (specialKeys.contains(key)) {
|
|
120
|
+
if (specialKeys.contains(key) || isMainKey) {
|
|
114
121
|
background = GradientDrawable().apply {
|
|
115
122
|
shape = GradientDrawable.RECTANGLE
|
|
116
123
|
cornerRadius = 24f
|
|
@@ -125,7 +132,7 @@ class CustomKeyboardView(
|
|
|
125
132
|
|
|
126
133
|
translationX = xOffset.toInt().toFloat()
|
|
127
134
|
translationY = yOffset.toInt().toFloat()
|
|
128
|
-
setOnClickListener { onKeyPress(key,
|
|
135
|
+
setOnClickListener { onKeyPress(key, isMainCTAKey) }
|
|
129
136
|
}
|
|
130
137
|
}
|
|
131
138
|
|
|
@@ -163,46 +170,15 @@ class CustomKeyboardView(
|
|
|
163
170
|
}
|
|
164
171
|
}
|
|
165
172
|
|
|
166
|
-
fun
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
val child = getChildAt(i)
|
|
170
|
-
if (child is Button) {
|
|
171
|
-
val key = child.text.toString()
|
|
172
|
-
if (specialKeys.contains(key)) {
|
|
173
|
-
if (key == "=") {
|
|
174
|
-
child.background = GradientDrawable().apply {
|
|
175
|
-
shape = GradientDrawable.RECTANGLE
|
|
176
|
-
cornerRadius = 24f
|
|
177
|
-
setColor(specialButtonColor)
|
|
178
|
-
}
|
|
179
|
-
} else {
|
|
180
|
-
child.background = GradientDrawable().apply {
|
|
181
|
-
shape = GradientDrawable.RECTANGLE
|
|
182
|
-
cornerRadius = 24f
|
|
183
|
-
setColor(specialButtonColor)
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
child.setTextColor(Color.BLACK)
|
|
187
|
-
}
|
|
188
|
-
} else if (child is ImageButton) {
|
|
189
|
-
child.background = GradientDrawable().apply {
|
|
190
|
-
shape = GradientDrawable.RECTANGLE
|
|
191
|
-
cornerRadius = 24f
|
|
192
|
-
setColor(specialButtonColor)
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
private fun onKeyPress(key: String, isCustomKey: Boolean) {
|
|
199
|
-
if (isCustomKey) {
|
|
200
|
-
emitCustomKey()
|
|
173
|
+
private fun onKeyPress(key: String, isMainCTAKey: Boolean) {
|
|
174
|
+
if (isMainCTAKey) {
|
|
175
|
+
emitCustomKey(context)
|
|
201
176
|
return
|
|
202
177
|
}
|
|
203
178
|
|
|
204
|
-
emitKeyPress(key)
|
|
179
|
+
emitKeyPress(context, key)
|
|
205
180
|
when (key) {
|
|
181
|
+
"AC" -> clearText()
|
|
206
182
|
"back" -> onBackSpace()
|
|
207
183
|
"=" -> calculateResult()
|
|
208
184
|
"×", "+", "-", "÷" -> keyDidPress(" $key ")
|
|
@@ -215,6 +191,10 @@ class CustomKeyboardView(
|
|
|
215
191
|
editText.text?.replace(editText.selectionStart, editText.selectionEnd, key)
|
|
216
192
|
}
|
|
217
193
|
|
|
194
|
+
private fun clearText() {
|
|
195
|
+
editText.text?.clear()
|
|
196
|
+
}
|
|
197
|
+
|
|
218
198
|
private fun onBackSpace() {
|
|
219
199
|
val start = editText.selectionStart
|
|
220
200
|
val end = editText.selectionEnd
|
|
@@ -251,44 +231,56 @@ class CustomKeyboardView(
|
|
|
251
231
|
}
|
|
252
232
|
}
|
|
253
233
|
|
|
254
|
-
private fun emitKeyPress(key: String) {
|
|
255
|
-
val reactContext = context as
|
|
256
|
-
val
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
234
|
+
private fun emitKeyPress(context: Context, key: String) {
|
|
235
|
+
val reactContext = context as ReactContext
|
|
236
|
+
val surfaceId = UIManagerHelper.getSurfaceId(reactContext)
|
|
237
|
+
val eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, editText.id)
|
|
238
|
+
val payload =
|
|
239
|
+
Arguments.createMap().apply {
|
|
240
|
+
putString("key", key)
|
|
241
|
+
}
|
|
242
|
+
val event = OnKeyPressEvent(surfaceId, editText.id, payload)
|
|
243
|
+
|
|
244
|
+
eventDispatcher?.dispatchEvent(event)
|
|
261
245
|
}
|
|
262
246
|
|
|
263
|
-
private fun emitCustomKey() {
|
|
264
|
-
val reactContext = context as
|
|
265
|
-
|
|
266
|
-
|
|
247
|
+
private fun emitCustomKey(context: Context) {
|
|
248
|
+
val reactContext = context as ReactContext
|
|
249
|
+
val surfaceId = UIManagerHelper.getSurfaceId(reactContext)
|
|
250
|
+
val eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, editText.id)
|
|
251
|
+
|
|
252
|
+
val event = OnCustomKeyPressEvent(surfaceId, editText.id)
|
|
253
|
+
|
|
254
|
+
eventDispatcher?.dispatchEvent(event)
|
|
267
255
|
}
|
|
268
256
|
|
|
269
257
|
fun setCustomKeyText(text: String) {
|
|
270
258
|
customKeyButton?.text = text
|
|
271
259
|
}
|
|
272
260
|
|
|
261
|
+
fun setMode(mode: String) {
|
|
262
|
+
keyboardMode = mode
|
|
263
|
+
renderUI()
|
|
264
|
+
}
|
|
265
|
+
|
|
273
266
|
fun setCustomKeyBackground(background: Int) {
|
|
274
267
|
customKeyButtonBackground = background
|
|
275
|
-
updateCustomKeyUI(background, customKeyButtonTextColor
|
|
268
|
+
updateCustomKeyUI(background, customKeyButtonTextColor)
|
|
276
269
|
}
|
|
277
270
|
|
|
278
271
|
fun setCustomKeyTextColor(textColor: Int) {
|
|
279
272
|
customKeyButtonTextColor = textColor
|
|
280
|
-
updateCustomKeyUI(customKeyButtonBackground, textColor
|
|
273
|
+
updateCustomKeyUI(customKeyButtonBackground, textColor)
|
|
281
274
|
}
|
|
282
275
|
|
|
283
276
|
|
|
284
277
|
fun setCustomKeyState(state: String) {
|
|
285
278
|
customKeyButtonState = state
|
|
286
279
|
customKeyButton?.isEnabled = state != "disable"
|
|
287
|
-
updateCustomKeyUI(customKeyButtonBackground, customKeyButtonTextColor
|
|
280
|
+
updateCustomKeyUI(customKeyButtonBackground, customKeyButtonTextColor)
|
|
288
281
|
}
|
|
289
282
|
|
|
290
|
-
private fun updateCustomKeyUI(background: Int, textColor: Int
|
|
291
|
-
|
|
283
|
+
private fun updateCustomKeyUI(background: Int, textColor: Int){
|
|
292
284
|
customKeyButton?.background = GradientDrawable().apply {
|
|
293
285
|
shape = GradientDrawable.RECTANGLE
|
|
294
286
|
cornerRadius = 24f
|
|
@@ -297,5 +289,4 @@ class CustomKeyboardView(
|
|
|
297
289
|
customKeyButton?.setTextColor(textColor)
|
|
298
290
|
}
|
|
299
291
|
|
|
300
|
-
|
|
301
292
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
package com.calculatorkeyboard
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.WritableMap
|
|
4
|
+
import com.facebook.react.uimanager.events.Event
|
|
5
|
+
|
|
6
|
+
class OnChangeEvent(
|
|
7
|
+
surfaceId: Int,
|
|
8
|
+
viewId: Int,
|
|
9
|
+
private val payload: WritableMap
|
|
10
|
+
) : Event<OnChangeEvent>(surfaceId, viewId) {
|
|
11
|
+
override fun getEventName() = "onChange"
|
|
12
|
+
|
|
13
|
+
override fun getEventData() = payload
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
class OnKeyPressEvent(
|
|
17
|
+
surfaceId: Int,
|
|
18
|
+
viewId: Int,
|
|
19
|
+
private val payload: WritableMap
|
|
20
|
+
) : Event<OnChangeEvent>(surfaceId, viewId) {
|
|
21
|
+
override fun getEventName() = "onKeyPress"
|
|
22
|
+
|
|
23
|
+
override fun getEventData() = payload
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
class OnCustomKeyPressEvent(
|
|
27
|
+
surfaceId: Int,
|
|
28
|
+
viewId: Int
|
|
29
|
+
) : Event<OnChangeEvent>(surfaceId, viewId) {
|
|
30
|
+
override fun getEventName() = "onCustomKeyEvent"
|
|
31
|
+
|
|
32
|
+
override fun getEventData() = null
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
@@ -3,20 +3,43 @@ package com.calculatorkeyboard
|
|
|
3
3
|
import android.annotation.SuppressLint
|
|
4
4
|
import android.content.Context
|
|
5
5
|
import android.graphics.Color
|
|
6
|
+
import android.graphics.Typeface
|
|
7
|
+
import android.os.Build
|
|
8
|
+
import android.provider.Settings.Global.putString
|
|
9
|
+
import android.text.Editable
|
|
10
|
+
import android.text.TextWatcher
|
|
6
11
|
import android.view.KeyEvent
|
|
7
12
|
import android.view.inputmethod.InputMethodManager
|
|
8
13
|
import androidx.core.graphics.toColorInt
|
|
9
14
|
import androidx.core.view.ViewCompat
|
|
10
15
|
import androidx.core.view.WindowInsetsCompat
|
|
16
|
+
import androidx.core.widget.addTextChangedListener
|
|
17
|
+
import com.facebook.react.bridge.Arguments
|
|
18
|
+
import com.facebook.react.bridge.ReactContext
|
|
11
19
|
import com.facebook.react.bridge.ReadableArray
|
|
20
|
+
import com.facebook.react.bridge.ReadableMap
|
|
12
21
|
import com.facebook.react.bridge.UiThreadUtil
|
|
22
|
+
import com.facebook.react.module.annotations.ReactModule
|
|
13
23
|
import com.facebook.react.uimanager.PixelUtil.dpToPx
|
|
24
|
+
import com.facebook.react.uimanager.SimpleViewManager
|
|
14
25
|
import com.facebook.react.uimanager.ThemedReactContext
|
|
26
|
+
import com.facebook.react.uimanager.UIManagerHelper
|
|
27
|
+
import com.facebook.react.uimanager.ViewManagerDelegate
|
|
15
28
|
import com.facebook.react.uimanager.annotations.ReactProp
|
|
29
|
+
import com.facebook.react.uimanager.events.RCTEventEmitter
|
|
30
|
+
import com.facebook.react.viewmanagers.NativeInputCalculatorManagerDelegate
|
|
31
|
+
import com.facebook.react.viewmanagers.NativeInputCalculatorManagerInterface
|
|
16
32
|
import com.facebook.react.views.textinput.ReactEditText
|
|
17
33
|
import com.facebook.react.views.textinput.ReactTextInputManager
|
|
18
34
|
|
|
19
|
-
|
|
35
|
+
@ReactModule(name = InputCalculatorViewManager.REACT_CLASS)
|
|
36
|
+
class InputCalculatorViewManager : SimpleViewManager<ReactEditText>(), NativeInputCalculatorManagerInterface<ReactEditText> {
|
|
37
|
+
private val delegate: NativeInputCalculatorManagerDelegate<ReactEditText, InputCalculatorViewManager> =
|
|
38
|
+
NativeInputCalculatorManagerDelegate(this)
|
|
39
|
+
|
|
40
|
+
override fun getDelegate(): ViewManagerDelegate<ReactEditText> = delegate
|
|
41
|
+
|
|
42
|
+
override fun getName() = REACT_CLASS
|
|
20
43
|
|
|
21
44
|
private var keyboardView: CustomKeyboardView? = null
|
|
22
45
|
private lateinit var editText: CalculatorEditText
|
|
@@ -27,15 +50,14 @@ class RCTInputCalculator : ReactTextInputManager() {
|
|
|
27
50
|
private var backListenerAttached = false
|
|
28
51
|
private var overlayShowing = false
|
|
29
52
|
|
|
30
|
-
override fun getName() = REACT_CLASS
|
|
31
53
|
|
|
32
54
|
companion object {
|
|
33
|
-
const val REACT_CLASS = "
|
|
55
|
+
const val REACT_CLASS = "NativeInputCalculator"
|
|
34
56
|
val calculatorHeight: Int = 240.dpToPx().toInt()
|
|
35
57
|
}
|
|
36
58
|
|
|
37
59
|
@ReactProp(name = "value")
|
|
38
|
-
fun setValue(view: ReactEditText, value: String?) {
|
|
60
|
+
override fun setValue(view: ReactEditText, value: String?) {
|
|
39
61
|
UiThreadUtil.runOnUiThread {
|
|
40
62
|
val e = view.editableText ?: run { view.setText(value ?: ""); return@runOnUiThread }
|
|
41
63
|
val newText = value ?: ""
|
|
@@ -48,29 +70,72 @@ class RCTInputCalculator : ReactTextInputManager() {
|
|
|
48
70
|
}
|
|
49
71
|
}
|
|
50
72
|
|
|
73
|
+
override fun setTextAttributes(view: ReactEditText?, value: ReadableMap?) {
|
|
74
|
+
val fontWeightStr = value?.getString("fontWeight")
|
|
75
|
+
val fontSize = value?.getDouble("fontSize")
|
|
76
|
+
|
|
77
|
+
fontWeightStr?.let { weightStr ->
|
|
78
|
+
val weight = when (weightStr) {
|
|
79
|
+
"100" -> 100
|
|
80
|
+
"200" -> 200
|
|
81
|
+
"300" -> 300
|
|
82
|
+
"400", "normal" -> 400
|
|
83
|
+
"500" -> 500
|
|
84
|
+
"600" -> 600
|
|
85
|
+
"700", "bold" -> 700
|
|
86
|
+
"800" -> 800
|
|
87
|
+
"900" -> 900
|
|
88
|
+
else -> 400
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
|
92
|
+
view?.typeface = Typeface.create(view.typeface, weight, false)
|
|
93
|
+
} else {
|
|
94
|
+
view?.typeface = if (weight >= 600) {
|
|
95
|
+
Typeface.create(view.typeface, Typeface.BOLD)
|
|
96
|
+
} else {
|
|
97
|
+
Typeface.create(view.typeface, Typeface.NORMAL)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
fontSize?.let {
|
|
103
|
+
view?.textSize = it.toFloat()
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@ReactProp(name = "mode")
|
|
109
|
+
override fun setMode(view: ReactEditText, mode: String?) {
|
|
110
|
+
keyboardView?.setMode(mode ?: "NumDefault")
|
|
111
|
+
}
|
|
112
|
+
|
|
51
113
|
@ReactProp(name = "customKeyText")
|
|
52
|
-
fun setCustomKeyText(view: ReactEditText, text: String?) {
|
|
53
|
-
keyboardView?.setCustomKeyText(text ?: "
|
|
114
|
+
override fun setCustomKeyText(view: ReactEditText, text: String?) {
|
|
115
|
+
keyboardView?.setCustomKeyText(text ?: "Tiếp")
|
|
54
116
|
}
|
|
55
117
|
|
|
56
118
|
@ReactProp(name = "customKeyBackground")
|
|
57
|
-
fun setCustomKeyBackground(view: ReactEditText, background: String?) {
|
|
119
|
+
override fun setCustomKeyBackground(view: ReactEditText, background: String?) {
|
|
58
120
|
keyboardView?.setCustomKeyBackground((background ?: "#d8d8d8").toColorInt())
|
|
59
121
|
}
|
|
60
122
|
|
|
61
123
|
@ReactProp(name = "customKeyTextColor")
|
|
62
|
-
fun setCustomKeyTextColor(view: ReactEditText, textColor: String?) {
|
|
124
|
+
override fun setCustomKeyTextColor(view: ReactEditText, textColor: String?) {
|
|
63
125
|
keyboardView?.setCustomKeyTextColor(textColor?.toColorInt() ?: Color.BLACK)
|
|
64
126
|
}
|
|
65
127
|
|
|
66
128
|
@ReactProp(name = "customKeyState")
|
|
67
|
-
fun setCustomKeyState(view: ReactEditText, state: String?) {
|
|
129
|
+
override fun setCustomKeyState(view: ReactEditText, state: String?) {
|
|
68
130
|
keyboardView?.setCustomKeyState(state ?: "default")
|
|
69
131
|
}
|
|
70
132
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
133
|
+
override fun focus(view: ReactEditText?) {
|
|
134
|
+
UiThreadUtil.runOnUiThread { if (!editText.isFocused) editText.requestFocus() }
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
override fun blur(view: ReactEditText?) {
|
|
138
|
+
UiThreadUtil.runOnUiThread { if (editText.isFocused) editText.clearFocus() }
|
|
74
139
|
}
|
|
75
140
|
|
|
76
141
|
@SuppressLint("ClickableViewAccessibility")
|
|
@@ -101,6 +166,16 @@ class RCTInputCalculator : ReactTextInputManager() {
|
|
|
101
166
|
}
|
|
102
167
|
false
|
|
103
168
|
}
|
|
169
|
+
addTextChangedListener(object : TextWatcher{
|
|
170
|
+
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
|
171
|
+
|
|
172
|
+
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
|
|
173
|
+
|
|
174
|
+
override fun afterTextChanged(s: Editable?) {
|
|
175
|
+
emitOnChange(context, s.toString())
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
})
|
|
104
179
|
}
|
|
105
180
|
|
|
106
181
|
keyboardView = CustomKeyboardView(context, editText).apply {
|
|
@@ -165,33 +240,31 @@ class RCTInputCalculator : ReactTextInputManager() {
|
|
|
165
240
|
v.showSoftInputOnFocus = true
|
|
166
241
|
}
|
|
167
242
|
|
|
168
|
-
|
|
243
|
+
private fun emitOnChange(context: Context, text: String) {
|
|
244
|
+
val reactContext = context as ReactContext
|
|
245
|
+
val surfaceId = UIManagerHelper.getSurfaceId(reactContext)
|
|
246
|
+
val eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, editText.id)
|
|
247
|
+
val payload =
|
|
248
|
+
Arguments.createMap().apply {
|
|
249
|
+
putString("text", text)
|
|
250
|
+
}
|
|
251
|
+
val event = OnChangeEvent(surfaceId, editText.id, payload)
|
|
169
252
|
|
|
170
|
-
|
|
171
|
-
when (commandId) {
|
|
172
|
-
1 -> blur()
|
|
173
|
-
2 -> focus()
|
|
174
|
-
}
|
|
253
|
+
eventDispatcher?.dispatchEvent(event)
|
|
175
254
|
}
|
|
176
255
|
|
|
177
256
|
override fun getExportedCustomBubblingEventTypeConstants(): MutableMap<String, Any> {
|
|
178
|
-
val base = super.getExportedCustomBubblingEventTypeConstants()
|
|
257
|
+
val base = super.getExportedCustomBubblingEventTypeConstants()?.toMutableMap() ?: mutableMapOf()
|
|
179
258
|
base["onKeyPress"] = mapOf("phasedRegistrationNames" to mapOf("bubbled" to "onKeyPress"))
|
|
259
|
+
base["onChange"] = mapOf("phasedRegistrationNames" to mapOf("bubbled" to "onChange"))
|
|
180
260
|
return base
|
|
181
261
|
}
|
|
182
262
|
|
|
183
263
|
override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> {
|
|
184
|
-
val base = super.getExportedCustomDirectEventTypeConstants()
|
|
264
|
+
val base = super.getExportedCustomDirectEventTypeConstants()?.toMutableMap() ?: mutableMapOf()
|
|
185
265
|
base["onCustomKeyEvent"] = mapOf("registrationName" to "onCustomKeyEvent")
|
|
186
266
|
return base
|
|
187
267
|
}
|
|
188
268
|
|
|
189
|
-
private fun focus() {
|
|
190
|
-
UiThreadUtil.runOnUiThread { if (!editText.isFocused) editText.requestFocus() }
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
private fun blur() {
|
|
194
|
-
UiThreadUtil.runOnUiThread { if (editText.isFocused) editText.clearFocus() }
|
|
195
|
-
}
|
|
196
269
|
}
|
|
197
270
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#import <UIKit/UIKit.h>
|
|
2
|
+
|
|
3
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
4
|
+
|
|
5
|
+
@protocol CalculatorKeyboardInput <NSObject>
|
|
6
|
+
|
|
7
|
+
- (void)keyDidPress:(NSString *)key;
|
|
8
|
+
- (void)clearText;
|
|
9
|
+
- (void)onBackSpace;
|
|
10
|
+
- (void)calculateResult;
|
|
11
|
+
- (void)emitCustomKey;
|
|
12
|
+
- (void)emitKeyPress:(NSString *)key;
|
|
13
|
+
|
|
14
|
+
@end
|
|
15
|
+
|
|
16
|
+
@interface CalculatorKeyboardView : UIView
|
|
17
|
+
|
|
18
|
+
@property (nonatomic, weak, nullable) id<CalculatorKeyboardInput> input;
|
|
19
|
+
@property (nonatomic, strong, nullable) NSString *keyboardMode;
|
|
20
|
+
@property (nonatomic, strong, nullable) NSString *customKeyText;
|
|
21
|
+
@property (nonatomic, strong, nullable) NSString *customKeyBackground;
|
|
22
|
+
@property (nonatomic, strong, nullable) NSString *customKeyTextColor;
|
|
23
|
+
@property (nonatomic, strong, nullable) NSString *customKeyState;
|
|
24
|
+
|
|
25
|
+
- (void)setKeyboardColor:(UIColor *)color;
|
|
26
|
+
|
|
27
|
+
@end
|
|
28
|
+
|
|
29
|
+
NS_ASSUME_NONNULL_END
|
|
30
|
+
|