@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(context: ThemedReactContext, private val editText: CalculatorEditText) :
18
- ConstraintLayout(context) {
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 keyboardColor: Int = Color.parseColor("#F7ACD5")
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(Color.parseColor("#F7ACD5"))
102
+ setColor(specialButtonColor)
105
103
  }
106
- setTextColor(Color.WHITE)
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(Color.parseColor("#F7ACD5"))
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
- keyboardColor = color
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(keyboardColor)
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(ColorUtils.setAlphaComponent(keyboardColor, 128))
160
+ setColor(specialButtonColor)
162
161
  }
163
162
  }
164
- child.setTextColor(Color.WHITE)
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(ColorUtils.setAlphaComponent(keyboardColor, 128))
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.ViewGroup
10
+ import android.view.WindowInsets
11
11
  import android.view.WindowManager
12
- import android.view.inputmethod.InputMethodManager
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 = 0
25
- private var addedWithWM = false
26
- private val ANIM_DURATION = 250L
29
+ private var calculatorHeight: Int = 290.dpToPx().toInt()
30
+ private var popup: PopupWindow? = null
31
+ private val animationDuration = 250L
27
32
 
28
- private var outsideOverlay: View? = null
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(Color.parseColor(color))
48
+ keyboardView?.updateButtonColors(color.toColorInt())
44
49
  }
45
50
 
46
51
  @SuppressLint("ClickableViewAccessibility")
47
52
  override fun createViewInstance(context: ThemedReactContext): ReactEditText {
48
- val editText = CalculatorEditText(context)
49
- editText.showSoftInputOnFocus = false
53
+ editText = CalculatorEditText(context).apply {
54
+ showSoftInputOnFocus = false
55
+ }
50
56
 
51
- layout = ConstraintLayout(context)
52
57
  keyboardView = CustomKeyboardView(context, editText).apply {
53
- setBackgroundColor(Color.parseColor("#f2f2f6"))
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
- addContentViewForDialog(context, view)
66
+ showKeyboardPopup(view)
72
67
  } else {
73
- removeContentViewForDialog(context)
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
- private fun ensureOverlay(context: ThemedReactContext, anchor: View) {
89
- if (outsideOverlay != null) return
90
- outsideOverlay = View(context).apply {
91
- layoutParams = ViewGroup.LayoutParams(
92
- ViewGroup.LayoutParams.MATCH_PARENT,
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
- private fun addContentViewForDialog(context: ThemedReactContext, anchor: View) {
105
- val root = layout ?: return
106
- if (addedWithWM || root.parent != null) return
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
- val wm = context.getSystemService(android.content.Context.WINDOW_SERVICE) as WindowManager
97
+ private fun ensurePopup() {
98
+ if (popup != null) return
99
+ val content = keyboardView ?: return
125
100
 
126
- val lp = WindowManager.LayoutParams(
101
+ popup = PopupWindow(
102
+ content,
127
103
  WindowManager.LayoutParams.MATCH_PARENT,
128
- WindowManager.LayoutParams.MATCH_PARENT,
129
- WindowManager.LayoutParams.TYPE_APPLICATION_PANEL,
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
- gravity = Gravity.BOTTOM
135
- token = anchor.applicationWindowToken
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
- wm.addView(root, lp)
141
- addedWithWM = true
129
+ p.showAtLocation(anchor.rootView, Gravity.BOTTOM or Gravity.START, 0, 0)
142
130
 
143
- root.animate().translationY(0f).setDuration(ANIM_DURATION).start()
131
+ root.animate()
132
+ ?.translationY(0f)
133
+ ?.setDuration(animationDuration)
134
+ ?.start()
144
135
  }
145
136
 
146
- private fun removeContentViewForDialog(context: ThemedReactContext) {
147
- if (!addedWithWM) return
148
- val wm = context.getSystemService(android.content.Context.WINDOW_SERVICE) as WindowManager
149
- val root = layout ?: return
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(ANIM_DURATION)
144
+ .setDuration(animationDuration)
154
145
  .withEndAction {
155
146
  try {
156
- wm.removeViewImmediate(root)
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 hideIme(context: ThemedReactContext, v: View) {
164
- val imm = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
165
- imm.hideSoftInputFromWindow(v.windowToken, 0)
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: "#d9d9d9")) {
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 = .white
80
+ button.tintColor = .black
81
81
  }
82
82
 
83
83
  if specialKeys.contains(key) {
84
- button.setTitleColor(.white, for: .normal)
85
- button.backgroundColor = color.withAlphaComponent(0.5)
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/calculator-keyboard",
3
- "version": "0.112.1-rn76.76",
3
+ "version": "0.112.1-rn80.1",
4
4
  "description": "react native calculator keyboard",
5
5
  "source": "./src/index.tsx",
6
6
  "main": "./lib/commonjs/index.js",