@momo-kits/calculator-keyboard 0.112.1-rn76.76 → 0.112.1-rn80.1
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.
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
package com.calculatorkeyboard
|
|
2
2
|
|
|
3
3
|
import android.annotation.SuppressLint
|
|
4
|
+
import android.content.res.ColorStateList
|
|
4
5
|
import android.graphics.Color
|
|
5
6
|
import android.graphics.drawable.GradientDrawable
|
|
6
7
|
import android.view.Gravity
|
|
@@ -11,11 +12,15 @@ import androidx.constraintlayout.widget.ConstraintLayout
|
|
|
11
12
|
import androidx.core.graphics.ColorUtils
|
|
12
13
|
import com.facebook.react.uimanager.ThemedReactContext
|
|
13
14
|
import org.mariuszgromada.math.mxparser.Expression
|
|
15
|
+
import androidx.core.graphics.toColorInt
|
|
16
|
+
import com.facebook.react.uimanager.PixelUtil.dpToPx
|
|
14
17
|
|
|
15
18
|
|
|
16
19
|
@SuppressLint("SetTextI18n", "ViewConstructor")
|
|
17
|
-
class CustomKeyboardView(
|
|
18
|
-
|
|
20
|
+
class CustomKeyboardView(
|
|
21
|
+
context: ThemedReactContext,
|
|
22
|
+
private val editText: CalculatorEditText
|
|
23
|
+
) : ConstraintLayout(context) {
|
|
19
24
|
private val keys = listOf(
|
|
20
25
|
listOf("AC", "÷", "×", "back"),
|
|
21
26
|
listOf("7", "8", "9", "-"),
|
|
@@ -25,21 +30,21 @@ class CustomKeyboardView(context: ThemedReactContext, private val editText: Calc
|
|
|
25
30
|
)
|
|
26
31
|
private val specialKeys = listOf("=", "-", "×", "÷", "AC", "back", "+")
|
|
27
32
|
private val separatorWidth = 8f
|
|
28
|
-
private var
|
|
33
|
+
private var specialButtonColor: Int = "#D8D8D8".toColorInt()
|
|
29
34
|
|
|
30
35
|
init {
|
|
31
36
|
val activity = context.currentActivity as? AppCompatActivity
|
|
32
37
|
if (activity != null) {
|
|
33
38
|
val displayMetrics = resources.displayMetrics
|
|
34
39
|
val widthButton = (displayMetrics.widthPixels - separatorWidth * 2 - 3 * separatorWidth) / 4f
|
|
40
|
+
val heightButton = (290.dpToPx() - separatorWidth * 2 - 4 * separatorWidth) / 5
|
|
35
41
|
|
|
36
|
-
renderUI(widthButton)
|
|
42
|
+
renderUI(widthButton, heightButton)
|
|
37
43
|
}
|
|
38
44
|
|
|
39
45
|
}
|
|
40
46
|
|
|
41
|
-
private fun renderUI(buttonWidth: Float) {
|
|
42
|
-
val buttonHeight = buttonWidth / 2
|
|
47
|
+
private fun renderUI(buttonWidth: Float, buttonHeight: Float) {
|
|
43
48
|
var yOffset = separatorWidth
|
|
44
49
|
for ((_, row) in keys.withIndex()) {
|
|
45
50
|
var xOffset = separatorWidth
|
|
@@ -91,19 +96,12 @@ class CustomKeyboardView(context: ThemedReactContext, private val editText: Calc
|
|
|
91
96
|
}
|
|
92
97
|
|
|
93
98
|
if (specialKeys.contains(key)) {
|
|
94
|
-
if (key == "=") {
|
|
95
|
-
background = GradientDrawable().apply {
|
|
96
|
-
shape = GradientDrawable.RECTANGLE
|
|
97
|
-
cornerRadius = 24f
|
|
98
|
-
setColor(Color.parseColor("#EB2F96"))
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
99
|
background = GradientDrawable().apply {
|
|
102
100
|
shape = GradientDrawable.RECTANGLE
|
|
103
101
|
cornerRadius = 24f
|
|
104
|
-
setColor(
|
|
102
|
+
setColor(specialButtonColor)
|
|
105
103
|
}
|
|
106
|
-
setTextColor(Color.
|
|
104
|
+
setTextColor(Color.BLACK)
|
|
107
105
|
}
|
|
108
106
|
|
|
109
107
|
|
|
@@ -124,7 +122,7 @@ class CustomKeyboardView(context: ThemedReactContext, private val editText: Calc
|
|
|
124
122
|
val shapeInit = GradientDrawable().apply {
|
|
125
123
|
shape = GradientDrawable.RECTANGLE
|
|
126
124
|
cornerRadius = 24f
|
|
127
|
-
setColor(
|
|
125
|
+
setColor(specialButtonColor)
|
|
128
126
|
}
|
|
129
127
|
background = shapeInit
|
|
130
128
|
stateListAnimator = null
|
|
@@ -137,12 +135,13 @@ class CustomKeyboardView(context: ThemedReactContext, private val editText: Calc
|
|
|
137
135
|
translationX = xOffset
|
|
138
136
|
translationY = yOffset
|
|
139
137
|
setImageResource(android.R.drawable.ic_input_delete)
|
|
138
|
+
setImageTintList(ColorStateList.valueOf(Color.BLACK))
|
|
140
139
|
setOnClickListener { onKeyPress(key) }
|
|
141
140
|
}
|
|
142
141
|
}
|
|
143
142
|
|
|
144
143
|
fun updateButtonColors(color: Int) {
|
|
145
|
-
|
|
144
|
+
specialButtonColor = color
|
|
146
145
|
for (i in 0 until childCount) {
|
|
147
146
|
val child = getChildAt(i)
|
|
148
147
|
if (child is Button) {
|
|
@@ -152,22 +151,22 @@ class CustomKeyboardView(context: ThemedReactContext, private val editText: Calc
|
|
|
152
151
|
child.background = GradientDrawable().apply {
|
|
153
152
|
shape = GradientDrawable.RECTANGLE
|
|
154
153
|
cornerRadius = 24f
|
|
155
|
-
setColor(
|
|
154
|
+
setColor(specialButtonColor)
|
|
156
155
|
}
|
|
157
156
|
} else {
|
|
158
157
|
child.background = GradientDrawable().apply {
|
|
159
158
|
shape = GradientDrawable.RECTANGLE
|
|
160
159
|
cornerRadius = 24f
|
|
161
|
-
setColor(
|
|
160
|
+
setColor(specialButtonColor)
|
|
162
161
|
}
|
|
163
162
|
}
|
|
164
|
-
child.setTextColor(Color.
|
|
163
|
+
child.setTextColor(Color.BLACK)
|
|
165
164
|
}
|
|
166
165
|
} else if (child is ImageButton) {
|
|
167
166
|
child.background = GradientDrawable().apply {
|
|
168
167
|
shape = GradientDrawable.RECTANGLE
|
|
169
168
|
cornerRadius = 24f
|
|
170
|
-
setColor(
|
|
169
|
+
setColor(specialButtonColor)
|
|
171
170
|
}
|
|
172
171
|
}
|
|
173
172
|
}
|
|
@@ -188,6 +187,7 @@ class CustomKeyboardView(context: ThemedReactContext, private val editText: Calc
|
|
|
188
187
|
}
|
|
189
188
|
|
|
190
189
|
"×", "+", "-", "÷" -> keyDidPress(" $key ")
|
|
190
|
+
|
|
191
191
|
else -> {
|
|
192
192
|
editText.text?.insert(editText.selectionStart, key)
|
|
193
193
|
}
|
|
@@ -2,30 +2,35 @@ package com.calculatorkeyboard
|
|
|
2
2
|
|
|
3
3
|
import android.annotation.SuppressLint
|
|
4
4
|
import android.app.Activity
|
|
5
|
-
import android.graphics.Color
|
|
6
5
|
import android.graphics.PixelFormat
|
|
6
|
+
import android.graphics.drawable.ColorDrawable
|
|
7
7
|
import android.view.Gravity
|
|
8
8
|
import android.view.KeyEvent
|
|
9
9
|
import android.view.View
|
|
10
|
-
import android.view.
|
|
10
|
+
import android.view.WindowInsets
|
|
11
11
|
import android.view.WindowManager
|
|
12
|
-
import android.
|
|
12
|
+
import android.widget.PopupWindow
|
|
13
13
|
import androidx.constraintlayout.widget.ConstraintLayout
|
|
14
|
+
import androidx.core.graphics.toColorInt
|
|
15
|
+
import com.facebook.react.bridge.ReadableArray
|
|
14
16
|
import com.facebook.react.bridge.UiThreadUtil
|
|
15
17
|
import com.facebook.react.uimanager.ThemedReactContext
|
|
16
18
|
import com.facebook.react.uimanager.annotations.ReactProp
|
|
17
19
|
import com.facebook.react.views.textinput.ReactEditText
|
|
18
20
|
import com.facebook.react.views.textinput.ReactTextInputManager
|
|
21
|
+
import androidx.core.graphics.drawable.toDrawable
|
|
22
|
+
import androidx.core.view.ViewCompat
|
|
23
|
+
import androidx.core.view.WindowInsetsCompat
|
|
24
|
+
import com.facebook.react.uimanager.PixelUtil.dpToPx
|
|
19
25
|
|
|
20
26
|
class RCTInputCalculator : ReactTextInputManager() {
|
|
21
27
|
|
|
22
|
-
private var layout: ConstraintLayout? = null
|
|
23
28
|
private var keyboardView: CustomKeyboardView? = null
|
|
24
|
-
private var calculatorHeight: Int =
|
|
25
|
-
private var
|
|
26
|
-
private val
|
|
29
|
+
private var calculatorHeight: Int = 290.dpToPx().toInt()
|
|
30
|
+
private var popup: PopupWindow? = null
|
|
31
|
+
private val animationDuration = 250L
|
|
27
32
|
|
|
28
|
-
private var
|
|
33
|
+
private lateinit var editText: CalculatorEditText
|
|
29
34
|
|
|
30
35
|
override fun getName() = REACT_CLASS
|
|
31
36
|
|
|
@@ -35,42 +40,32 @@ class RCTInputCalculator : ReactTextInputManager() {
|
|
|
35
40
|
|
|
36
41
|
@ReactProp(name = "value")
|
|
37
42
|
fun setValue(view: ReactEditText, value: String?) {
|
|
38
|
-
view.setText(value)
|
|
43
|
+
// view.setText(value)
|
|
39
44
|
}
|
|
40
45
|
|
|
41
46
|
@ReactProp(name = "keyboardColor")
|
|
42
47
|
fun setKeyboardColor(view: ReactEditText, color: String) {
|
|
43
|
-
keyboardView?.updateButtonColors(
|
|
48
|
+
keyboardView?.updateButtonColors(color.toColorInt())
|
|
44
49
|
}
|
|
45
50
|
|
|
46
51
|
@SuppressLint("ClickableViewAccessibility")
|
|
47
52
|
override fun createViewInstance(context: ThemedReactContext): ReactEditText {
|
|
48
|
-
|
|
49
|
-
|
|
53
|
+
editText = CalculatorEditText(context).apply {
|
|
54
|
+
showSoftInputOnFocus = false
|
|
55
|
+
}
|
|
50
56
|
|
|
51
|
-
layout = ConstraintLayout(context)
|
|
52
57
|
keyboardView = CustomKeyboardView(context, editText).apply {
|
|
53
|
-
setBackgroundColor(
|
|
58
|
+
setBackgroundColor("#f2f2f6".toColorInt())
|
|
54
59
|
elevation = 24f
|
|
55
60
|
}
|
|
56
61
|
|
|
57
|
-
val dm = context.currentActivity!!.resources.displayMetrics
|
|
58
|
-
calculatorHeight = (dm.widthPixels * 0.675f).toInt()
|
|
59
|
-
|
|
60
|
-
editText.setOnClickListener { v: View ->
|
|
61
|
-
UiThreadUtil.runOnUiThread {
|
|
62
|
-
hideIme(context, v)
|
|
63
|
-
if (!editText.isFocused) editText.requestFocusFromJS()
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
62
|
editText.onFocusListener = object : CalculatorEditText.OnFocusChangeListener {
|
|
68
63
|
override fun onFocusChange(view: CalculatorEditText, hasFocus: Boolean) {
|
|
69
64
|
UiThreadUtil.runOnUiThread {
|
|
70
65
|
if (hasFocus) {
|
|
71
|
-
|
|
66
|
+
showKeyboardPopup(view)
|
|
72
67
|
} else {
|
|
73
|
-
|
|
68
|
+
hideKeyboardPopup()
|
|
74
69
|
}
|
|
75
70
|
view.setOnKeyListener { v, keyCode, _ ->
|
|
76
71
|
if (keyCode == KeyEvent.KEYCODE_BACK && hasFocus) {
|
|
@@ -85,83 +80,87 @@ class RCTInputCalculator : ReactTextInputManager() {
|
|
|
85
80
|
return editText
|
|
86
81
|
}
|
|
87
82
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
ViewGroup.LayoutParams.MATCH_PARENT
|
|
94
|
-
)
|
|
95
|
-
setBackgroundColor(Color.TRANSPARENT)
|
|
96
|
-
isClickable = true
|
|
97
|
-
isFocusable = true
|
|
98
|
-
setOnClickListener {
|
|
99
|
-
anchor.clearFocus()
|
|
100
|
-
}
|
|
101
|
-
}
|
|
83
|
+
override fun getCommandsMap(): Map<String, Int> {
|
|
84
|
+
return mapOf(
|
|
85
|
+
"blur" to 1,
|
|
86
|
+
"focus" to 2
|
|
87
|
+
)
|
|
102
88
|
}
|
|
103
89
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
ensureOverlay(context, anchor)
|
|
109
|
-
|
|
110
|
-
if (outsideOverlay?.parent == null) {
|
|
111
|
-
root.addView(outsideOverlay)
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (keyboardView?.parent == null) {
|
|
115
|
-
val lp = ConstraintLayout.LayoutParams(
|
|
116
|
-
ConstraintLayout.LayoutParams.MATCH_PARENT,
|
|
117
|
-
calculatorHeight
|
|
118
|
-
).apply {
|
|
119
|
-
bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID
|
|
120
|
-
}
|
|
121
|
-
root.addView(keyboardView, lp)
|
|
90
|
+
override fun receiveCommand(reactEditText: ReactEditText, commandId: Int, args: ReadableArray?) {
|
|
91
|
+
when (commandId) {
|
|
92
|
+
1 -> blur()
|
|
93
|
+
2 -> focus()
|
|
122
94
|
}
|
|
95
|
+
}
|
|
123
96
|
|
|
124
|
-
|
|
97
|
+
private fun ensurePopup() {
|
|
98
|
+
if (popup != null) return
|
|
99
|
+
val content = keyboardView ?: return
|
|
125
100
|
|
|
126
|
-
|
|
101
|
+
popup = PopupWindow(
|
|
102
|
+
content,
|
|
127
103
|
WindowManager.LayoutParams.MATCH_PARENT,
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN or
|
|
131
|
-
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
|
|
132
|
-
PixelFormat.TRANSLUCENT
|
|
104
|
+
calculatorHeight + bottomInsetFrom(editText.rootView),
|
|
105
|
+
false
|
|
133
106
|
).apply {
|
|
134
|
-
|
|
135
|
-
|
|
107
|
+
setBackgroundDrawable(android.graphics.Color.TRANSPARENT.toDrawable())
|
|
108
|
+
isOutsideTouchable = false
|
|
109
|
+
isClippingEnabled = false
|
|
136
110
|
softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING
|
|
111
|
+
inputMethodMode = PopupWindow.INPUT_METHOD_NOT_NEEDED
|
|
137
112
|
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
private fun bottomInsetFrom(view: View): Int {
|
|
116
|
+
val insets = ViewCompat.getRootWindowInsets(view) ?: return 0
|
|
117
|
+
val mask = WindowInsetsCompat.Type.navigationBars() or WindowInsetsCompat.Type.displayCutout()
|
|
118
|
+
return insets.getInsets(mask).bottom
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
private fun showKeyboardPopup(anchor: View) {
|
|
122
|
+
ensurePopup()
|
|
123
|
+
val p = popup ?: return
|
|
124
|
+
if (p.isShowing) return
|
|
125
|
+
|
|
126
|
+
val root = keyboardView ?: return
|
|
138
127
|
|
|
139
128
|
root.translationY = calculatorHeight.toFloat()
|
|
140
|
-
|
|
141
|
-
addedWithWM = true
|
|
129
|
+
p.showAtLocation(anchor.rootView, Gravity.BOTTOM or Gravity.START, 0, 0)
|
|
142
130
|
|
|
143
|
-
root.animate()
|
|
131
|
+
root.animate()
|
|
132
|
+
?.translationY(0f)
|
|
133
|
+
?.setDuration(animationDuration)
|
|
134
|
+
?.start()
|
|
144
135
|
}
|
|
145
136
|
|
|
146
|
-
private fun
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
val root =
|
|
137
|
+
private fun hideKeyboardPopup() {
|
|
138
|
+
val p = popup ?: return
|
|
139
|
+
if (!p.isShowing) return
|
|
140
|
+
val root = keyboardView ?: return
|
|
150
141
|
|
|
151
142
|
root.animate()
|
|
152
143
|
.translationY(calculatorHeight.toFloat())
|
|
153
|
-
.setDuration(
|
|
144
|
+
.setDuration(animationDuration)
|
|
154
145
|
.withEndAction {
|
|
155
146
|
try {
|
|
156
|
-
|
|
157
|
-
} catch (_: Throwable) {}
|
|
158
|
-
addedWithWM = false
|
|
147
|
+
if (p.isShowing) p.dismiss()
|
|
148
|
+
} catch (_: Throwable) { }
|
|
159
149
|
}
|
|
160
150
|
.start()
|
|
151
|
+
|
|
152
|
+
popup = null
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
private fun focus() {
|
|
156
|
+
UiThreadUtil.runOnUiThread {
|
|
157
|
+
if (!editText.isFocused) editText.requestFocus()
|
|
158
|
+
}
|
|
161
159
|
}
|
|
162
160
|
|
|
163
|
-
private fun
|
|
164
|
-
|
|
165
|
-
|
|
161
|
+
private fun blur() {
|
|
162
|
+
UiThreadUtil.runOnUiThread {
|
|
163
|
+
if (editText.isFocused) editText.clearFocus()
|
|
164
|
+
}
|
|
166
165
|
}
|
|
167
|
-
}
|
|
166
|
+
}
|
|
@@ -30,7 +30,7 @@ class CalculatorKeyboardView: UIView {
|
|
|
30
30
|
self.setup(color)
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
private func setup(_ color: UIColor = UIColor(hex: "#
|
|
33
|
+
private func setup(_ color: UIColor = UIColor(hex: "#d8d8d8")) {
|
|
34
34
|
self.subviews.forEach { $0.removeFromSuperview() }
|
|
35
35
|
|
|
36
36
|
backgroundColor = UIColor(hex: "#f2f2f6")
|
|
@@ -77,15 +77,12 @@ class CalculatorKeyboardView: UIView {
|
|
|
77
77
|
button.setTitle("", for: .normal)
|
|
78
78
|
let image = UIImage(systemName: "delete.backward", withConfiguration: UIImage.SymbolConfiguration(weight: .bold))
|
|
79
79
|
button.setImage(image, for: .normal)
|
|
80
|
-
button.tintColor = .
|
|
80
|
+
button.tintColor = .black
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
if specialKeys.contains(key) {
|
|
84
|
-
button.setTitleColor(.
|
|
85
|
-
button.backgroundColor = color
|
|
86
|
-
if key == "=" {
|
|
87
|
-
button.backgroundColor = color
|
|
88
|
-
}
|
|
84
|
+
button.setTitleColor(.black, for: .normal)
|
|
85
|
+
button.backgroundColor = color
|
|
89
86
|
}
|
|
90
87
|
|
|
91
88
|
button.addTarget(self, action: #selector(keyPressed(_:)), for: .touchUpInside)
|
|
@@ -29,14 +29,18 @@ class InputCalculator: RCTSinglelineTextInputView {
|
|
|
29
29
|
super.init(bridge: bridge)
|
|
30
30
|
self.bridge = bridge
|
|
31
31
|
self.keyboardView = CalculatorKeyboardView()
|
|
32
|
-
self.keyboardView!.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 290)
|
|
32
|
+
self.keyboardView!.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 290 + getbottomInset())
|
|
33
33
|
self.keyboardView!.input = self
|
|
34
34
|
|
|
35
35
|
backedTextInputView.inputView = self.keyboardView
|
|
36
36
|
backedTextInputView.inputView?.reloadInputViews()
|
|
37
37
|
}
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
func getbottomInset() -> CGFloat {
|
|
39
|
+
let window = UIApplication.shared.windows.first?.rootViewController?.view
|
|
40
|
+
let bottom = (window?.safeAreaInsets.bottom ?? 0) > 0 ? 21 : 0
|
|
41
|
+
return CGFloat(bottom)
|
|
42
|
+
}
|
|
43
|
+
|
|
40
44
|
func keyDidPress(_ key: String) {
|
|
41
45
|
backedTextInputView.insertText(key)
|
|
42
46
|
value += key
|
|
@@ -87,7 +91,6 @@ class InputCalculator: RCTSinglelineTextInputView {
|
|
|
87
91
|
value = result.stringValue
|
|
88
92
|
if let bridge = bridge {
|
|
89
93
|
bridge.eventDispatcher().sendTextEvent(with: .change, reactTag: reactTag, text: value, key: "=", eventCount: 1)
|
|
90
|
-
textField.reactBlur()
|
|
91
94
|
}
|
|
92
95
|
}
|
|
93
96
|
}
|