Skip to content

Instantly share code, notes, and snippets.

@luck-alex13
Last active September 2, 2019 05:24
Show Gist options
  • Save luck-alex13/13e04684b7040e6d21e70060a208451a to your computer and use it in GitHub Desktop.
Save luck-alex13/13e04684b7040e6d21e70060a208451a to your computer and use it in GitHub Desktop.
TriangleLabelView for CardView
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="TriangleLabelView">
<attr name="backgroundColor" format="color" />
<attr name="primaryTextColor" format="color" />
<attr name="secondaryTextColor" format="color" />
<attr name="primaryText" format="string" />
<attr name="secondaryText" format="string" />
<attr name="primaryTextSize" format="dimension" />
<attr name="secondaryTextSize" format="dimension" />
<attr name="labelTopPadding" format="dimension" />
<attr name="labelCenterPadding" format="dimension" />
<attr name="labelBottomPadding" format="dimension" />
<attr name="primaryTextStyle">
<enum name="normal" value="0" />
<enum name="italic" value="1" />
<enum name="bold" value="2" />
</attr>
<attr name="secondaryTextStyle">
<enum name="normal" value="0" />
<enum name="italic" value="1" />
<enum name="bold" value="2" />
</attr>
<attr name="corner">
<enum name="leftTop" value="1" />
<enum name="rightTop" value="2" />
<enum name="leftBottom" value="3" />
<enum name="rightBottom" value="4" />
</attr>
</declare-styleable>
</resources>
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.*;
import android.os.Build;
import androidx.annotation.ColorInt;
import androidx.annotation.ColorRes;
import androidx.annotation.StringRes;
import androidx.core.content.ContextCompat;
import android.util.AttributeSet;
import android.view.View;
import ***.R;
public class TriangleLabelView extends View {
private static final String TAG = TriangleLabelView.class.getSimpleName();
private static class PaintHolder {
String text = "";
Paint paint;
int color;
float size;
float height;
float width;
int style;
void initPaint() {
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(color);
paint.setTextAlign(Paint.Align.CENTER);
paint.setTextSize(size);
if (style == 1) {
paint.setTypeface(Typeface.SANS_SERIF);
} else if (style == 2) {
paint.setTypeface(Typeface.DEFAULT_BOLD);
}
}
void resetStatus() {
Rect rectText = new Rect();
paint.getTextBounds(text, 0, text.length(), rectText);
width = rectText.width();
height = rectText.height();
}
}
private PaintHolder primary = new PaintHolder();
private PaintHolder secondary = new PaintHolder();
private float topPadding;
private float bottomPadding;
private float centerPadding;
private Paint trianglePaint;
private int backGroundColor;
private int width;
private int height;
private static final int DEGREES_LEFT = -45;
private static final int DEGREES_RIGHT = 45;
private Corner corner;
public enum Corner {
TOP_LEFT(1),
TOP_RIGHT(2),
BOTTOM_LEFT(3),
BOTTOM_RIGHT(4),
;
private final int type;
Corner(int type) {
this.type = type;
}
private boolean top() {
return this == TOP_LEFT || this == TOP_RIGHT;
}
private boolean left() {
return this == TOP_LEFT || this == BOTTOM_LEFT;
}
private static Corner from(int type) {
for (Corner c : values()) {
if (c.type == type) return c;
}
return Corner.TOP_LEFT;
}
}
public TriangleLabelView(Context context) {
this(context, null);
}
public TriangleLabelView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TriangleLabelView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public TriangleLabelView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.TriangleLabelView);
this.topPadding = ta.getDimension(R.styleable.TriangleLabelView_labelTopPadding, dp2px(7));
this.centerPadding = ta.getDimension(R.styleable.TriangleLabelView_labelCenterPadding, dp2px(3));
this.bottomPadding = ta.getDimension(R.styleable.TriangleLabelView_labelBottomPadding, dp2px(3));
this.backGroundColor = ta.getColor(R.styleable.TriangleLabelView_backgroundColor, Color.parseColor("#66000000"));
this.primary.color = ta.getColor(R.styleable.TriangleLabelView_primaryTextColor, Color.WHITE);
this.secondary.color = ta.getColor(R.styleable.TriangleLabelView_secondaryTextColor, Color.WHITE);
this.primary.size = ta.getDimension(R.styleable.TriangleLabelView_primaryTextSize, sp2px(11));
this.secondary.size = ta.getDimension(R.styleable.TriangleLabelView_secondaryTextSize, sp2px(8));
final String primary = ta.getString(R.styleable.TriangleLabelView_primaryText);
if (primary != null) {
this.primary.text = primary;
}
final String secondary = ta.getString(R.styleable.TriangleLabelView_secondaryText);
if (secondary != null) {
this.secondary.text = secondary;
}
this.primary.style = ta.getInt(R.styleable.TriangleLabelView_primaryTextStyle, 2);
this.secondary.style = ta.getInt(R.styleable.TriangleLabelView_secondaryTextStyle, 0);
this.corner = Corner.from(ta.getInt(R.styleable.TriangleLabelView_corner, 1));
ta.recycle();
this.primary.initPaint();
this.secondary.initPaint();
trianglePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
trianglePaint.setColor(backGroundColor);
this.primary.resetStatus();
this.secondary.resetStatus();
}
public void setLabelTopPadding(float dp) {
topPadding = dp2px(dp);
}
public float getLabelTopPadding() {
return topPadding;
}
public void setLabelCenterPadding(float dp) {
centerPadding = dp2px(dp);
relayout();
}
public float getLabelCenterPadding() {
return centerPadding;
}
public void setLabelBottomPadding(float dp) {
bottomPadding = dp2px(dp);
relayout();
}
public float getLabelBottomPadding() {
return bottomPadding;
}
public void setPrimaryText(String text) {
primary.text = text;
primary.resetStatus();
relayout();
}
public void setPrimaryText(@StringRes int textRes) {
primary.text = getContext().getString(textRes);
primary.resetStatus();
relayout();
}
public String getPrimaryText() {
return primary.text;
}
public void setSecondaryText(String smallText) {
secondary.text = smallText;
secondary.resetStatus();
relayout();
}
public void setSecondaryText(@StringRes int textRes) {
secondary.text = getContext().getString(textRes);
secondary.resetStatus();
relayout();
}
public String getSecondaryText() {
return secondary.text;
}
public void setPrimaryTextColor(@ColorInt int color) {
primary.color = color;
primary.initPaint();
primary.resetStatus();
relayout();
}
public void setPrimaryTextColorResource(@ColorRes int colorResource) {
primary.color = ContextCompat.getColor(getContext(), colorResource);
primary.initPaint();
primary.resetStatus();
relayout();
}
public void setSecondaryTextColor(@ColorInt int color) {
secondary.color = color;
secondary.initPaint();
secondary.resetStatus();
relayout();
}
public void setSecondaryTextColorResource(@ColorRes int colorResource) {
secondary.color = ContextCompat.getColor(getContext(), colorResource);
secondary.initPaint();
secondary.resetStatus();
relayout();
}
public void setPrimaryTextSize(float sp) {
primary.size = sp2px(sp);
relayout();
}
public void setSecondaryTextSize(float sp) {
secondary.size = sp2px(sp);
relayout();
}
public float getPrimaryTextSize() {
return primary.size;
}
public float getSecondaryTextSize() {
return secondary.size;
}
public void setTriangleBackgroundColor(@ColorInt int color) {
backGroundColor = color;
trianglePaint.setColor(backGroundColor);
relayout();
}
public void setTriangleBackgroundColorResource(@ColorRes int colorResource) {
backGroundColor = ContextCompat.getColor(getContext(), colorResource);
trianglePaint.setColor(backGroundColor);
relayout();
}
public int getTriangleBackGroundColor() {
return backGroundColor;
}
public void setCorner(Corner corner) {
this.corner = corner;
relayout();
}
public Corner getCorner() {
return corner;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
// translate
if (corner.top()) {
canvas.translate(0, (float) ((height * Math.sqrt(2)) - height));
}
// rotate
if (corner.top()) {
if (corner.left()) {
canvas.rotate(DEGREES_LEFT, 0, height);
} else {
canvas.rotate(DEGREES_RIGHT, width, height);
}
} else {
if (corner.left()) {
canvas.rotate(DEGREES_RIGHT, 0, 0);
} else {
canvas.rotate(DEGREES_LEFT, width, 0);
}
}
// draw triangle
@SuppressLint("DrawAllocation")
Path path = new Path();
if (corner.top()) {
path.moveTo(0, height);
path.lineTo(width / 2, 0);
path.lineTo(width, height);
} else {
path.moveTo(0, 0);
path.lineTo(width / 2, height);
path.lineTo(width, 0);
}
path.close();
canvas.drawPath(path, trianglePaint);
// draw secondaryText
if (corner.top()) {
canvas.drawText(secondary.text, (width) / 2, topPadding + secondary.height, secondary.paint);
canvas.drawText(primary.text, (width) / 2, (topPadding + secondary.height + centerPadding + primary.height), primary.paint);
} else {
canvas.drawText(secondary.text, (width) / 2, bottomPadding + secondary.height + centerPadding + primary.height, secondary.paint);
canvas.drawText(primary.text, (width) / 2, (bottomPadding + primary.height), primary.paint);
}
canvas.restore();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
height = (int) (topPadding + centerPadding + bottomPadding + secondary.height + primary.height);
width = 2 * height;
int realHeight = (int) (height * Math.sqrt(2));
setMeasuredDimension(width, realHeight);
}
public int dp2px(float dpValue) {
final float scale = getContext().getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
public float sp2px(float spValue) {
final float scale = getContext().getResources().getDisplayMetrics().scaledDensity;
return spValue * scale;
}
/**
* Should be called whenever what we're displaying could have changed.
*/
private void relayout() {
invalidate();
requestLayout();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment