Tôi chỉ đọc mã nguồn ImageView
và về cơ bản là không thể nếu không sử dụng các giải pháp phân lớp con trong chủ đề này. Trong ImageView.onMeasure
chúng ta có những dòng sau:
// Get the max possible width given our constraints
widthSize = resolveAdjustedSize(w + pleft + pright, mMaxWidth, widthMeasureSpec);
// Get the max possible height given our constraints
heightSize = resolveAdjustedSize(h + ptop + pbottom, mMaxHeight, heightMeasureSpec);
Kích thước của hình ảnh ở đâu h
và ở đâu w
, và p*
là phần đệm.
Và sau đó:
private int resolveAdjustedSize(int desiredSize, int maxSize,
int measureSpec) {
...
switch (specMode) {
case MeasureSpec.UNSPECIFIED:
/* Parent says we can be as big as we want. Just don't be larger
than max size imposed on ourselves.
*/
result = Math.min(desiredSize, maxSize);
Vì vậy, nếu bạn có, layout_height="wrap_content"
nó sẽ đặt widthSize = w + pleft + pright
, hay nói cách khác, chiều rộng tối đa bằng chiều rộng hình ảnh.
Điều này có nghĩa là trừ khi bạn đặt kích thước chính xác, hình ảnh KHÔNG BAO GIỜ được phóng to . Tôi coi đây là một lỗi, nhưng may mắn được Google chú ý hoặc sửa chữa nó. Chỉnh sửa: Ăn theo lời của tôi, tôi đã gửi một báo cáo lỗi và họ nói rằng nó đã được sửa trong một bản phát hành trong tương lai!
Giải pháp khác
Đây là một giải pháp thay thế lớp con khác, nhưng bạn nên (về lý thuyết, tôi chưa thực sự thử nghiệm nó nhiều!) Có thể sử dụng nó ở bất cứ đâu ImageView
. Để sử dụng nó thiết lập layout_width="match_parent"
, và layout_height="wrap_content"
. Nó cũng tổng quát hơn nhiều so với giải pháp được chấp nhận. Ví dụ: bạn có thể làm vừa với chiều cao cũng như vừa với chiều rộng.
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ImageView;
// This works around the issue described here: http://stackoverflow.com/a/12675430/265521
public class StretchyImageView extends ImageView
{
public StretchyImageView(Context context)
{
super(context);
}
public StretchyImageView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public StretchyImageView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
// Call super() so that resolveUri() is called.
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// If there's no drawable we can just use the result from super.
if (getDrawable() == null)
return;
final int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
final int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
int w = getDrawable().getIntrinsicWidth();
int h = getDrawable().getIntrinsicHeight();
if (w <= 0)
w = 1;
if (h <= 0)
h = 1;
// Desired aspect ratio of the view's contents (not including padding)
float desiredAspect = (float) w / (float) h;
// We are allowed to change the view's width
boolean resizeWidth = widthSpecMode != MeasureSpec.EXACTLY;
// We are allowed to change the view's height
boolean resizeHeight = heightSpecMode != MeasureSpec.EXACTLY;
int pleft = getPaddingLeft();
int pright = getPaddingRight();
int ptop = getPaddingTop();
int pbottom = getPaddingBottom();
// Get the sizes that ImageView decided on.
int widthSize = getMeasuredWidth();
int heightSize = getMeasuredHeight();
if (resizeWidth && !resizeHeight)
{
// Resize the width to the height, maintaining aspect ratio.
int newWidth = (int) (desiredAspect * (heightSize - ptop - pbottom)) + pleft + pright;
setMeasuredDimension(newWidth, heightSize);
}
else if (resizeHeight && !resizeWidth)
{
int newHeight = (int) ((widthSize - pleft - pright) / desiredAspect) + ptop + pbottom;
setMeasuredDimension(widthSize, newHeight);
}
}
}