mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Fix ReactSwitch for non RippleDrawable backgrounds (#32468)
Summary:
ReactSwitch component is crashing on Android when it is initialised with both a backgroundColor and thumbColor, `style={{ backgroundColor: "anyColor" }} thumbColor="anyColor"`, due to IllegalCastException.
When setting a background color, BaseViewManagerDelegate is calling `setBackgroundColor` which replaces the background drawable with a ColorDrawale, hence [this line](https://github.com/facebook/react-native/blob/72ea0e111fccd99456abf3f974439432145585e3/ReactAndroid/src/main/java/com/facebook/react/views/switchview/ReactSwitch.java#L68) fails.
Instead, given the ripple effect needs to be preserved, one should initialise a RippleDrawable using the current background drawable and set it as the background of the switch.
Given the RippleDrawable should be preserved, overriding the `setBackgroundColor` seemed the sensible thing to do.
## Changelog
[Android] [Fixed] - Fix crash when a Switch is initialised with both backgroundColor and thumbColor.
Pull Request resolved: https://github.com/facebook/react-native/pull/32468
Test Plan:
### Setup:
Initialise an empty React Native project. Add a switch component:
`<Switch
style={{backgroundColor: 'red'}}
thumbColor={'https://github.com/facebook/react-native/issues/356'}
/>`
Run the project `yarn android`
### Current state (RN 65+):
Red screen will show highlighting an IllegalCastException.
<img src="https://user-images.githubusercontent.com/4354327/138616661-3ba1370c-6a2b-48c2-ba70-b99415a4256f.png" width="200"/>
### With fix:
- The component is expected to have a red background.
- When pressed a ripple effect shows inside the backgrounds bounding box.
- Business as usual otherwise.
`backgroundColor` with `thumbColor`:

Just `thumbColor`:

Reviewed By: ShikaSD
Differential Revision: D31895690
Pulled By: cortinico
fbshipit-source-id: 60af16de7db61440ccfbf11d67a3d945dd90b562
This commit is contained in:
committed by
Facebook GitHub Bot
parent
f58c496e07
commit
456cf3db14
@@ -10,6 +10,7 @@ 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 android.os.Build;
|
||||
@@ -48,6 +49,18 @@ import androidx.appcompat.widget.SwitchCompat;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundColor(int color) {
|
||||
// Ensure RippleDrawable is preserved for >=21
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
setBackground(
|
||||
new RippleDrawable(
|
||||
createRippleDrawableColorStateList(color), new ColorDrawable(color), null));
|
||||
} else {
|
||||
super.setBackgroundColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
void setColor(Drawable drawable, @Nullable Integer color) {
|
||||
if (color == null) {
|
||||
drawable.clearColorFilter();
|
||||
@@ -63,14 +76,10 @@ import androidx.appcompat.widget.SwitchCompat;
|
||||
public void setThumbColor(@Nullable Integer color) {
|
||||
setColor(super.getThumbDrawable(), color);
|
||||
|
||||
// Set the ripple color with thumb color if >= LOLLIPOP
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
RippleDrawable ripple = (RippleDrawable) super.getBackground();
|
||||
ColorStateList customColorState =
|
||||
new ColorStateList(
|
||||
new int[][] {new int[] {android.R.attr.state_pressed}}, new int[] {color});
|
||||
|
||||
ripple.setColor(customColorState);
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,4 +122,9 @@ import androidx.appcompat.widget.SwitchCompat;
|
||||
setTrackColor(currentTrackColor);
|
||||
}
|
||||
}
|
||||
|
||||
private ColorStateList createRippleDrawableColorStateList(@Nullable Integer color) {
|
||||
return new ColorStateList(
|
||||
new int[][] {new int[] {android.R.attr.state_pressed}}, new int[] {color});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user