Fix incorrect gradient rotation.

This commit is contained in:
Alex Hart 2021-09-28 16:51:23 -03:00 committed by Cody Henthorne
parent 83b9fbac11
commit f3d0b4a671
3 changed files with 20 additions and 29 deletions

View file

@ -8,6 +8,7 @@ import android.graphics.PixelFormat;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.Shader; import android.graphics.Shader;
import android.graphics.Xfermode;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@ -100,8 +101,8 @@ public final class RotatableGradientDrawable extends Drawable {
fillPaint.setShader(new LinearGradient(fillRect.left, fillRect.top, fillRect.right, fillRect.bottom, colors, positions, Shader.TileMode.CLAMP)); fillPaint.setShader(new LinearGradient(fillRect.left, fillRect.top, fillRect.right, fillRect.bottom, colors, positions, Shader.TileMode.CLAMP));
} }
public @Nullable Shader getShader() { public void setXfermode(@NonNull Xfermode xfermode) {
return fillPaint.getShader(); fillPaint.setXfermode(xfermode);
} }
private static Point cornerPrime(@NonNull Point origin, @NonNull Point corner, float degrees) { private static Point cornerPrime(@NonNull Point origin, @NonNull Point corner, float degrees) {

View file

@ -5,7 +5,6 @@ import android.graphics.ColorFilter
import android.graphics.Path import android.graphics.Path
import android.graphics.PorterDuff import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter import android.graphics.PorterDuffColorFilter
import android.graphics.Shader
import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.graphics.drawable.ShapeDrawable import android.graphics.drawable.ShapeDrawable
@ -32,6 +31,8 @@ class ChatColors private constructor(
private val singleColor: Int? private val singleColor: Int?
) { ) {
fun isGradient(): Boolean = Build.VERSION.SDK_INT >= 21 && linearGradient != null
/** /**
* Returns the Drawable to render the linear gradient, or null if this ChatColors is a single color. * Returns the Drawable to render the linear gradient, or null if this ChatColors is a single color.
*/ */
@ -54,18 +55,6 @@ class ChatColors private constructor(
} }
} }
fun asShader(left: Int, top: Int, right: Int, bottom: Int): Shader? {
return linearGradient?.let {
RotatableGradientDrawable(
linearGradient.degrees,
linearGradient.colors,
linearGradient.positions
).apply {
setBounds(left, top, right, bottom)
}
}?.shader
}
/** /**
* Returns the ColorFilter to apply to a conversation bubble or other relevant piece of UI. * Returns the ColorFilter to apply to a conversation bubble or other relevant piece of UI.
*/ */

View file

@ -10,6 +10,7 @@ import android.view.View
import android.widget.EdgeEffect import android.widget.EdgeEffect
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import org.thoughtcrime.securesms.components.RotatableGradientDrawable
/** /**
* Draws the ChatColors color or gradient following this procedure: * Draws the ChatColors color or gradient following this procedure:
@ -77,7 +78,6 @@ class RecyclerViewColorizer(private val recyclerView: RecyclerView) {
color = Color.BLACK color = Color.BLACK
} }
private val shaderPaint = Paint()
private val colorPaint = Paint() private val colorPaint = Paint()
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) { override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
@ -107,26 +107,27 @@ class RecyclerViewColorizer(private val recyclerView: RecyclerView) {
private fun drawShaderMask(canvas: Canvas, parent: RecyclerView, chatColors: ChatColors) { private fun drawShaderMask(canvas: Canvas, parent: RecyclerView, chatColors: ChatColors) {
if (useLayer) { if (useLayer) {
shaderPaint.xfermode = layerXfermode
colorPaint.xfermode = layerXfermode colorPaint.xfermode = layerXfermode
} else { } else {
shaderPaint.xfermode = noLayerXfermode
colorPaint.xfermode = noLayerXfermode colorPaint.xfermode = noLayerXfermode
} }
val shader = chatColors.asShader(0, 0, parent.width, parent.height) if (chatColors.isGradient()) {
shaderPaint.shader = shader val mask = chatColors.chatBubbleMask as RotatableGradientDrawable
colorPaint.color = chatColors.asSingleColor() mask.setXfermode(colorPaint.xfermode)
mask.setBounds(0, 0, parent.width, parent.height)
mask.draw(canvas)
} else {
canvas.drawRect( canvas.drawRect(
0f, 0f,
0f, 0f,
parent.width.toFloat(), parent.width.toFloat(),
parent.height.toFloat(), parent.height.toFloat(),
if (shader == null) colorPaint else shaderPaint colorPaint
) )
} }
} }
}
init { init {
recyclerView.edgeEffectFactory = edgeEffectFactory recyclerView.edgeEffectFactory = edgeEffectFactory