Матрица просмотра изображений для Android + переводить
Я пытаюсь вручную получить изображение внутри изображения с центром и подгонять экран. Мне нужно сделать это с помощью матрицы (позже я буду динамически менять матричное преобразование).
Проблема в том, что я не могу получить изображение с центром в представлении (масштаб подходит). Вот код:
// Compute the scale to choose (this works)
float scaleX = (float) displayWidth / (float) imageWidth;
float scaleY = (float) displayHeight / (float) imageHeight;
float minScale = Math.min(scaleX, scaleY);
// tx, ty should be the translation to take the image back to the screen center
float tx = Math.max(0,
0.5f * ((float) displayWidth - (minScale * imageWidth)));
float ty = Math.max(0,
0.5f * ((float) displayHeight - (minScale * imageHeight)));
// Compute the matrix
Matrix m = new Matrix();
m.reset();
// Middle of the image should be the scale pivot
m.postScale(minScale, imageWidth/2, imageHeight/2);
// Translate
m.postTranslate(tx, ty);
imageView.setImageMatrix(m);
Вышеприведенный код работает, если я не центрирую масштаб в центре изображения (но мне нужно будет сделать это позже, поэтому мне нужно выяснить формулу сейчас).
Я думал, что следующее будет исправлять проблему, но изображение по-прежнему смещено (вниз и вправо).
tx += 0.5*imageWidth*minScale;
ty += 0.5*imageHeight*minScale;
Некоторые значения у меня:
- изображение: 200x133
- дисплей: 800x480
- minScale: 2.4
- конечный верхний левый угол изображения: 100, 67 (должно быть 17, 0)
Ответы
Ответ 1
Здесь вам поможет удобный метод Matrix.setRectToRect(RectF, RectF, ScaleToFit).
Matrix m = imageView.getImageMatrix();
RectF drawableRect = new RectF(0, 0, imageWidth, imageHeight);
RectF viewRect = new RectF(0, 0, imageView.getWidth(), imageView.getHeight());
m.setRectToRect(drawableRect, viewRect, Matrix.ScaleToFit.CENTER);
imageView.setImageMatrix(m);
Это должно установить матрицу m
, чтобы иметь комбинацию масштабирования и переводить значения, необходимые для отображения центрированного и подходящего элемента в виджетах ImageView.
Ответ 2
Вот как я решил свою проблему с помощью матриц (запрошенных joakime в другом ответе):
private void setImageTransformation(float tx, float ty, float scale) {
savedMatrix.reset();
savedMatrix.postTranslate(-imageWidth / 2f, -imageHeight / 2f);
savedMatrix.postScale(scale, scale);
savedMatrix.postTranslate(tx, ty);
imageView.setImageMatrix(savedMatrix);
}
public void resetImageMatrix() {
if (!isImageLoaded()) return;
imageWidth = imageView.getDrawable().getIntrinsicWidth();
imageHeight = imageView.getDrawable().getIntrinsicHeight();
float scaleX = (float) displayWidth / (float) imageWidth;
float scaleY = (float) displayHeight / (float) imageHeight;
minScale = Math.min(scaleX, scaleY);
maxScale = 2.5f * minScale;
initialTranslation.set(
Math.max(0,
minScale * imageWidth / 2f
+ 0.5f * (displayWidth - (minScale * imageWidth))),
Math.max(0,
minScale * imageHeight / 2f
+ 0.5f * (displayHeight - (minScale * imageHeight))));
currentScale = minScale;
currentTranslation.set(initialTranslation);
initialImageRect.set(0, 0, imageWidth, imageHeight);
setImageTransformation(initialTranslation.x, initialTranslation.y,
minScale);
}
Я немного обманываюсь, потому что пинч не находится по центру между пальцами пользователя, что приемлемо в моем случае.
Ответ 3
Или используя
m.postScale(minScale, minScale); //keep aspect ratio
float tx = (getWidth() - bitmap1.getWidth()* scale) * 0.5f ;
float ty = (getHeight() - bitmap1.getHeight()* scale) * 0.5f ;
matrix.postTranslate(tx, ty );
где getWidth - это ширина вашего изображения.
Отлично работает для меня
Ответ 4
Эй, у меня была такая же проблема, и ты был так близок! Это был порядок операций, по крайней мере для меня. Для меня работали следующие:
tx = (width - imgWidth) * 0.5f * scale;