From 5b953e51fab6ed9ebc5987437689c1078298db86 Mon Sep 17 00:00:00 2001 From: Guilherme Iscaro Date: Tue, 23 Jul 2019 23:35:11 -0700 Subject: [PATCH] Revert Picker item original color (#25750) Summary: Since the Android's Picker implementation uses an ArrayAdapter, it means that the views that were created may be reused for other items in order to save memory. With this in mind, if one sets the Picker.Item prop color for only certain items there might be an state that some items that does not have the color set will end up appearing with the wrong color. This happens because, this new item is reusing a view of an item that had the color prop set. In order to avoid this problem, once a new view is created the ReactPickerAdapter will save the original color and re-apply if the item does not have the color prop. ## Changelog [Android] [Fixed] - Picker.Item displays wrong colors Pull Request resolved: https://github.com/facebook/react-native/pull/25750 Test Plan: On android execute the code below. Only the FIRST item should be red. ```javascript import React from 'react'; import { StyleSheet, View, Picker } from 'react-native'; const values = new Array(100); for (let i = 0; i < values.length; i += 1) { values[i] = (i * i).toString(); } const App = () => { const [selected, setSelected] = React.useState(0); const onValueChange = React.useCallback((_, idx) => { setSelected(idx); }, []); return ( {values.map((v, i) => ( ))} ); }; export default App; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', paddingHorizontal: 20, }, }); ``` ### Without the patch You should see various items with the red color (when only the first one should be red) ![picker-not-working](https://user-images.githubusercontent.com/984610/61584012-fe902300-ab16-11e9-8131-62c471b7f753.gif) ### With the patch Only the first item is red. ![picker-working](https://user-images.githubusercontent.com/984610/61584013-09e34e80-ab17-11e9-9ae0-95a513581779.gif) Closes https://github.com/facebook/react-native/issues/25456 Differential Revision: D16430961 Pulled By: mdvacca fbshipit-source-id: 48b41845d465df2e3dd34fc4a76950ddc75a010a --- .../react/views/picker/ReactPickerAdapter.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactPickerAdapter.java b/ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactPickerAdapter.java index 16e502f58d..f811178c5d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactPickerAdapter.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactPickerAdapter.java @@ -1,6 +1,7 @@ package com.facebook.react.views.picker; import android.content.Context; +import android.content.res.ColorStateList; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -36,12 +37,16 @@ class ReactPickerAdapter extends ArrayAdapter { private View getView(int position, View convertView, ViewGroup parent, boolean isDropdown) { ReactPickerItem item = getItem(position); + boolean isNew = false; if (convertView == null) { int layoutResId = isDropdown ? android.R.layout.simple_spinner_dropdown_item : android.R.layout.simple_spinner_item; convertView = mInflater.inflate(layoutResId, parent, false); + // Save original text colors + convertView.setTag(((TextView) convertView).getTextColors()); + isNew = true; } TextView textView = (TextView) convertView; @@ -50,9 +55,12 @@ class ReactPickerAdapter extends ArrayAdapter { textView.setTextColor(mPrimaryTextColor); } else if (item.color != null) { textView.setTextColor(item.color); + } else if (textView.getTag() != null && !isNew) { + // In case the new item does not set the color prop, go back to the default one + textView.setTextColor((ColorStateList) textView.getTag()); } - return convertView; + return textView; } public @Nullable Integer getPrimaryTextColor() {