Created
March 16, 2018 17:18
-
-
Save VaibhavLakhera/3e3fc8f82d3e36433fed726362a6c577 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<resources> | |
<declare-styleable name="ShapeTextView"> | |
<!-- Common attributes for all types --> | |
<attr name="shapeType" format="enum"> | |
<enum name="solid" value="0" /> | |
<enum name="gradient" value="1" /> | |
</attr> | |
<attr name="radius" format="dimension" /> | |
<attr name="topLeftRadius" format="dimension" /> | |
<attr name="topRightRadius" format="dimension" /> | |
<attr name="bottomLeftRadius" format="dimension" /> | |
<attr name="bottomRightRadius" format="dimension" /> | |
<attr name="solidBackgroundColor" format="color" /> | |
<attr name="setOvalShape" format="boolean" /> | |
<attr name="setRippleEnabled" format="boolean" /> | |
<attr name="rippleColor" format="color" /> | |
<attr name="strokeWidth" format="dimension" /> | |
<attr name="strokeColor" format="color" /> | |
<!-- Only used when shape type is Gradient --> | |
<attr name="gradientStartColor" format="color" /> | |
<attr name="gradientEndColor" format="color" /> | |
<attr name="gradientOrientation" format="enum"> | |
<enum name="leftToRight" value="0" /> | |
<enum name="topToBottom" value="1" /> | |
<enum name="topLeftToBottomRight" value="2" /> | |
<enum name="topRightToBottomLeft" value="3" /> | |
</attr> | |
</declare-styleable> | |
</resources> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ShapeTextView : AppCompatTextView { | |
companion object { | |
private const val SHAPE_SOLID = 0 | |
private const val SHAPE_GRADIENT = 1 | |
private const val GRADIENT_ORIENTATION_LEFT_TO_RIGHT = 0 | |
private const val GRADIENT_ORIENTATION_TOP_TO_BOTTOM = 1 | |
private const val GRADIENT_ORIENTATION_TOP_LEFT_TO_BOTTOM_RIGHT = 2 | |
private const val GRADIENT_ORIENTATION_TOP_RIGHT_TO_BOTTOM_LEFT = 3 | |
private const val DEFAULT_RIPPLE_COLOR = 0x40000000 | |
} | |
private var shapeType = SHAPE_SOLID | |
private var radius = 0f | |
private var topLeftRadius = 0f | |
private var topRightRadius = 0f | |
private var bottomLeftRadius = 0f | |
private var bottomRightRadius = 0f | |
private var shapeBackgroundColor = 0 | |
private var setOvalShape = false | |
private var setRippleEnabled = false | |
private var rippleColor = DEFAULT_RIPPLE_COLOR | |
private var strokeWidth = 0 | |
private var strokeColor = 0 | |
private var gradientStartColor = 0 | |
private var gradientEndColor = 0 | |
private var gradientOrientation = GRADIENT_ORIENTATION_LEFT_TO_RIGHT | |
private val cornerRadii: FloatArray | |
constructor(context: Context) : this(context, null) | |
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0) | |
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { | |
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.ShapeTextView) | |
// Common attributes for all shapes | |
shapeType = typedArray.getInt(R.styleable.ShapeTextView_shapeType, SHAPE_SOLID) | |
radius = typedArray.getDimensionPixelSize(R.styleable.ShapeTextView_radius, 0).toFloat() | |
if (radius == 0f) { | |
topLeftRadius = typedArray.getDimensionPixelSize(R.styleable.ShapeTextView_topLeftRadius, 0).toFloat() | |
topRightRadius = typedArray.getDimensionPixelSize(R.styleable.ShapeTextView_topRightRadius, 0).toFloat() | |
bottomLeftRadius = typedArray.getDimensionPixelSize(R.styleable.ShapeTextView_bottomLeftRadius, 0).toFloat() | |
bottomRightRadius = typedArray.getDimensionPixelSize(R.styleable.ShapeTextView_bottomRightRadius, 0).toFloat() | |
} | |
shapeBackgroundColor = typedArray.getColor(R.styleable.ShapeTextView_solidBackgroundColor, 0) | |
setOvalShape = typedArray.getBoolean(R.styleable.ShapeTextView_setOvalShape, false) | |
setRippleEnabled = typedArray.getBoolean(R.styleable.ShapeTextView_setRippleEnabled, false) | |
if (setRippleEnabled && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { | |
rippleColor = typedArray.getColor(R.styleable.ShapeTextView_rippleColor, DEFAULT_RIPPLE_COLOR) | |
} | |
strokeWidth = typedArray.getDimensionPixelSize(R.styleable.ShapeTextView_strokeWidth, 0) | |
strokeColor = typedArray.getColor(R.styleable.ShapeTextView_strokeColor, 0) | |
// Only used when shape type is Gradient | |
gradientStartColor = typedArray.getColor(R.styleable.ShapeTextView_gradientStartColor, 0) | |
gradientEndColor = typedArray.getColor(R.styleable.ShapeTextView_gradientEndColor, 0) | |
gradientOrientation = typedArray.getInt(R.styleable.ShapeTextView_gradientOrientation, GRADIENT_ORIENTATION_LEFT_TO_RIGHT) | |
typedArray.recycle() | |
// If radius is non-zero then apply it to all corners otherwise use the individual corner radius | |
cornerRadii = if (radius != 0f) { | |
getCornerRadiiArray(radius, radius, radius, radius) | |
} else { | |
getCornerRadiiArray(topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius) | |
} | |
// Set the background of view according to the shape type | |
when (shapeType) { | |
SHAPE_SOLID -> { | |
background = if (strokeColor != 0 && strokeWidth != 0) { | |
getStrokeShapeDrawable() | |
} else { | |
getShapeDrawable(setOvalShape, cornerRadii, shapeBackgroundColor) | |
} | |
} | |
SHAPE_GRADIENT -> { | |
background = getGradientDrawable() | |
} | |
} | |
// Add the ripple if enabled and os version is above Kitkat | |
if (setRippleEnabled && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { | |
// Mask will have the same shape as the background of the view | |
val mask = getShapeDrawable(setOvalShape, cornerRadii, rippleColor) | |
background = RippleDrawable(ColorStateList.valueOf(rippleColor), background, mask) | |
} | |
} | |
private fun getShapeDrawable(setOvalShape: Boolean, cornerRadii: FloatArray, backgroundColor: Int): ShapeDrawable { | |
val shape = if (setOvalShape) OvalShape() else RoundRectShape(cornerRadii, null, null) | |
val shapeDrawable = ShapeDrawable(shape) | |
shapeDrawable.paint.color = backgroundColor | |
return shapeDrawable | |
} | |
private fun getStrokeShapeDrawable(): GradientDrawable { | |
val drawable = GradientDrawable() | |
drawable.setColor(shapeBackgroundColor) | |
drawable.shape = if (setOvalShape) GradientDrawable.OVAL else GradientDrawable.RECTANGLE | |
drawable.setStroke(strokeWidth, strokeColor) | |
drawable.cornerRadii = cornerRadii | |
return drawable | |
} | |
private fun getGradientDrawable(): GradientDrawable { | |
val gradientOrientation = getGradientOrientation(gradientOrientation) | |
val gradient = GradientDrawable(gradientOrientation, intArrayOf(gradientStartColor, gradientEndColor)) | |
gradient.shape = if (setOvalShape) GradientDrawable.OVAL else GradientDrawable.RECTANGLE | |
gradient.cornerRadii = cornerRadii | |
if (strokeWidth != 0 && strokeColor != 0) { | |
gradient.setStroke(strokeWidth, strokeColor) | |
} | |
return gradient | |
} | |
/** | |
* The corners are ordered top-left, top-right, bottom-right, bottom-left. | |
* For each corner, the array contains 2 values [X_radius, Y_radius] | |
* */ | |
private fun getCornerRadiiArray(topLeftRadius: Float, topRightRadius: Float, bottomLeftRadius: Float, bottomRightRadius: Float): FloatArray { | |
val radii = FloatArray(8) | |
radii[0] = topLeftRadius | |
radii[1] = topLeftRadius | |
radii[2] = topRightRadius | |
radii[3] = topRightRadius | |
radii[4] = bottomRightRadius | |
radii[5] = bottomRightRadius | |
radii[6] = bottomLeftRadius | |
radii[7] = bottomLeftRadius | |
return radii | |
} | |
private fun getGradientOrientation(orientation: Int): GradientDrawable.Orientation { | |
return when (orientation) { | |
GRADIENT_ORIENTATION_LEFT_TO_RIGHT -> GradientDrawable.Orientation.LEFT_RIGHT | |
GRADIENT_ORIENTATION_TOP_TO_BOTTOM -> GradientDrawable.Orientation.TOP_BOTTOM | |
GRADIENT_ORIENTATION_TOP_LEFT_TO_BOTTOM_RIGHT -> GradientDrawable.Orientation.TL_BR | |
GRADIENT_ORIENTATION_TOP_RIGHT_TO_BOTTOM_LEFT -> GradientDrawable.Orientation.TR_BL | |
else -> GradientDrawable.Orientation.LEFT_RIGHT | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment