Skip to content

Latest commit

 

History

History
308 lines (224 loc) · 9.63 KB

zoom.md

File metadata and controls

308 lines (224 loc) · 9.63 KB

Gesture zoom

Translations: 简体中文

Caution

This component is no longer updated, please use the SketchZoomImageView component of the https://github.com/panpf/zoomimage library instead

Important

Required import sketch-zoom module

Sketch's SketchZoomImageView provides gesture zooming and super large image sampling functions. Gesture zoom function reference PhotoView implementation

Compare PhotoView

  • Double-click zoom level: reduced from three levels to two levels in PhotoView, making the operation easier
  • Double-click scale factor: The double-click scale factor of PhotoView is fixed, while SketchZoomImageView is based on the size of the image and View The width, height and ScaleType are dynamically calculated for a better experience.
  • Boundary damping: When manual scaling exceeds the minimum or maximum ratio, PhotoView cannot be pulled directly, and SketchZoomImageView It will feel like pulling a rubber band and the experience will be better
  • Boundary judgment: SketchZoomImageView optimizes the judgment of scrollEdge and fixes the problem that the edge cannot be recognized under a scale factor that is not divisible bug
  • Slider: SketchZoomImageView adds a slider to easily see the current sliding position
  • Positioning: SketchZoomImageView adds a positioning function, which allows you to specify a point on the image and then move to this point in an animated manner
  • Reading mode: SketchZoomImageView adds read mode, which provides a better read experience for long images

Use

Simply replace ImageView with SketchZoomImageView

sketchZoomImageView.displayImage("https://www.sample.com/image.jpg")

Note:

  • The zoom function supports Drawable from any source
  • The super large image sampling function only supports Drawable from Sketch

Scale

// Zoom in 3x (without animation)
sketchZoomImageView.scale(3f)

// Zoom in 3x and use animation
sketchZoomImageView.scale(3f, true)

// Zoom in 3x with 100x200 as center point and use animation
sketchZoomImageView.scale(3f, 100f, 200f, true)

Note:

  • The set scaling ratio cannot be less than the minimum scaling ratio nor greater than the maximum scaling ratio.
  • The scaling ratio set by the scale method is only temporary and will not be maintained forever. Any other scaling behavior and update behavior will overwrite this scaling ratio.

Rotate

// Rotate to 180°
sketchZoomImageView.rotateTo(180)

// Rotate another 90° clockwise
sketchZoomImageView.rotateBy(90)

Note:

  • Only supports rotation angles such as 90, 180, 270, 360, etc. that can be evenly divided by 90
  • The rotation angle will always exist

Location

// Position to 100x200 (regardless of rotation angle)
sketchZoomImageView.location(100f, 200f)

// Position to 100x200 and use animation (regardless of rotation angle)
sketchZoomImageView.location(100f, 200f, true)

Note: The position set by the location method is only temporary and will not be maintained forever. Any other displacement behavior and update behavior will overwrite this position.

Scroll Bar

The scroll bar allows you to clearly know the current position when viewing a long image. SketchZoomImageView turns on the scroll bar function by default. You can also turn it off, as follows:

sketchZoomImageView.scrollBarEnabled = false

Displayed when scrolling, automatically hidden after 800 milliseconds of no operation

Read Mode

For long images with a particularly large difference in width and height, if the entire image is displayed at the beginning, nothing can be seen clearly, and the user must double-click to enlarge before starting to read.

For such images SketchZoomImageView provides a read mode to fill the screen from the beginning, so that users can directly start read the content of long images.

Turn on read mode:

sketchZoomImageView.readModeEnabled = true

SketchZoomImageView uses ReadModeDecider to determine whether read mode needs to be used. The default implementation is LongImageReadModeDecider, which only uses read mode for long images.

The default implementation of long image rules is [DefaultLongImageDecider], you can also create LongImageReadModeDecider Use custom long image determination rules when

If you want to modify the read mode determination rules, you can implement the ReadModeDecider interface and then apply it through the readModeDecider attribute of SketchZoomImageView, as follows:

class MyReadModeDecider : ReadModeDecider {

    override fun should(
        imageWidth: Int,
        imageHeight: Int,
        viewWidth: Int,
        viewHeight: Int
    ): Boolean {
        // Implement your decision rules
    }
}

sketchZoomImageView.readModeDecider = MyReadModeDecider()

Custom scaling

Through ScaleState, you can modify the minimum, maximum, double-click, initial and other scaling ratios. Just customize your ScaleState and apply it as follows:

class MyScaleStateFactory : ScaleState.Factory {

    override fun create(
        viewSize: Size,
        imageSize: Size,
        drawableSize: Size,
        rotateDegrees: Int,
        scaleType: ScaleType,
        readModeDecider: ReadModeDecider?,
    ): ScaleState {
        val minScale = ...
        val maxScale = ...
        val fullScale = ...
        val fillScale = ...
        val originScale = ...
        val initial = ...
        val steps = ...
        return ScaleState(
            min = minScale,
            max = maxScale,
            full = fullScale,
            fill = fillScale,
            origin = originScale,
            initial = initial,
            doubleClickSteps = steps,
        )
    }
}

sketchZoomImageView.scaleStateFactory = MyScaleStateFactory()

Zoom information

// Get the current scale factor
sketchZoomImageView.scale

// Get the current rotation angle (clockwise)
sketchZoomImageView.rotateDegrees

// Get the minimum scale factor
sketchZoomImageView.minScale

// Get the maximum scale factor
sketchZoomImageView.maxScale

// Get the area visible to the user on the current preview image (not affected by rotation)
sketchZoomImageView.getVisibleRect(Rect())

// more ...

Gesture zoom listener

// Listen for scale changes
sketchZoomImageView.addOnScaleChangeListener { scaleFactor: Float, focusX: Float, focusY: Float ->

}

// Listen click
sketchZoomImageView.onViewTapListener = { view: View, x: Float, y: Float ->

}

// Monitor long press
sketchZoomImageView.onViewLongPressListener = { view: View, x: Float, y: Float ->

}

// more ...

Note: When OnViewTapListener or OnViewLongPressListener is not registered, SketchZoomImageView will try to call back ImageView's OnClickListener or OnLongClickListener

ArrayIndexOutOfBoundsException 与 IllegalArgumentException:pointerIndex out of range

Since it is implemented with reference to PhotoView, this exception is inevitable. It is recommended to intercept it in Activity, as follows:

class ImageDetailActivity : AppCompatActivity() {

    override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
        return try {
            super.dispatchTouchEvent(ev)
        } catch (e: RuntimeException) {
            e.printStackTrace()
            true
        }
    }
}

Very large image sampling

Very large images are usually huge in size, and trying to read them completely into the memory will definitely cause the app to crash due to insufficient memory.

SketchZoomImageView supports the function of super large image sampling through BitmapRegionDecoder to avoid app crashes

Under what circumstances will the super large image sampling function be turned on?

  1. The image is a type supported by BitmapRegionDecoder
  2. Bitmap size is smaller than the original image
  3. Images are loaded via Sketch

Lifecycle

SketchZoomImageView can monitor the status of Lifecycle, pause the super large image sampling and release the Bitmap of all fragments in the pause state, and resume the super large image sampling and reload the fragments in the resume state, so that it can switch to the background or not display when the Fragment or Activity Actively release memory

SketchZoomImageView will obtain the Lifecycle from DisplayRequest, and DisplayRequest will first obtain the Lifecycle from SketchZoomImageView.context. In this way, what is usually obtained is the Lifecycle of the Activity, which is generally sufficient.

If SketchZoomImageView is used in a combination of ViewPager + Fragment, then you need to actively set the Fragment's viewLifecycleOwner.lifecycle to DisplayRequest, as follows:

class MyFragment : Fragment() {

    override fun onViewCreated(view: View) {
        // ...
        sketchZoomImageView.displayImage("https://www.sample.com/image.jpg") {
            lifecycle(viewLifecycleOwner.lifecycle)
        }
    }
}

Super large image sampling monitoring

// Listen tile changes
sketchZoomImageView.addOnTileChangedListener {

}