Baseflow/PhotoView · error · IllegalArgumentException

Medium zoom has to be less than Maximum zoom. Call setMaximu

Error message

Medium zoom has to be less than Maximum zoom. Call setMaximumZoom() with a more appropriate value

What it means

Util.checkZoomLevels enforces minimumScale < mediumScale < maximumScale; this branch throws IllegalArgumentException when midZoom >= maxZoom, from setMediumScale, setMaximumScale, or setScaleLevels. PhotoView's double-tap handler cycles min -> mid -> max (see setScale(getMediumScale()/getMaximumScale()) in the attacher's onDoubleTap), which requires medium strictly below maximum. The check runs before assignment, so previous valid levels survive the failed call.

Source

Thrown at photoview/src/main/java/com/github/chrisbanes/photoview/Util.java:14

package com.github.chrisbanes.photoview;

import android.view.MotionEvent;
import android.widget.ImageView;

class Util {

    static void checkZoomLevels(float minZoom, float midZoom,
                                float maxZoom) {
        if (minZoom >= midZoom) {
            throw new IllegalArgumentException(
                    "Minimum zoom has to be less than Medium zoom. Call setMinimumZoom() with a more appropriate value");
        } else if (midZoom >= maxZoom) {
            throw new IllegalArgumentException(
                    "Medium zoom has to be less than Maximum zoom. Call setMaximumZoom() with a more appropriate value");
        }
    }

    static boolean hasDrawable(ImageView imageView) {
        return imageView.getDrawable() != null;
    }

    static boolean isSupportedScaleType(final ImageView.ScaleType scaleType) {
        if (scaleType == null) {
            return false;
        }
        switch (scaleType) {
            case MATRIX:
                throw new IllegalStateException("Matrix scale type is not supported");
        }
        return true;
    }

View on GitHub (pinned to 565505d5cb)

Solutions

  1. Set all three at once with setScaleLevels(min, mid, max) keeping mid strictly less than max (e.g. setScaleLevels(1f, 2f, 3f)).
  2. When lowering max, lower mid proportionally first (or in the same call): max = 2f implies mid <= something strictly below 2f, e.g. mid = max * 0.66f.
  3. If levels are dynamic, derive them from one base: min = base, mid = base * 1.75f, max = base * 3f, so ordering can never collapse.

Example fix

// before
photoView.setMaximumScale(1.5f); // throws: mid (2.0) >= max (1.5)

// after
photoView.setScaleLevels(1f, 1.2f, 1.5f);
Defensive patterns

Strategy: validation

Validate before calling

if (mediumScale < maximumScale
        && minimumScale < mediumScale) {
    photoView.setScaleLevels(minimumScale, mediumScale, maximumScale);
} else {
    // derive ordered levels from a single base
    photoView.setScaleLevels(base, base * 1.75f, base * 3f);
}

Prevention

When it happens

Trigger: Calling setMaximumScale(2f) while mediumScale is 2.0 or higher (e.g. default mid 2.0 with new max 2.0 -> 2 >= 2 throws); calling setMediumScale(3f) while max is still 3.0; setScaleLevels(1f, 2.5f, 2f) with mid above max.

Common situations: Lowering maximum zoom for a detail-view screen without also lowering medium; computing medium from image resolution so it exceeds a deliberately small max; setting medium before max during init and picking values that collide at equality; porting constants between screens where max was tuned per-layout but mid is a shared constant.

Related errors


AI-assisted analysis of Baseflow/PhotoView@565505d5cb (2026-08-14). Data as JSON: /api/errors/c75a311489ca3747. Report an issue: GitHub.