Skip to content

Instantly share code, notes, and snippets.

@nosix
Created July 17, 2016 05:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nosix/d2c27439c231954dbb3033cd26a92ccf to your computer and use it in GitHub Desktop.
Save nosix/d2c27439c231954dbb3033cd26a92ccf to your computer and use it in GitHub Desktop.
Custom View for Android (SDK 22) in Kotlin 1.0.2
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="Themes">
<attr name="circleMeterStyle" format="reference"/>
</declare-styleable>
<declare-styleable name="CircleMeter">
<attr name="size" format="dimension" />
<attr name="centerCircle" format="float" />
</declare-styleable>
</resources>
package xxx.view
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.View
import xxx.R
class CircleMeter(context: Context, attrs: AttributeSet?, defStyleAttr: Int) :
View(context, attrs, defStyleAttr) {
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, R.attr.circleMeterStyle)
constructor(context: Context) : this(context, null)
companion object {
private val DEFAULT_SIZE = 64f
private val DEFAULT_CENTER_CIRCLE = 0.2f
}
private val paint = Paint()
private val paintForArc = Paint()
private val paintForCenterCircle = Paint()
var size: Float = DEFAULT_SIZE
var centerCircle: Float = DEFAULT_CENTER_CIRCLE // 0.0f..1.0f
var range: IntRange = 0..100
var value: Int = 100
init {
context.obtainStyledAttributes(attrs, R.styleable.CircleMeter, defStyleAttr, 0).let {
size = it.getDimension(R.styleable.CircleMeter_size, DEFAULT_SIZE)
centerCircle = it.getFloat(R.styleable.CircleMeter_centerCircle, DEFAULT_CENTER_CIRCLE)
it.recycle()
}
paintForArc.let {
it.color = context.resources.getColor(R.color.colorAccent)
}
paintForCenterCircle.let {
it.color = Color.TRANSPARENT
it.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)
}
setLayerType(LAYER_TYPE_SOFTWARE, null) // Not painted black.
}
private val degreeOfArc: Float
get() = 360f * (value - range.first) / (range.last - range.first)
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
val widthMode = MeasureSpec.getMode(widthMeasureSpec)
val widthSize = MeasureSpec.getSize(widthMeasureSpec)
val heightMode = MeasureSpec.getMode(heightMeasureSpec)
val heightSize = MeasureSpec.getSize(heightMeasureSpec)
val width = when (widthMode) {
MeasureSpec.AT_MOST -> Math.min(widthSize, size.toInt())
MeasureSpec.UNSPECIFIED -> size.toInt()
MeasureSpec.EXACTLY -> widthSize
else -> throw AssertionError()
}
val height = when (heightMode) {
MeasureSpec.AT_MOST -> Math.min(heightSize, size.toInt())
MeasureSpec.UNSPECIFIED -> size.toInt()
MeasureSpec.EXACTLY -> heightSize
else -> throw AssertionError()
}
val size = Math.min(width, height)
setMeasuredDimension(size, size)
}
override fun onDraw(canvas: Canvas) {
/* if LayerType == LAYER_TYPE_HARDWARE then
val bitmap = Bitmap.createBitmap(canvas.width, canvas.height, Bitmap.Config.ARGB_8888)
Canvas(bitmap).let {
it.drawArc(0f, 0f, width.toFloat(), height.toFloat(), -90f, degreeOfArc, true, paintForArc)
it.drawCircle(width.toFloat()/2, height.toFloat()/2, height.toFloat()/2*centerCircle, paintForCenterCircle)
canvas.drawBitmap(bitmap, 0f, 0f, paint)
}
*/
canvas.drawArc(0f, 0f, width.toFloat(), height.toFloat(), -90f, degreeOfArc, true, paintForArc)
canvas.drawCircle(width.toFloat()/2, height.toFloat()/2, height.toFloat()/2*centerCircle, paintForCenterCircle)
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<xxx.CircleMeter
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:size="24dp"
app:centerCircle="0.2" />
</LinearLayout>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment