Поместите изображение в ImageView, сохраните соотношение сторон, а затем измените размер ImageView на размеры изображения?
как поместить изображение случайного размера в ImageView
?
Когда:
- изначально
ImageView
размеры 250dp * 250dp - больший размер изображения должен быть масштабирован вверх / вниз до 250dp
- изображение должно сохранять соотношение сторон
- на
ImageView
размеры должны соответствовать размерам изображение после масштабирования
Е. Г. для изображения 100*150, изображения и ImageView
должно быть 166*250.
Е. Г. для изображения 150*100, изображения и ImageView
должно быть 250*166.
если я установлю границы как
<ImageView
android:id="@+id/picture"
android:layout_width="250dp"
android:layout_height="250dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="20dp"
android:adjustViewBounds="true" />
изображения правильно вписываются в ImageView
, а ImageView
всегда 250dp * 250dp.
13 ответов
(ответ был сильно изменен после разъяснений к исходному вопросу)
после разъяснения:
Это невозможно сделать только в xml. Невозможно масштабировать как изображение, так и ImageView
Так что одно измерение изображения всегда будет 250dp и ImageView
будет иметь те же размеры, что и изображение.
этот код весы Drawable
на ImageView
чтобы остаться в квадрате, как 250dp x 250dp с одним размером ровно 250dp и сохранением соотношения сторон. Тогда ImageView
изменяется в соответствии с размерами масштабировать изображения. Код используется в действии. Я протестировал его с помощью обработчика нажатия кнопки.
наслаждайтесь. :)
private void scaleImage(ImageView view) throws NoSuchElementException {
// Get bitmap from the the ImageView.
Bitmap bitmap = null;
try {
Drawable drawing = view.getDrawable();
bitmap = ((BitmapDrawable) drawing).getBitmap();
} catch (NullPointerException e) {
throw new NoSuchElementException("No drawable on given view");
} catch (ClassCastException e) {
// Check bitmap is Ion drawable
bitmap = Ion.with(view).getBitmap();
}
// Get current dimensions AND the desired bounding box
int width = 0;
try {
width = bitmap.getWidth();
} catch (NullPointerException e) {
throw new NoSuchElementException("Can't find bitmap on given view/drawable");
}
int height = bitmap.getHeight();
int bounding = dpToPx(250);
Log.i("Test", "original width = " + Integer.toString(width));
Log.i("Test", "original height = " + Integer.toString(height));
Log.i("Test", "bounding = " + Integer.toString(bounding));
// Determine how much to scale: the dimension requiring less scaling is
// closer to the its side. This way the image always stays inside your
// bounding box AND either x/y axis touches it.
float xScale = ((float) bounding) / width;
float yScale = ((float) bounding) / height;
float scale = (xScale <= yScale) ? xScale : yScale;
Log.i("Test", "xScale = " + Float.toString(xScale));
Log.i("Test", "yScale = " + Float.toString(yScale));
Log.i("Test", "scale = " + Float.toString(scale));
// Create a matrix for the scaling and add the scaling data
Matrix matrix = new Matrix();
matrix.postScale(scale, scale);
// Create a new bitmap and convert it to a format understood by the ImageView
Bitmap scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
width = scaledBitmap.getWidth(); // re-use
height = scaledBitmap.getHeight(); // re-use
BitmapDrawable result = new BitmapDrawable(scaledBitmap);
Log.i("Test", "scaled width = " + Integer.toString(width));
Log.i("Test", "scaled height = " + Integer.toString(height));
// Apply the scaled bitmap
view.setImageDrawable(result);
// Now change ImageView's dimensions to match the scaled image
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams();
params.width = width;
params.height = height;
view.setLayoutParams(params);
Log.i("Test", "done");
}
private int dpToPx(int dp) {
float density = getApplicationContext().getResources().getDisplayMetrics().density;
return Math.round((float)dp * density);
}
код xml для ImageView
:
<ImageView a:id="@+id/image_box"
a:background="#ff0000"
a:src="@drawable/star"
a:layout_width="wrap_content"
a:layout_height="wrap_content"
a:layout_marginTop="20dp"
a:layout_gravity="center_horizontal"/>
Благодаря этому обсуждению для масштабирования code:
http://www.anddev.org/resize_and_rotate_image_-_example-t621.html
обновление 7 ноября 2012:
Добавлена проверка нулевого указателя, как предложено в комментариях
может не быть ответом на этот конкретный вопрос, но если кто-то, как и я, ищет ответ, как соответствовать изображению в ImageView с ограниченным размером (например,maxWidth
) сохраняя соотношение сторон, а затем избавляясь от избыточного пространства, занятого ImageView, самым простым решением является использование следующих свойств в XML:
android:scaleType="centerInside"
android:adjustViewBounds="true"
<ImageView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:adjustViewBounds="true"/>
приведенный ниже код делает растровое изображение идеально с тем же размером imageview. Получите высоту и ширину растрового изображения, а затем вычислите новую высоту и ширину с помощью параметров imageview. Это дает вам требуемое изображение с лучшим соотношением сторон.
int currentBitmapWidth = bitMap.getWidth();
int currentBitmapHeight = bitMap.getHeight();
int ivWidth = imageView.getWidth();
int ivHeight = imageView.getHeight();
int newWidth = ivWidth;
newHeight = (int) Math.floor((double) currentBitmapHeight *( (double) new_width / (double) currentBitmapWidth));
Bitmap newbitMap = Bitmap.createScaledBitmap(bitMap, newWidth, newHeight, true);
imageView.setImageBitmap(newbitMap)
наслаждайтесь.
после поисков в течение дня, я думаю, что это самое простое решение:
imageView.getLayoutParams().width = 250;
imageView.getLayoutParams().height = 250;
imageView.setAdjustViewBounds(true);
лучшим решением, которое работает в большинстве случаев, является
вот пример:
<ImageView android:id="@+id/avatar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"/>
используйте этот код:
<ImageView android:id="@+id/avatar"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:scaleType="fitXY" />
все это можно сделать с помощью XML... другие методы кажутся довольно сложными. В любом случае, вы просто устанавливаете высоту на то, что вы хотите в dp, а затем устанавливаете ширину для обертывания контента или наоборот. Используйте scaleType fitCenter для настройки размера изображения.
<ImageView
android:layout_height="200dp"
android:layout_width="wrap_content"
android:scaleType="fitCenter"
android:adjustViewBounds="true"
android:src="@mipmap/ic_launcher"
android:layout_below="@+id/title"
android:layout_margin="5dip"
android:id="@+id/imageView1">
редактировать Ярно Argillanders ответ:
как соответствовать изображению с вашей шириной и высотой:
1) инициализировать ImageView и установить изображение:
iv = (ImageView) findViewById(R.id.iv_image);
iv.setImageBitmap(image);
2) теперь размер:
scaleImage(iv);
редактировать scaleImage
способ: (вы можете заменить ожидаемые ограничивающие значения)
private void scaleImage(ImageView view) {
Drawable drawing = view.getDrawable();
if (drawing == null) {
return;
}
Bitmap bitmap = ((BitmapDrawable) drawing).getBitmap();
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int xBounding = ((View) view.getParent()).getWidth();//EXPECTED WIDTH
int yBounding = ((View) view.getParent()).getHeight();//EXPECTED HEIGHT
float xScale = ((float) xBounding) / width;
float yScale = ((float) yBounding) / height;
Matrix matrix = new Matrix();
matrix.postScale(xScale, yScale);
Bitmap scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
width = scaledBitmap.getWidth();
height = scaledBitmap.getHeight();
BitmapDrawable result = new BitmapDrawable(context.getResources(), scaledBitmap);
view.setImageDrawable(result);
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams();
params.width = width;
params.height = height;
view.setLayoutParams(params);
}
и .XML-код:
<ImageView
android:id="@+id/iv_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
сделал это для моего случая.
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:scaleType="centerCrop"
android:adjustViewBounds="true"
/>
мне нужно было сделать это в макете ограничений с Пикассо, поэтому я собрал некоторые из вышеупомянутых ответов и придумал это решение (я уже знаю соотношение сторон изображения, которое я загружаю, так что это помогает):
вызывается в моем коде активности где-то после setContentView (...)
protected void setBoxshotBackgroundImage() {
ImageView backgroundImageView = (ImageView) findViewById(R.id.background_image_view);
if(backgroundImageView != null) {
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int width = displayMetrics.widthPixels;
int height = (int) Math.round(width * ImageLoader.BOXART_HEIGHT_ASPECT_RATIO);
// we adjust the height of this element, as the width is already pinned to the parent in xml
backgroundImageView.getLayoutParams().height = height;
// implement your Picasso loading code here
} else {
// fallback if no element in layout...
}
}
в моем XML
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout_editor_absoluteY="0dp"
tools:layout_editor_absoluteX="0dp">
<ImageView
android:id="@+id/background_image_view"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="fitStart"
app:srcCompat="@color/background"
android:adjustViewBounds="true"
tools:layout_editor_absoluteY="0dp"
android:layout_marginTop="0dp"
android:layout_marginBottom="0dp"
android:layout_marginRight="0dp"
android:layout_marginLeft="0dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<!-- other elements of this layout here... -->
</android.support.constraint.ConstraintLayout>
обратите внимание на отсутствие атрибута constraintBottom_toBottomOf. ImageLoader мой собственный статический класс для загрузки изображений util методы и константы.
мне нужно было иметь ImageView и растровое изображение, поэтому растровое изображение масштабируется до размера ImageView, а размер ImageView совпадает с масштабированным растровым изображением :).
Я просматривал этот пост, как это сделать, и наконец сделал то, что я хочу, а не как описано здесь.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/acpt_frag_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/imageBackground"
android:orientation="vertical">
<ImageView
android:id="@+id/acpt_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:layout_margin="@dimen/document_editor_image_margin"
android:background="@color/imageBackground"
android:elevation="@dimen/document_image_elevation" />
а затем в методе onCreateView
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_scanner_acpt, null);
progress = view.findViewById(R.id.progress);
imageView = view.findViewById(R.id.acpt_image);
imageView.setImageBitmap( bitmap );
imageView.getViewTreeObserver().addOnGlobalLayoutListener(()->
layoutImageView()
);
return view;
}
а затем layoutImageView () код
private void layoutImageView(){
float[] matrixv = new float[ 9 ];
imageView.getImageMatrix().getValues(matrixv);
int w = (int) ( matrixv[Matrix.MSCALE_X] * bitmap.getWidth() );
int h = (int) ( matrixv[Matrix.MSCALE_Y] * bitmap.getHeight() );
imageView.setMaxHeight(h);
imageView.setMaxWidth(w);
}
и в результате это изображение вписывается внутрь идеально, сохраняя соотношение сторон, и не имеет дополнительных оставшихся пикселей из ImageView, когда растровое изображение находится внутри.
важно иметь ImageView wrap_content в качестве параметров и adjustViewBounds в true, тогда setMaxWidth и setMaxHeight будут работать, это написано в исходном коде ImageView,
/*An optional argument to supply a maximum height for this view. Only valid if
* {@link #setAdjustViewBounds(boolean)} has been set to true. To set an image to be a
* maximum of 100 x 100 while preserving the original aspect ratio, do the following: 1) set
* adjustViewBounds to true 2) set maxWidth and maxHeight to 100 3) set the height and width
* layout params to WRAP_CONTENT. */