Skip to content

[android] support checkbox tinting#18300

Closed
vonovak wants to merge 8 commits into
react:masterfrom
vonovak:checkboxTinting
Closed

[android] support checkbox tinting#18300
vonovak wants to merge 8 commits into
react:masterfrom
vonovak:checkboxTinting

Conversation

@vonovak

@vonovak vonovak commented Mar 9, 2018

Copy link
Copy Markdown
Contributor

Motivation

RN offers checkbox component on android: https://facebook.github.io/react-native/docs/checkbox.html

The Checkbox colors for checked and unchecked states cannot be controlled from JS at the moment; this PR adds support for that.

The essence of changing colors for the states is this:

ColorStateList cls = new ColorStateList(
        new int[][] {
                new int[] { -android.R.attr.state_checked }, // unchecked
                new int[] {  android.R.attr.state_checked }  // checked
        },
        new int[] {
                uncheckedColor,
                checkedColor
        }
);
checkBox.setSupportButtonTintList(cls);

Because of this, I did it so that both colors have to provided together in an object. This is similar to switch

Test Plan

I have added this to the RN tester.

Related PRs

#11940 Support tintColor and thumbTintColor for Switch on Android

Release Notes

[ANDROID] [FEATURE] [Checkbox] - support custom colors of checked and unchecked states

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Mar 9, 2018
@pull-bot

pull-bot commented Mar 9, 2018

Copy link
Copy Markdown
Warnings
⚠️

📋 Missing Summary - Can you add a Summary? To do so, add a "## Summary" section to your PR description. This is a good place to explain the motivation for making this change.

⚠️

📋 Changelog Format - Did you include a Changelog? A changelog entry has the following format: [CATEGORY] [TYPE] - Message.

Generated by 🚫 dangerJS

@vonovak vonovak changed the title [WIP] support android checkbox tinting support android checkbox tinting Mar 10, 2018

@vonovak vonovak Mar 10, 2018

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is taken from ToolbarAndroid

@vonovak vonovak changed the title support android checkbox tinting [android] support checkbox tinting Mar 13, 2018
@hramos hramos added Android and removed Android labels Mar 13, 2018
@react-native-bot react-native-bot added Feature Request 🌟 Ran Commands One of our bots successfully processed a command. labels Mar 16, 2018
@react-native-bot react-native-bot added Ran Commands One of our bots successfully processed a command. Platform: Android Android applications. labels Mar 18, 2018
@hramos hramos added Type: Enhancement A new feature or enhancement of an existing feature. and removed 🌟Feature Request labels Mar 19, 2018

@vonovak vonovak Mar 28, 2018

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be nice to have only one CompoundButtonCompat.setButtonTintList call instead of two, but I'm afraid it would break the tests (because they are somehow unstable lately), so I'm leaving it as-is for now.

@facebook-github-bot

Copy link
Copy Markdown
Contributor

@vonovak I tried to find reviewers for this pull request and wanted to ping them to take another look. However, based on the blame information for the files in this pull request I couldn't find any reviewers. This sometimes happens when the files in the pull request are new or don't exist on master anymore. Is this pull request still relevant? If yes could you please rebase? In case you know who has context on this code feel free to mention them in a comment (one person is fine). Thanks for reading and hope you will continue contributing to the project.

@vonovak

vonovak commented Apr 9, 2018

Copy link
Copy Markdown
Contributor Author

@janicduplessis you mentioned in #18318 (comment) that you were going to review this PR, may I ask you for the review? Thanks.

@janicduplessis janicduplessis left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we could simplify the logic a bit by moving this to ReactCheckBox.java and saving the colors of the checked / unchecked status as nullable int ivars (null means the theme color). That way we don't have to do to much crazy stuff with the ColorStateList class. We can have a simple updateColorStateList method that reads both of those instance variables to create and set a new ColorStateList. Then we can have two new methods on ReactCheckBox; setCheckedTintColor and setUncheckedTintColor that just update one of the ivar and calls updateColorStateList.

Let me know if that makes sense.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use ColorPropType instead of PropTypes.string

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should call it checkedTintColor instead for consistency with other components (I was looking at Switch). Same for unchecked.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move this to setCheckboxTintList instead of passing it as arguments, seems like we always pass the same values.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we always pass the same values, but in different order:

setCheckboxTintList(..., defaultColorIdOfUncheckedState, defaultColorIdOfCheckedState);
setCheckboxTintList(..., defaultColorIdOfCheckedState, defaultColorIdOfUncheckedState);

I guess I should rename those vars

facebook-github-bot pushed a commit that referenced this pull request Jun 15, 2018
Summary:
The checkbox components inherits from `android.widget.CheckBox`. `AppCompatCheckBox` offers better appearance and support for advanced features (eg. tinting) on older APIs.

~~However, the build fails for some reason; If somebody could shed some light on this, I'd appreciate it.~~ Thanks for the comment, I was being blind and somehow ignored the BUCK file.

I have created a simple app with a checkbox.

Screenshot from android 4.1 (current master):

<img src="https://user-images.githubusercontent.com/1566403/37357997-2d34bdb8-26ea-11e8-8c77-709a4f96c6bf.png" width="300" />

Screenshot after applying the change, also android 4.1:

<img src="https://user-images.githubusercontent.com/1566403/37358016-3c28fb86-26ea-11e8-8dca-3a92e41450c9.png" width="300" />

#18300 (this PR is needed to support tinting on older android api levels)

[ANDROID]  [ENHANCEMENT]  [Checkbox] - Checkbox inherits from AppCompatCheckBox
Closes #18318

Differential Revision: D7268393

Pulled By: hramos

fbshipit-source-id: 01cb2819f4d56c4e0f94cdd1fb5e1a90667a398a
@vonovak

vonovak commented Jun 23, 2018

Copy link
Copy Markdown
Contributor Author

I wonder if we could simplify the logic a bit by moving this to ReactCheckBox.java and saving the colors of the checked / unchecked status as nullable int ivars (null means the theme color).

yes, that would certainly lead to simpler code. The approach I took was using CompoundButtonCompat.getButtonTintList because I wanted to keep a single source of truth - one maintained by the checkbox itself rather than having two more instance variables that would essentially hold a duplicate of what can be obtained via CompoundButtonCompat.getButtonTintList and also eat extra memory (although that probably isn't a huge deal in this case).

@janicduplessis please let me know if I should keep the logic the way it is or rewrite it as you suggested. Thanks.

@vonovak

vonovak commented Sep 21, 2018

Copy link
Copy Markdown
Contributor Author

@janicduplessis can you please answer to my comment above? Thanks.

@vonovak

vonovak commented Jan 15, 2019

Copy link
Copy Markdown
Contributor Author

@janicduplessis could you please answer to my comment above? Thanks :)

@cpojer

cpojer commented Jan 29, 2019

Copy link
Copy Markdown
Contributor

@vonovak Hey! Please go with the suggestion from @janicduplessis to simplify your code a lot, and then we can land this change.

@vonovak

vonovak commented Jan 30, 2019

Copy link
Copy Markdown
Contributor Author

@cpojer thanks for the comment. I have another suggestion: taking a look at the switch, the trackColor prop there accepts an object that contains the colors for the two states.

How about doing it the same way here? That would simplify the code even more, as it would allow to use the ColorStateList and we would not need to add any instance vars. WDYT? Thanks.

@analysis-bot analysis-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code analysis results:

  • eslint found some issues.
  • flow found some issues.

Comment thread Libraries/Components/CheckBox/CheckBox.android.js Outdated
Comment thread Libraries/Components/CheckBox/CheckBox.android.js Outdated
Comment thread RNTester/js/VojtaExample.js Outdated
Comment thread RNTester/js/VojtaExample.js Outdated
Comment thread RNTester/js/VojtaExample.js Outdated

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no-undef: 'getRandomInt' is not defined.

Comment thread RNTester/js/VojtaExample.js Outdated
Comment thread RNTester/js/VojtaExample.js Outdated
Comment thread RNTester/js/VojtaExample.js Outdated
Comment thread RNTester/js/VojtaExample.js Outdated

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cannot get this.state.checked because property checked is missing in undefined [1].

Comment thread RNTester/js/VojtaExample.js Outdated

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cannot call this.setState with object literal bound to partialState because property checked is missing in undefined [1] but exists in object literal [2].

@analysis-bot analysis-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code analysis results:

  • eslint found some issues.

Comment thread Libraries/Components/CheckBox/CheckBox.android.js Outdated
Comment thread Libraries/Components/CheckBox/CheckBox.android.js Outdated
@react react deleted a comment Feb 4, 2019
@cpojer

cpojer commented Feb 6, 2019

Copy link
Copy Markdown
Contributor

@janicduplessis would you care to do a final review of this?

Comment thread Libraries/Components/CheckBox/AndroidCheckBoxNativeComponent.js

@janicduplessis janicduplessis left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, just some comments about the flow types.

Comment thread Libraries/Components/CheckBox/AndroidCheckBoxNativeComponent.js
Comment thread Libraries/Components/CheckBox/CheckBox.android.js

type Props = $ReadOnly<{|
...CommonProps,
tintColors?: {|true?: ColorValue, false?: ColorValue|},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comments about the type

Comment thread Libraries/Components/CheckBox/CheckBox.android.js Outdated
style: [styles.rctCheckBox, style],
};

console.warn('render');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops, thanks, removed

@cpojer cpojer left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, thank you for your work on this!

@facebook-github-bot facebook-github-bot added the Import Started This pull request has been imported. This does not imply the PR has been approved. label Feb 22, 2019

@facebook-github-bot facebook-github-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cpojer is landing this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

@react-native-bot

Copy link
Copy Markdown
Collaborator

@vonovak merged commit 976f4be into facebook:master.

@react react locked as resolved and limited conversation to collaborators Feb 22, 2019
@react-native-bot react-native-bot added the Merged This PR has been merged. label Feb 22, 2019
@hramos hramos removed Import Started This pull request has been imported. This does not imply the PR has been approved. labels Feb 23, 2019
@vonovak
vonovak deleted the checkboxTinting branch May 15, 2019 18:29
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Merged This PR has been merged. Platform: Android Android applications. Ran Commands One of our bots successfully processed a command. Type: Enhancement A new feature or enhancement of an existing feature.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants