package com.marshalchen.common.uimodule.shapeimageview.shader; import android.annotation.SuppressLint; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.util.AttributeSet; import com.marshalchen.common.uimodule.R; public class BubbleShader extends ShaderHelper { private static final int DEFAULT_HEIGHT_DP = 10; private enum ArrowPosition { @SuppressLint("RtlHardcoded") LEFT, RIGHT } private final Path path = new Path(); private int triangleHeightPx; private ArrowPosition arrowPosition = ArrowPosition.LEFT; public BubbleShader() { } @Override public void init(Context context, AttributeSet attrs, int defStyle) { super.init(context, attrs, defStyle); borderWidth = 0; if(attrs != null){ TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ShaderImageView, defStyle, 0); triangleHeightPx = typedArray.getDimensionPixelSize(R.styleable.ShaderImageView_triangleHeight, 0); int arrowPositionInt = typedArray.getInt(R.styleable.ShaderImageView_arrowPosition, ArrowPosition.LEFT.ordinal()); arrowPosition = ArrowPosition.values()[arrowPositionInt]; typedArray.recycle(); } if(triangleHeightPx == 0) { triangleHeightPx = dpToPx(context.getResources().getDisplayMetrics(), DEFAULT_HEIGHT_DP); } } @Override public void draw(Canvas canvas, Paint imagePaint, Paint borderPaint) { canvas.save(); canvas.concat(matrix); canvas.drawPath(path, imagePaint); canvas.restore(); } @Override public void calculate(int bitmapWidth, int bitmapHeight, float width, float height, float scale, float translateX, float translateY) { path.reset(); float x = -translateX; float y = -translateY; float scaledTriangleHeight = triangleHeightPx / scale; float resultWidth = bitmapWidth + 2 * translateX; float resultHeight = bitmapHeight + 2 * translateY; float centerY = resultHeight / 2f + y; path.setFillType(Path.FillType.EVEN_ODD); float rectLeft; float rectRight; switch (arrowPosition) { case LEFT: rectLeft = scaledTriangleHeight + x; rectRight = resultWidth + rectLeft; path.addRect(rectLeft, y, rectRight, resultHeight + y, Path.Direction.CW); path.moveTo(x, centerY); path.lineTo(rectLeft, centerY - scaledTriangleHeight); path.lineTo(rectLeft, centerY + scaledTriangleHeight); path.lineTo(x, centerY); break; case RIGHT: rectLeft = x; float imgRight = resultWidth + rectLeft; rectRight = imgRight - scaledTriangleHeight; path.addRect(rectLeft, y, rectRight, resultHeight + y, Path.Direction.CW); path.moveTo(imgRight, centerY); path.lineTo(rectRight, centerY - scaledTriangleHeight); path.lineTo(rectRight, centerY + scaledTriangleHeight); path.lineTo(imgRight, centerY); break; } } @Override public void reset() { path.reset(); } }