-
Notifications
You must be signed in to change notification settings - Fork 6.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support tint list on GifDrawable. #5341
base: master
Are you sure you want to change the base?
Conversation
The Java doc of `Drawable#setColorFilter(ColorFilter)` says that "non-null color filter disables tint.". https://developer.android.com/reference/android/graphics/drawable/Drawable#setColorFilter(android.graphics.ColorFilter) This change sets the tint color filter by `draw()` to align with the document. This behavior is the same as the `ColorDrawable`.
@@ -298,7 +315,47 @@ public void setAlpha(int i) { | |||
|
|||
@Override | |||
public void setColorFilter(ColorFilter colorFilter) { | |||
getPaint().setColorFilter(colorFilter); | |||
if (getColorFilter() != colorFilter) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why use reference equality instead of Objects.equals?
and why does this specific method check for equality but the other methods not? I guess this is trying to handle the case where colorFilter is null to prevent it from clearing the tint? If that's the case please can you make the code explicit (preferred) or add a comment to say it is, because otherwise it's not at all obvious from the code that this is the intent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added the check because GradientDrawable does the same thing.
However, I think it is not directly related to this PR, so please let me revert this change to simplify this PR.
@@ -66,6 +70,9 @@ public class GifDrawable extends Drawable | |||
|
|||
private boolean applyGravity; | |||
private Paint paint; | |||
private ColorStateList tint; | |||
private PorterDuff.Mode tintMode; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Default tintMode is documented as SRC_IN
The Android Drawable implementations also imply that this should not be settable to null but null should set back to the default (this behavior is not documented and is not marked as nullable, but the base Drawable compat implementation treats null as default values)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
null should set back to the default
You are right. I updated this PR to use the default mode if null.
The Android Drawable implementations also imply that this should not be settable to null
FYI, Drawable#setTintMode() accept null.
https://cs.android.com/android/platform/superproject/+/master:frameworks/base/graphics/java/android/graphics/drawable/Drawable.java;l=692?q=drawable.java
|
||
// draw() temporary sets tint filter then restore. | ||
verify(paint).setColorFilter(eq(new PorterDuffColorFilter(Color.GREEN, Mode.ADD))); | ||
verify(paint).setColorFilter(null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this test is not testing drawable behavior but internal implementation details of the draw method, what we care about is that the bitmap was drawn with a paint configured with the tint filter, not that paint was interacted with.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for pointing it out!
Previously I followed the test code of setColorFilter()
.
Now, I updated the test code of both setColorFilter()
and setTintList()
to check the Paint object which is used by Canvas#drawBitmap()
.
PTAL?
(Ideally it's better to check the drawn bitmap colors, but we cannot do it on Robolectric tests. Instrumentation tests may work, but I think the current Robolectric test is enough.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note:
I updated the behavior of GifDrawable#draw() to make it test-friendly.
We had the following code inside GifDrawable#draw().
// Temporary set a tint filter then restore.
paint.setColorFilter(tintFilter);
canvas.drawBitmap(currentFrame, null, getDestRect(), paint);
paint.setColorFilter(colorFilter);
With this code, we cannot verify whether canvas#drawBitmap()
uses the tintFilter
or not with ArgumentCaptor, because paint.setColorFilter(colorFilter)
is called before ArgumentCaptor#capture()
. The new code doesn't call paint.setColorFilter(colorFilter)
to avoid the issue.
verify(paint).setColorFilter(null); | ||
|
||
assertThat(drawable.setState(new int[] {android.R.attr.state_pressed})).isTrue(); | ||
drawable.draw(new Canvas()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
performing multiple acts in a test implies that there should be two tests, please split this into a separate test that verifies the state is reflected in the filter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
66a32ed
to
6d23472
Compare
Description
This PR implements
GifDrawable#setTintList()
andGifDrawable#setTintMode()
to support tint list (e.g. android:tint).Motivation and Context
Our Android app uses a tint list to change the drawable colors, but GifDrawable doesn't support tint thus it doesn't work well.