自定义属性
<resources>
<declare-styleable name="MyTurnAroundView">
<attr name="my_offset" format="dimension" />
<attr name="color" format="color" />
<attr name="my_rect_width" format="dimension" />
<attr name="my_rect_height" format="dimension" />
<attr name="draw_num" format="integer" />
declare-styleable>
resources>
测量
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
var widthMeasureMode = MeasureSpec.getMode(widthMeasureSpec)
var widthMeasureSize = MeasureSpec.getSize(widthMeasureSpec)
var heightMeasureMode = MeasureSpec.getMode(heightMeasureSpec)
var heightMeasureSize = MeasureSpec.getSize(heightMeasureSpec)
if (widthMeasureMode == MeasureSpec.AT_MOST) {
widthMeasureSize = dp2px(100)
}
if (heightMeasureMode == MeasureSpec.AT_MOST) {
heightMeasureSize = dp2px(100)
}
setMeasuredDimension(
MeasureSpec.makeMeasureSpec(widthMeasureSize, widthMeasureMode),
MeasureSpec.makeMeasureSpec(heightMeasureSize, heightMeasureMode)
)
}
绘制
override fun onDraw(canvas: Canvas) {
var xCenter = mWidth / 2
var yCenter = mHeight / 2
var num = 360 / mDrawNum
for (i in 0..mDrawNum) {
canvas.rotate(num.toFloat(), xCenter.toFloat(), yCenter.toFloat())
var path = Path()
path.moveTo(xCenter.toFloat(), 0f)
path.lineTo(xCenter.toFloat() - mOffset, mRectHeight.toFloat())
path.lineTo(xCenter.toFloat() - mOffset + mRectWidth, mRectHeight.toFloat())
path.lineTo(xCenter.toFloat() + mRectWidth, 0f)
canvas.drawPath(path, mPaint)
canvas.drawPath(path, mPaint)
}
startAnim()
}
完整代码
class MyTurnAroundView(context: Context, attrs: AttributeSet?) : View(context, attrs) {
private var mWidth = 0
private var mHeight = 0
private var mOffset = 0
private var mRectHeight = dp2px(10)
private var mRectWidth = dp2px(10)
private var mDrawNum = 20
private var mColor = Color.RED
private var mPaint: Paint = Paint()
private var mRotationAnim: ObjectAnimator? = null
private var isAnim = false;
init {
val styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.MyTurnAroundView)
mOffset = styledAttrs.getDimension(styledAttrs.getIndex(R.styleable.MyTurnAroundView_my_offset), 0f).toInt()
mRectHeight = styledAttrs.getDimension(styledAttrs.getIndex(R.styleable.MyTurnAroundView_my_rect_height), 10f).toInt()
mRectWidth = styledAttrs.getDimension(styledAttrs.getIndex(R.styleable.MyTurnAroundView_my_rect_width), 10f).toInt()
mDrawNum = styledAttrs.getInt(styledAttrs.getIndex(R.styleable.MyTurnAroundView_draw_num), 20)
mColor = styledAttrs.getColor(styledAttrs.getIndex(R.styleable.MyTurnAroundView_color), Color.RED)
styledAttrs.recycle()
mPaint.setColor(mColor)
mPaint.isAntiAlias = true
mPaint.isDither = true
mPaint.style = Paint.Style.FILL
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
mWidth = measuredWidth
mHeight = measuredHeight
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
var widthMeasureMode = MeasureSpec.getMode(widthMeasureSpec)
var widthMeasureSize = MeasureSpec.getSize(widthMeasureSpec)
var heightMeasureMode = MeasureSpec.getMode(heightMeasureSpec)
var heightMeasureSize = MeasureSpec.getSize(heightMeasureSpec)
if (widthMeasureMode == MeasureSpec.AT_MOST) {
widthMeasureSize = dp2px(100)
}
if (heightMeasureMode == MeasureSpec.AT_MOST) {
heightMeasureSize = dp2px(100)
}
setMeasuredDimension(
MeasureSpec.makeMeasureSpec(widthMeasureSize, widthMeasureMode),
MeasureSpec.makeMeasureSpec(heightMeasureSize, heightMeasureMode)
)
}
override fun onDraw(canvas: Canvas) {
var xCenter = mWidth / 2
var yCenter = mHeight / 2
var num = 360 / mDrawNum
for (i in 0..mDrawNum) {
canvas.rotate(num.toFloat(), xCenter.toFloat(), yCenter.toFloat())
var path = Path()
path.moveTo(xCenter.toFloat(), 0f)
path.lineTo(xCenter.toFloat() - mOffset, mRectHeight.toFloat())
path.lineTo(xCenter.toFloat() - mOffset + mRectWidth, mRectHeight.toFloat())
path.lineTo(xCenter.toFloat() + mRectWidth, 0f)
canvas.drawPath(path, mPaint)
canvas.drawPath(path, mPaint)
}
startAnim()
}
fun dp2px(dp: Int): Int = (Resources.getSystem().displayMetrics.density * dp + 0.5).toInt()
fun startAnim() {
if (isAnim) return
isAnim = true
mRotationAnim = ObjectAnimator.ofFloat(this, "Rotation", -360f)
.setDuration(4000)
mRotationAnim!!.setRepeatCount(-1)
mRotationAnim!!.setInterpolator(LinearInterpolator())
mRotationAnim!!.start()
}
fun stopAnim() {
isAnim = false
mRotationAnim?.cancel()
}
}
布局文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.turnaroundtest.MyTurnAroundView
android:id="@+id/around1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:color="#ff0000"
app:draw_num="20"
app:my_offset="0dp"
app:my_rect_height="10dp"
app:my_rect_width="10dp"
android:layout_margin="10dp" />
<com.example.turnaroundtest.MyTurnAroundView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_toRightOf="@id/around1"
app:color="@android:color/darker_gray"
app:draw_num="18"
app:my_offset="5dp"
app:my_rect_height="10dp"
app:my_rect_width="10dp" />
<com.example.turnaroundtest.MyTurnAroundView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_below="@id/around1"
app:color="#00ff00"
app:draw_num="18"
app:my_offset="5dp"
app:my_rect_height="20dp"
app:my_rect_width="10dp" />
<com.example.turnaroundtest.MyTurnAroundView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_below="@id/around1"
android:layout_toRightOf="@id/around1"
app:color="#0000ff"
app:draw_num="10"
app:my_offset="-5dp"
app:my_rect_height="18dp"
app:my_rect_width="10dp" />
RelativeLayout>