From 03c0e5e2af288e96f39fa044cbbe8ebef91bdb1e Mon Sep 17 00:00:00 2001 From: Blake Friedman Date: Thu, 8 Aug 2024 03:17:26 -0700 Subject: [PATCH] =?UTF-8?q?ReactSwitch.java=20=E2=86=92=20Kotlin=20(#45931?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45931 Migration to Kotlin. Changelog: [Android][Changed] Migrated ReactSwitch to Kotlin Reviewed By: cortinico Differential Revision: D60898267 fbshipit-source-id: 530e240a071deb3eff3e463f04edc590de03c594 --- .../react/views/switchview/ReactSwitch.java | 124 ------------------ .../react/views/switchview/ReactSwitch.kt | 110 ++++++++++++++++ 2 files changed, 110 insertions(+), 124 deletions(-) delete mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/switchview/ReactSwitch.java create mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/switchview/ReactSwitch.kt diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/switchview/ReactSwitch.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/switchview/ReactSwitch.java deleted file mode 100644 index 2bdd48ecc40..00000000000 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/switchview/ReactSwitch.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.views.switchview; - -import android.content.Context; -import android.content.res.ColorStateList; -import android.graphics.PorterDuff; -import android.graphics.drawable.ColorDrawable; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.RippleDrawable; -import androidx.annotation.Nullable; -import androidx.appcompat.widget.SwitchCompat; - -/** - * Switch that has its value controlled by JS. Whenever the value of the switch changes, we do not - * allow any other changes to that switch until JS sets a value explicitly. This stops the Switch - * from changing its value multiple times, when those changes have not been processed by JS first. - */ -/*package*/ class ReactSwitch extends SwitchCompat { - - private boolean mAllowChange; - @Nullable private Integer mTrackColorForFalse; - @Nullable private Integer mTrackColorForTrue; - - public ReactSwitch(Context context) { - super(context); - mAllowChange = true; - mTrackColorForFalse = null; - mTrackColorForTrue = null; - } - - @Override - public void setChecked(boolean checked) { - if (mAllowChange && isChecked() != checked) { - mAllowChange = false; - super.setChecked(checked); - setTrackColor(checked); - } else { - // Even if mAllowChange is set to false or the checked value hasn't changed, we still must - // call the super method, since it will make sure the thumb is moved back to the correct edge. - // Without calling the super method, the thumb might stuck in the middle of the switch. - super.setChecked(isChecked()); - } - } - - @Override - public void setBackgroundColor(int color) { - setBackground( - new RippleDrawable( - createRippleDrawableColorStateList(color), new ColorDrawable(color), null)); - } - - void setColor(Drawable drawable, @Nullable Integer color) { - if (color == null) { - drawable.clearColorFilter(); - } else { - drawable.setColorFilter(color, PorterDuff.Mode.MULTIPLY); - } - } - - public void setTrackColor(@Nullable Integer color) { - setColor(super.getTrackDrawable(), color); - } - - public void setThumbColor(@Nullable Integer color) { - setColor(super.getThumbDrawable(), color); - - // Set the ripple color if background is instance of RippleDrawable - if (color != null && super.getBackground() instanceof RippleDrawable) { - ColorStateList customColorState = createRippleDrawableColorStateList(color); - ((RippleDrawable) super.getBackground()).setColor(customColorState); - } - } - - /*package*/ void setOn(boolean on) { - // If the switch has a different value than the value sent by JS, we must change it. - if (isChecked() != on) { - super.setChecked(on); - setTrackColor(on); - } - mAllowChange = true; - } - - public void setTrackColorForTrue(@Nullable Integer color) { - if (color == mTrackColorForTrue) { - return; - } - - mTrackColorForTrue = color; - if (isChecked()) { - setTrackColor(mTrackColorForTrue); - } - } - - public void setTrackColorForFalse(@Nullable Integer color) { - if (color == mTrackColorForFalse) { - return; - } - - mTrackColorForFalse = color; - if (!isChecked()) { - setTrackColor(mTrackColorForFalse); - } - } - - private void setTrackColor(boolean checked) { - if (mTrackColorForTrue != null || mTrackColorForFalse != null) { - // Update the track color to reflect the new value. We only want to do this if these - // props were actually set from JS; otherwise we'll just reset the color to the default. - Integer currentTrackColor = checked ? mTrackColorForTrue : mTrackColorForFalse; - setTrackColor(currentTrackColor); - } - } - - private ColorStateList createRippleDrawableColorStateList(@Nullable Integer color) { - return new ColorStateList( - new int[][] {new int[] {android.R.attr.state_pressed}}, new int[] {color}); - } -} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/switchview/ReactSwitch.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/switchview/ReactSwitch.kt new file mode 100644 index 00000000000..388d471357f --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/switchview/ReactSwitch.kt @@ -0,0 +1,110 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.views.switchview + +import android.content.Context +import android.content.res.ColorStateList +import android.graphics.PorterDuff +import android.graphics.PorterDuffColorFilter +import android.graphics.drawable.ColorDrawable +import android.graphics.drawable.Drawable +import android.graphics.drawable.RippleDrawable +import androidx.appcompat.widget.SwitchCompat + +/** + * Switch that has its value controlled by JS. Whenever the value of the switch changes, we do not + * allow any other changes to that switch until JS sets a value explicitly. This stops the Switch + * from changing its value multiple times, when those changes have not been processed by JS first. + */ +internal class ReactSwitch(context: Context) : SwitchCompat(context) { + + private var allowChange = true + private var trackColorForFalse: Int? = null + private var trackColorForTrue: Int? = null + + override fun setChecked(checked: Boolean) { + if (allowChange && isChecked != checked) { + allowChange = false + super.setChecked(checked) + setTrackColor(checked) + } else { + // Even if mAllowChange is set to false or the checked value hasn't changed, we still must + // call the super method, since it will make sure the thumb is moved back to the correct edge. + // Without calling the super method, the thumb might stuck in the middle of the switch. + super.setChecked(isChecked) + } + } + + override fun setBackgroundColor(color: Int) { + background = + RippleDrawable(createRippleDrawableColorStateList(color), ColorDrawable(color), null) + } + + public fun setColor(drawable: Drawable, color: Int?): Unit { + if (color == null) { + drawable.clearColorFilter() + } else { + drawable.setColorFilter(PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)) + } + } + + public fun setTrackColor(color: Int?): Unit { + setColor(super.getTrackDrawable(), color) + } + + public fun setThumbColor(color: Int?): Unit { + setColor(super.getThumbDrawable(), color) + + // Set the ripple color if background is instance of RippleDrawable + if (color != null && super.getBackground() is RippleDrawable) { + val customColorState = createRippleDrawableColorStateList(color) + (super.getBackground() as RippleDrawable).setColor(customColorState) + } + } + + public fun setOn(on: Boolean): Unit { + // If the switch has a different value than the value sent by JS, we must change it. + if (isChecked != on) { + super.setChecked(on) + setTrackColor(on) + } + allowChange = true + } + + public fun setTrackColorForTrue(color: Int?): Unit { + if (color == trackColorForTrue) { + return + } + trackColorForTrue = color + if (isChecked) { + setTrackColor(trackColorForTrue) + } + } + + public fun setTrackColorForFalse(color: Int?): Unit { + if (color == trackColorForFalse) { + return + } + trackColorForFalse = color + if (!isChecked) { + setTrackColor(trackColorForFalse) + } + } + + private fun setTrackColor(checked: Boolean) { + if (trackColorForTrue != null || trackColorForFalse != null) { + // Update the track color to reflect the new value. We only want to do this if these + // props were actually set from JS; otherwise we'll just reset the color to the default. + val currentTrackColor = if (checked) trackColorForTrue else trackColorForFalse + setTrackColor(currentTrackColor) + } + } + + private fun createRippleDrawableColorStateList(color: Int): ColorStateList = + ColorStateList(arrayOf(intArrayOf(android.R.attr.state_pressed)), intArrayOf(color)) +}