Android自定義View之愛的魔力轉圈圈


效果

自定義屬性

<?xml version="1.0" encoding="utf-8"?>
<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) {
//        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        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) {
//        super.onDraw(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) {
//        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        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) {
//        super.onDraw(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()
    }
}

佈局文件

<?xml version="1.0" encoding="utf-8"?>
<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>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章