ImageView adjustViewBounds не работает
У меня есть ImageView с android:layout_width=100dp
, android:layout_height=wrap_content
и android:adjustViewBounds=true
Источник - это 50 x 50 пикселей. Но соотношение сторон не сохраняется - высота ImageView составляет 50 пикселей, а не 100 пикселей (т.е. adjustViewBounds
не работает). Если у меня есть изображение 200x200px, оно работает - ширина и высота - 100 пикселей. Этот код дает изображение шириной 100 пикселей и размером 50 пикселей, но изображение src равно квадрату:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView
android:id="@+id/photo"
android:src="@drawable/icon"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:adjustViewBounds="true" />
</LinearLayout>
Ответы
Ответ 1
Проблема заключается в том, что adjustViewBounds
не будет увеличивать размер ImageView
за пределами естественных размеров извлекаемого. Он будет только уменьшать представление, чтобы поддерживать соотношение сторон; если вы предоставили изображение размером 500x500 вместо изображения 50x50, это должно работать.
Если вам интересно, где это поведение реализовано, см. ImageView.java onMeasure.
Одним из способов решения является реализация пользовательского ImageView
, который изменяет это поведение в onMeasure
.
Ответ 2
Там более простой способ. Сделайте свой ImageView следующим:
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitCenter"
android:adjustViewBounds="true"/>
Таким образом, drawable будет растягиваться, чтобы поместиться в центре ImageView, сохранив
соотношение сторон. Нам просто нужно вычислить правильную высоту, чтобы сделать ее пропорциональной
поэтому у нас нет пробелов:
private void setImageBitmap(Bitmap bitmap, ImageView imageView){
float i = ((float)imageWidth)/((float)bitmap.getWidth());
float imageHeight = i * (bitmap.getHeight());
imageView.setLayoutParams(new RelativeLayout.LayoutParams(imageWidth, (int) imageHeight));
imageView.setImageBitmap(bitmap);
}
Ответ 3
В дополнение к @RomanNurik answer
Здесь вы можете найти рабочее решение здесь, либо код для копирования-вставки, либо просто добавить зависимость Gradle
dependencies {
compile 'com.inthecheesefactory.thecheeselibrary:adjustable-imageview:1.0.1'
}
P.S. Решение, предоставленное @Nilzor, не сработало для меня
Ответ 4
У меня было аналогичное требование; в моем случае я хотел, чтобы изображение было квадратным, и хотел, чтобы ImageView соответствовал соотношению сторон, поэтому я мог использовать его фон и дополнение для рисования границы.
Я прочитал ответы здесь, но вместо того, чтобы переопределять ImageView, я решил создать макет, который гарантирует, что его содержимое (должно быть только одно представление) является квадратным. Таким образом, я мог бы использовать стандартный ImageView внутри него. (И вы никогда не знаете, я мог бы захотеть сделать что-то еще квадратное позже. Хотя, вероятно, нет.)
В случае, если это полезно для кого-то еще, вот код (не стесняйтесь копировать). Вероятно, есть ошибки, поскольку я только что сделал это для моего приложения, а затем остановился.:)
public class SquareLayout extends ViewGroup
{
public SquareLayout(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
public SquareLayout(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public SquareLayout(Context context)
{
super(context);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b)
{
// Work out width and height, and square size.
int width = r - l;
int height = b - t;
int size, xOffset, yOffset;
if(width < height)
{
size = width;
xOffset = 0;
yOffset = (height - size) / 2;
}
else
{
size = height;
xOffset = (width - size) / 2;
yOffset = 0;
}
for(int i = 0; i < getChildCount(); i++)
{
View child = getChildAt(i);
child.layout(xOffset, yOffset, size + xOffset, size + yOffset);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
// Get width and height.
int w = -1, h = -1;
switch(MeasureSpec.getMode(widthMeasureSpec))
{
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
w = MeasureSpec.getSize(widthMeasureSpec);
break;
case MeasureSpec.UNSPECIFIED:
break;
}
switch(MeasureSpec.getMode(heightMeasureSpec))
{
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
h = MeasureSpec.getSize(heightMeasureSpec);
break;
case MeasureSpec.UNSPECIFIED:
break;
}
// If only one of width/height is unspecified, set them both the same.
if(w == -1 && h != -1)
{
w = h;
}
else if(h == -1 && w != -1)
{
h = w;
}
// Either they're both specified or both unspecified.
int childMeasureSpec;
if(w == -1)
{
childMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
}
else
{
childMeasureSpec = MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY);
}
// Pass through to children.
int maxDimension = 1;
for(int i = 0; i < getChildCount(); i++)
{
View child = getChildAt(i);
child.measure(childMeasureSpec, childMeasureSpec);
maxDimension = Math.max(maxDimension, child.getMeasuredWidth());
maxDimension = Math.max(maxDimension, child.getMeasuredHeight());
}
if(w == -1)
{
w = maxDimension;
h = maxDimension;
}
setMeasuredDimension(w, h);
}
}
Ответ 5
эта строка сделает это за вас android: scaleType = "fitXY"