[android] Android Image View Pinch Zooming

Custom zoom view in Kotlin

 import android.content.Context
 import android.graphics.Matrix
 import android.graphics.PointF
 import android.util.AttributeSet
 import android.util.Log
 import android.view.MotionEvent
 import android.view.ScaleGestureDetector
 import android.view.ScaleGestureDetector.SimpleOnScaleGestureListener
 import androidx.appcompat.widget.AppCompatImageView

 class ZoomImageview : AppCompatImageView {
var matri: Matrix? = null
var mode = NONE

// Remember some things for zooming
var last = PointF()
var start = PointF()
var minScale = 1f
var maxScale = 3f
lateinit var m: FloatArray
var viewWidth = 0
var viewHeight = 0
var saveScale = 1f
protected var origWidth = 0f
protected var origHeight = 0f
var oldMeasuredWidth = 0
var oldMeasuredHeight = 0
var mScaleDetector: ScaleGestureDetector? = null
var contex: Context? = null

constructor(context: Context) : super(context) {
    sharedConstructing(context)
}

constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
    sharedConstructing(context)
}

private fun sharedConstructing(context: Context) {
    super.setClickable(true)
    this.contex= context
    mScaleDetector = ScaleGestureDetector(context, ScaleListener())
    matri = Matrix()
    m = FloatArray(9)
    imageMatrix = matri
    scaleType = ScaleType.MATRIX
    setOnTouchListener { v, event ->
        mScaleDetector!!.onTouchEvent(event)
        val curr = PointF(event.x, event.y)
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                last.set(curr)
                start.set(last)
                mode = DRAG
            }
            MotionEvent.ACTION_MOVE -> if (mode == DRAG) {
                val deltaX = curr.x - last.x
                val deltaY = curr.y - last.y
                val fixTransX = getFixDragTrans(deltaX, viewWidth.toFloat(), origWidth * saveScale)
                val fixTransY = getFixDragTrans(deltaY, viewHeight.toFloat(), origHeight * saveScale)
                matri!!.postTranslate(fixTransX, fixTransY)
                fixTrans()
                last[curr.x] = curr.y
            }
            MotionEvent.ACTION_UP -> {
                mode = NONE
                val xDiff = Math.abs(curr.x - start.x).toInt()
                val yDiff = Math.abs(curr.y - start.y).toInt()
                if (xDiff < CLICK && yDiff < CLICK) performClick()
            }
            MotionEvent.ACTION_POINTER_UP -> mode = NONE
        }
        imageMatrix = matri
        invalidate()
        true // indicate event was handled
    }
}

fun setMaxZoom(x: Float) {
    maxScale = x
}

private inner class ScaleListener : SimpleOnScaleGestureListener() {
    override fun onScaleBegin(detector: ScaleGestureDetector): Boolean {
        mode = ZOOM
        return true
    }

    override fun onScale(detector: ScaleGestureDetector): Boolean {
        var mScaleFactor = detector.scaleFactor
        val origScale = saveScale
        saveScale *= mScaleFactor
        if (saveScale > maxScale) {
            saveScale = maxScale
            mScaleFactor = maxScale / origScale
        } else if (saveScale < minScale) {
            saveScale = minScale
            mScaleFactor = minScale / origScale
        }
        if (origWidth * saveScale <= viewWidth || origHeight * saveScale <= viewHeight) matri!!.postScale(mScaleFactor, mScaleFactor, viewWidth / 2.toFloat(), viewHeight / 2.toFloat()) else matri!!.postScale(mScaleFactor, mScaleFactor, detector.focusX, detector.focusY)
        fixTrans()
        return true
    }
}

fun fixTrans() {
    matri!!.getValues(m)
    val transX = m[Matrix.MTRANS_X]
    val transY = m[Matrix.MTRANS_Y]
    val fixTransX = getFixTrans(transX, viewWidth.toFloat(), origWidth * saveScale)
    val fixTransY = getFixTrans(transY, viewHeight.toFloat(), origHeight * saveScale)
    if (fixTransX != 0f || fixTransY != 0f) matri!!.postTranslate(fixTransX, fixTransY)
}

fun getFixTrans(trans: Float, viewSize: Float, contentSize: Float): Float {
    val minTrans: Float
    val maxTrans: Float
    if (contentSize <= viewSize) {
        minTrans = 0f
        maxTrans = viewSize - contentSize
    } else {
        minTrans = viewSize - contentSize
        maxTrans = 0f
    }
    if (trans < minTrans) return -trans + minTrans
    if (trans > maxTrans) return -trans + maxTrans
    return 0f
}

fun getFixDragTrans(delta: Float, viewSize: Float, contentSize: Float): Float {
    if (contentSize <= viewSize) {
        return 0f
    } else {
        return delta
    }
}

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec)
    viewWidth = MeasureSpec.getSize(widthMeasureSpec)
    viewHeight = MeasureSpec.getSize(heightMeasureSpec)
    //
    // Rescales image on rotation
    //
    if (oldMeasuredHeight == viewWidth && oldMeasuredHeight == viewHeight || viewWidth == 0 || viewHeight == 0) return
    oldMeasuredHeight = viewHeight
    oldMeasuredWidth = viewWidth
    if (saveScale == 1f) {
        //Fit to screen.
        val scale: Float
        val drawable = drawable
        if (drawable == null || drawable.intrinsicWidth == 0 || drawable.intrinsicHeight == 0) return
        val bmWidth = drawable.intrinsicWidth
        val bmHeight = drawable.intrinsicHeight
        Log.d("bmSize", "bmWidth: $bmWidth bmHeight : $bmHeight")
        val scaleX = viewWidth.toFloat() / bmWidth.toFloat()
        val scaleY = viewHeight.toFloat() / bmHeight.toFloat()
        scale = Math.min(scaleX, scaleY)
        matri!!.setScale(scale, scale)
        // Center the image
        var redundantYSpace = viewHeight.toFloat() - scale * bmHeight.toFloat()
        var redundantXSpace = viewWidth.toFloat() - scale * bmWidth.toFloat()
        redundantYSpace /= 2.toFloat()
        redundantXSpace /= 2.toFloat()
        matri!!.postTranslate(redundantXSpace, redundantYSpace)
        origWidth = viewWidth - 2 * redundantXSpace
        origHeight = viewHeight - 2 * redundantYSpace
        imageMatrix = matri
    }
    fixTrans()
}

companion object {
    // We can be in one of these 3 states
    const val NONE = 0
    const val DRAG = 1
    const val ZOOM = 2
    const val CLICK = 3
}
 }

Examples related to android

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How to implement a simple scenario the OO way My eclipse won't open, i download the bundle pack it keeps saying error log getting " (1) no such column: _id10 " error java doesn't run if structure inside of onclick listener Cannot retrieve string(s) from preferences (settings) strange error in my Animation Drawable how to put image in a bundle and pass it to another activity FragmentActivity to Fragment A failure occurred while executing com.android.build.gradle.internal.tasks

Examples related to android-layout

How to check if a key exists in Json Object and get its value How to center the elements in ConstraintLayout Android - how to make a scrollable constraintlayout? Add ripple effect to my button with button background color? This view is not constrained vertically. At runtime it will jump to the left unless you add a vertical constraint Is it possible to put a ConstraintLayout inside a ScrollView? Differences between ConstraintLayout and RelativeLayout How to remove title bar from the android activity? How to have EditText with border in Android Lollipop Android: ScrollView vs NestedScrollView

Examples related to android-intent

Kotlin Android start new Activity Open Facebook Page in Facebook App (if installed) on Android Android - Adding at least one Activity with an ACTION-VIEW intent-filter after Updating SDK version 23 Not an enclosing class error Android Studio Parcelable encountered IOException writing serializable object getactivity() Sending intent to BroadcastReceiver from adb How to pass ArrayList<CustomeObject> from one activity to another? Android Intent Cannot resolve constructor Android Gallery on Android 4.4 (KitKat) returns different URI for Intent.ACTION_GET_CONTENT Android - java.lang.SecurityException: Permission Denial: starting Intent

Examples related to android-widget

How to create custom button in Android using XML Styles How can I do factory reset using adb in android? Setting Action Bar title and subtitle Determine when a ViewPager changes pages Android Image View Pinch Zooming Add padding on view programmatically Changing position of the Dialog on screen android Using setImageDrawable dynamically to set image in an ImageView how to get html content from a webview? Android How to adjust layout in Full Screen Mode when softkeyboard is visible