{"record":{"id":"3ef0b237cc03c4b4","repo":"Baseflow/PhotoView","slug":"minimum-zoom-has-to-be-less-than-medium-zoom-call","errorCode":null,"errorMessage":"Minimum zoom has to be less than Medium zoom. Call setMinimumZoom() with a more appropriate value","messagePattern":"Minimum zoom has to be less than Medium zoom\\. Call setMinimumZoom\\(\\) with a more appropriate value","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"photoview/src/main/java/com/github/chrisbanes/photoview/Util.java","lineNumber":11,"sourceCode":"package com.github.chrisbanes.photoview;\n\nimport android.view.MotionEvent;\nimport android.widget.ImageView;\n\nclass Util {\n\n    static void checkZoomLevels(float minZoom, float midZoom,\n                                float maxZoom) {\n        if (minZoom >= midZoom) {\n            throw new IllegalArgumentException(\n                    \"Minimum zoom has to be less than Medium zoom. Call setMinimumZoom() with a more appropriate value\");\n        } else if (midZoom >= maxZoom) {\n            throw new IllegalArgumentException(\n                    \"Medium zoom has to be less than Maximum zoom. Call setMaximumZoom() with a more appropriate value\");\n        }\n    }\n\n    static boolean hasDrawable(ImageView imageView) {\n        return imageView.getDrawable() != null;\n    }\n\n    static boolean isSupportedScaleType(final ImageView.ScaleType scaleType) {\n        if (scaleType == null) {\n            return false;\n        }\n        switch (scaleType) {\n            case MATRIX:\n                throw new IllegalStateException(\"Matrix scale type is not supported\");","sourceCodeStart":1,"sourceCodeEnd":29,"githubUrl":"https://github.com/Baseflow/PhotoView/blob/565505d5cb84f5977771b5d2ccb7726338e77224/photoview/src/main/java/com/github/chrisbanes/photoview/Util.java#L1-L29","documentation":"Util.checkZoomLevels enforces the invariant minimumScale < mediumScale < maximumScale and throws IllegalArgumentException from setMinimumScale, setMediumScale, setMaximumScale, or setScaleLevels when minZoom >= midZoom. PhotoView's double-tap and zoom gesture logic assumes a strictly increasing ordering, so a flat or inverted range would make double-tap cycles undefined. The exception fires before any state is mutated, so the attacher keeps its previous valid levels.","triggerScenarios":"Calling photoView.setMinimumScale(2f) while mediumScale is still 2.0 (default) — 2 >= 2 throws; calling setScaleLevels(1f, 1f, 3f) with min equal to mid; calling setScaleLevels(1.5f, 1.2f, 3f) with min greater than mid; any per-level setter whose new value crosses the adjacent level.","commonSituations":"Deriving one zoom level from image dimensions (e.g. medium = drawableWidth/viewWidth) while leaving others hardcoded, so medium ends up <= min (a large image in a small view gives medium < 1.0 while min stays 1.0); ordering setMinimumScale/setMediumScale calls wrongly during initialization (setting min after mid); migrating from an older PhotoView version where level checks were looser.","solutions":["Set all three levels atomically with setScaleLevels(min, mid, max) in strictly increasing order, instead of sequencing individual setters.","If levels are computed from image size, clamp/order them before applying: ensure min < mid < max, e.g. min = Math.min(min, mid / 2f).","Reorder initialization so setMinimumScale runs before setMediumScale/setMaximumScale, and make each new value respect the levels already set."],"exampleFix":"// before\nphotoView.setMinimumScale(fitScale); // throws when fitScale >= midScale\n\n// after\nphotoView.setScaleLevels(\n    Math.min(fitScale, DEFAULT_MID / 2f),\n    Math.max(fitScale * 1.5f, DEFAULT_MID),\n    Math.max(fitScale * 3f, DEFAULT_MAX));","handlingStrategy":"validation","validationCode":"float min = Math.min(minScale, midScale * 0.5f);\nfloat mid = Math.max(midScale, min * 1.5f);\n// keep mid < max by construction before any setter runs\nphotoView.setScaleLevels(min, mid, Math.max(maxScale, mid * 1.5f));","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always configure all three levels in one setScaleLevels(min, mid, max) call instead of sequencing individual setters.","When levels are computed from drawable size, assert min < mid < max in debug builds (assert mid > min && max > mid).","Order setters min -> mid -> max if you must set them individually, and make each value strictly greater than the previous."],"tags":["photoview","android","zoom","validation","configuration","illegalargumentexception"],"backgroundTag":null,"analyzedSha":"565505d5cb84f5977771b5d2ccb7726338e77224","analyzedAt":"2026-08-14T14:25:26.552Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}