티스토리 뷰

안드로이드

이미지 zoom & Pinch-to-Zoom

성현아빠 2020. 7. 28. 10:28

ImageView에서 작은 이미지를 눌렀을때 이미지 확대해주는 기능이 필요하다.

구글에 이미지 확대를 해주면서 animation이 되는 코드가 있어 이 코드를 참고해서 구현을 했다.

 

https://developer.android.com/training/animation/zoom?hl=ko

 

확대/축소 애니메이션으로 뷰 확대  |  Android 개발자  |  Android Developers

이 과정에서는 '터치로 확대/축소' 애니메이션을 실행하는 방법을 설명합니다. 이러한 애니메이션은 뷰를 미리보기 이미지에서 화면을 가득 채우는 전체 크기 이미지로 애니메이션하는 사진 갤

developer.android.com

zoom 이미지를 터치하면 다시 작아지는데

zoom 이미지를 pinch-to-zoom 기능이 추가가 필요해서 PhotoView library를 추가했다.

 

https://github.com/chrisbanes/PhotoView

 

chrisbanes/PhotoView

Implementation of ImageView for Android that supports zooming, by various touch gestures. - chrisbanes/PhotoView

github.com

 

전체 적용한 코드

layout.xml

    <com.github.chrisbanes.photoview.PhotoView
        android:id="@+id/expanded_image"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

 

이미지 Click시 zoom 이벤트 추가

    private var shortAnimationDuration: Int = 0
    private lateinit var expandedImageView: PhotoView
    
    override fun onCreate(savedInstanceState: Bundle?) {
    
        ........
        
        mBannerSlider = findViewById(R.id.banner_slider)

        mBannerSlider.setOnSlideClickListener {
            // 이미지 줌 기능 추가 - 이미지 touch시 zoom된 이미지 animation으로 보여줌
	        zoomImageFromThumb(mBannerSlider.findViewById(R.id.banner_slider), mFileList[index])
        }

        // 이미지 줌 기능 추가
        // Retrieve and cache the system's default "short" animation time.
        shortAnimationDuration = resources.getInteger(android.R.integer.config_shortAnimTime)
    }

 

zoom 기능 코드

   private fun zoomImageFromThumb(thumbView: View, imageFile: String) {
        // If there's an animation in progress, cancel it
        // immediately and proceed with this one.
        currentAnimator?.cancel()

        // 이전버튼 동작을 위해 추가
        mThumbView = thumbView

        // Load the high-resolution "zoomed-in" image.
// original 코드
//        val expandedImageView: ImageView = findViewById(R.id.expanded_image)
//        expandedImageView.setImageResource(imageResId)
// 파일을 읽어서 보여주기 때문에 file URI로 변경
        expandedImageView = findViewById(R.id.expanded_image)
        val f = AppUtil.getFile(imageFile)
        expandedImageView.setImageURI(Uri.fromFile(f))

        // Calculate the starting and ending bounds for the zoomed-in image.
        // This step involves lots of math. Yay, math.
        val startBoundsInt = Rect()
        val finalBoundsInt = Rect()
        val globalOffset = Point()

        // The start bounds are the global visible rectangle of the thumbnail,
        // and the final bounds are the global visible rectangle of the container
        // view. Also set the container view's offset as the origin for the
        // bounds, since that's the origin for the positioning animation
        // properties (X, Y).
        thumbView.getGlobalVisibleRect(startBoundsInt)
        findViewById<View>(R.id.container)
            .getGlobalVisibleRect(finalBoundsInt, globalOffset)
        startBoundsInt.offset(-globalOffset.x, -globalOffset.y)
        finalBoundsInt.offset(-globalOffset.x, -globalOffset.y)

        val startBounds = RectF(startBoundsInt)
        val finalBounds = RectF(finalBoundsInt)

        // 이전버튼 동작을 위해 추가
        mStartBounds = startBounds

        // Adjust the start bounds to be the same aspect ratio as the final
        // bounds using the "center crop" technique. This prevents undesirable
        // stretching during the animation. Also calculate the start scaling
        // factor (the end scaling factor is always 1.0).
        val startScale: Float
        if ((finalBounds.width() / finalBounds.height() > startBounds.width() / startBounds.height())) {
            // Extend start bounds horizontally
            startScale = startBounds.height() / finalBounds.height()
            val startWidth: Float = startScale * finalBounds.width()
            val deltaWidth: Float = (startWidth - startBounds.width()) / 2
            startBounds.left -= deltaWidth.toInt()
            startBounds.right += deltaWidth.toInt()
        } else {
            // Extend start bounds vertically
            startScale = startBounds.width() / finalBounds.width()
            val startHeight: Float = startScale * finalBounds.height()
            val deltaHeight: Float = (startHeight - startBounds.height()) / 2f
            startBounds.top -= deltaHeight.toInt()
            startBounds.bottom += deltaHeight.toInt()
        }

        // 이전버튼 동작을 위해 추가
        mStartScale = startScale

        // Hide the thumbnail and show the zoomed-in view. When the animation
        // begins, it will position the zoomed-in view in the place of the
        // thumbnail.
        thumbView.alpha = 0f
        expandedImageView.visibility = View.VISIBLE

        // Set the pivot point for SCALE_X and SCALE_Y transformations
        // to the top-left corner of the zoomed-in view (the default
        // is the center of the view).
        expandedImageView.pivotX = 0f
        expandedImageView.pivotY = 0f

        // Construct and run the parallel animation of the four translation and
        // scale properties (X, Y, SCALE_X, and SCALE_Y).
        currentAnimator = AnimatorSet().apply {
            play(
                ObjectAnimator.ofFloat(
                expandedImageView,
                View.X,
                startBounds.left,
                finalBounds.left)
            ).apply {
                with(ObjectAnimator.ofFloat(expandedImageView, View.Y, startBounds.top, finalBounds.top))
                with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_X, startScale, 1f))
                with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_Y, startScale, 1f))
            }
            duration = shortAnimationDuration.toLong()
            interpolator = DecelerateInterpolator()
            addListener(object : AnimatorListenerAdapter() {

                override fun onAnimationEnd(animation: Animator) {
                    currentAnimator = null
                }

                override fun onAnimationCancel(animation: Animator) {
                    currentAnimator = null
                }
            })
            start()
        }

        // Upon clicking the zoomed-in image, it should zoom back down
        // to the original bounds and show the thumbnail instead of
        // the expanded image.
        expandedImageView.setOnClickListener {
            // 아래 코드 함수로 이동
            closeExpandedImageView()
        }
    }

 

Back 키 누를경우 activity finish 기능을 추가했더니

zoom된 상태에서 back 키 누를경우 화면이 finish 되는 문제로

expandedImageView.setOnClickListener의 내용을 따로 분리해서 back key 눌렀을때에 같이 이용.

 

    private lateinit var mThumbView: View
    private lateinit var mStartBounds: RectF
    private var mStartScale: Float = 0.0f
    
    private fun closeExpandedImageView() {
        currentAnimator?.cancel()

        // Animate the four positioning/sizing properties in parallel,
        // back to their original values.
        currentAnimator = AnimatorSet().apply {
            play(ObjectAnimator.ofFloat(expandedImageView, View.X, mStartBounds.left)).apply {
                with(ObjectAnimator.ofFloat(expandedImageView, View.Y, mStartBounds.top))
                with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_X, mStartScale))
                with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_Y, mStartScale))
            }
            duration = shortAnimationDuration.toLong()
            interpolator = DecelerateInterpolator()
            addListener(object : AnimatorListenerAdapter() {

                override fun onAnimationEnd(animation: Animator) {
                    mThumbView.alpha = 1f
                    expandedImageView.visibility = View.GONE
                    currentAnimator = null
                }

                override fun onAnimationCancel(animation: Animator) {
                    mThumbView.alpha = 1f
                    expandedImageView.visibility = View.GONE
                    currentAnimator = null
                }
            })
            start()
        }
    }

 

build.gradle(app)

// Pinch-to-Zoom 기능
implementation 'com.github.chrisbanes:PhotoView:2.1.3'

이렇게 또 하나 했는데 재미가 없다. 왜 그럴까??

'안드로이드' 카테고리의 다른 글

이미지 파일공유(여러파일)  (0) 2020.08.25
미디어파일 저장  (0) 2020.08.25
안드로이드 Volley Multi-part File upload  (0) 2020.07.15
다이얼로그 배경 지우기  (0) 2020.07.01
Toolbar Home Indicator Icon 변경  (0) 2020.04.24