Android打造能旋轉能縮放的ImageView(Kotlin版)

引言

嗨,好久不見,大家還好麼?這回我帶來了最新的用kotlin打造的imageview,屬於kotlin練手級別小製作,希望大家喜歡~~
先看效果,然後看源碼,關鍵部分已有註釋。

採用的是3指縮放,2指旋轉。

效果圖

在這裏插入圖片描述
涉及知識點

  • 安卓手勢
  • 矩陣
  • assets目錄
  • 安卓觸摸事件處理
  • 自定義view
  • 一點點的數學運算

kotlin知識點

  • 類的繼承
  • 從構造方法
  • object關鍵字
  • when的使用
  • 如何創建一個對象
  • 懶加載
  • val和var區別
  • 類型轉換

不會的小夥伴還要加油哦!kotlin未來可是安卓開發的主流~

自定義view源碼

class RotateZoomImageView : ImageView {

    private lateinit var mScaleGestureDetector: ScaleGestureDetector
    private var mLastAngle = 0
    private var x = 0
    private var y = 0
    private lateinit var mImageMatrix: Matrix
    val mScaleListener = object: ScaleGestureDetector.SimpleOnScaleGestureListener() {
        override fun onScale(detector: ScaleGestureDetector): Boolean {
            //縮放比例因子
            val scaleFactor = detector.scaleFactor;
            mImageMatrix.postScale(scaleFactor, scaleFactor, x.toFloat(), y.toFloat());
            imageMatrix = mImageMatrix

            return true
        }
    }

    constructor(context: Context): super(context) {
        init(context);
    }

    constructor(context: Context, attributeSet: AttributeSet): super(context, attributeSet) {
        init(context);
    }

    constructor(context: Context, attributeSet: AttributeSet, defStyle: Int): super(context, attributeSet, defStyle) {
        init(context);
    }

    private fun init(context: Context) {
        mScaleGestureDetector = ScaleGestureDetector(context, mScaleListener)
        scaleType = ImageView.ScaleType.MATRIX
        mImageMatrix = Matrix()
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        if (w != oldw || h != oldh) {
            val transX = (w - drawable.intrinsicWidth) / 2.0
            val transY = (h - drawable.intrinsicHeight) / 2.0
            mImageMatrix.setTranslate(transX.toFloat(), transY.toFloat())
            imageMatrix = mImageMatrix
            x = w / 2
            y = h / 2
        }
    }

    private fun doRotationEvent(ev: MotionEvent): Boolean {
        //計算兩個手指的角度
        val dx = ev.getX(0) - ev.getX(1)
        val dy = ev.getY(0) - ev.getY(1)
        //弧度
        val radians = Math.atan(dy.toDouble() / dx.toDouble())
        //角度
        val degrees = (radians*180 / Math.PI).toInt()

        when (ev.actionMasked) {
            MotionEvent.ACTION_DOWN, MotionEvent.ACTION_POINTER_DOWN, MotionEvent.ACTION_POINTER_UP -> mLastAngle = degrees
            MotionEvent.ACTION_MOVE -> {
                when {
                    (degrees - mLastAngle) > 45 -> mImageMatrix.postRotate(-5f, x.toFloat(), y.toFloat())
                    (degrees - mLastAngle) < -45 -> mImageMatrix.postRotate(5f, x.toFloat(), y.toFloat())
                    else -> mImageMatrix.postRotate((degrees - mLastAngle).toFloat(), x.toFloat(), y.toFloat())
                }
                imageMatrix = mImageMatrix
                mLastAngle = degrees
            }
        }

        return true
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        if (event.action == MotionEvent.ACTION_DOWN) {
            return true
        }
        when (event.pointerCount) {
            3 -> return mScaleGestureDetector.onTouchEvent(event)
            2 -> return doRotationEvent(event)
            else -> return super.onTouchEvent(event)
        }
    }
}

Activity源碼

class MainActivity : Activity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val iv = RotateZoomImageView(this)

        val inp = assets.open("android.jpg")
        val image = BitmapFactory.decodeStream(inp)
        iv.setImageBitmap(image)

        setContentView(iv)
    }
}

支持我

您的支持,就是我創作的最大動力

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章