ImageView 是动态宽度的正方形?
Posted
技术标签:
【中文标题】ImageView 是动态宽度的正方形?【英文标题】:ImageView be a square with dynamic width? 【发布时间】:2013-05-06 13:20:10 【问题描述】:我有一个 GridView,里面有 ImageViews。我每行有 3 个。我可以使用 WRAP_CONTENT 和 scaleType = CENTER_CROP 正确设置宽度,但我不知道如何将 ImageView 的大小设置为正方形。这是我到目前为止所做的,除了高度之外似乎还可以,即“静态”:
imageView = new ImageView(context);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setLayoutParams(new GridView.LayoutParams(GridView.LayoutParams.WRAP_CONTENT, 300));
我在适配器内部进行。
【问题讨论】:
【参考方案1】:最好的选择是自己继承ImageView
,覆盖measure pass:
public class SquareImageView extends ImageView
...
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
setMeasuredDimension(width, width);
...
【讨论】:
太棒了!非常感谢,我没有想过这种可能 如果我设置填充 // 边距,我会得到一个白色边框。知道如何解决这个问题吗? android:adjustViewBounds="true" android:scaleType="centerCrop" @Waza_Be 不应该改为min(width,height)吗? 这是一个微小的优化,但检查宽度和高度是否不同可能会阻止另一次测量通过。 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) super.onMeasure(widthMeasureSpec, heightMeasureSpec); int 宽度 = getMeasuredWidth(); int 高度 = getMeasuredHeight(); // 优化所以我们不会测量两次,除非我们需要 if (width != height) setMeasuredDimension(width, width); 【参考方案2】:另一个答案很好。这只是 bertucci 的解决方案的扩展,以相对于 xml 膨胀布局制作具有正方形宽度和高度的 ImageView。
创建一个类,比如像这样扩展 ImageView 的 SquareImageView,
public class SquareImageView extends ImageView
public SquareImageView(Context context)
super(context);
public SquareImageView(Context context, AttributeSet attrs)
super(context, attrs);
public SquareImageView(Context context, AttributeSet attrs, int defStyle)
super(context, attrs, defStyle);
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
setMeasuredDimension(width, width);
现在,在您的 xml 中执行此操作,
<com.packagepath.tothis.SquareImageView
android:id="@+id/Imageview"
android:layout_
android:layout_ />
如果你需要一个 ImageView 不在程序中动态创建,而是在 xml 中固定,那么这个实现会很有帮助。
【讨论】:
太棒了,谢谢安德罗。这正是我想要的。再次感谢您花时间提供完整的答案。 这应该被标记为正确的、完整的解决方案。 另请参阅使用此技术的优秀教程:raywenderlich.com/…【参考方案3】:更简单:
public class SquareImageView extends ImageView
...
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
【讨论】:
不要忘记 sdk >= 21 @TargetApi(Build.VERSION_CODES.LOLLIPOP) public SquareImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) super(context, attrs, defStyleAttr, defStyleRes); 【参考方案4】:前面的几个答案已经足够了。我只是在这里为@Andro Selva 和@a.bertucci 的解决方案添加了一个小优化:
这是一个微小的优化,但检查宽度和高度是否不同可能会阻止另一次测量通过。
public class SquareImageView extends ImageView
public SquareImageView(Context context)
super(context);
public SquareImageView(Context context, AttributeSet attrs)
super(context, attrs);
public SquareImageView(Context context, AttributeSet attrs, int defStyle)
super(context, attrs, defStyle);
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
int width = getMeasuredWidth();
int height = getMeasuredHeight();
// Optimization so we don't measure twice unless we need to
if (width != height)
setMeasuredDimension(width, width);
【讨论】:
【参考方案5】:对于那些寻找 Kotlin 解决方案的人:
class SquareImageView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, defStyleRes: Int = 0
) : ImageView(context, attrs, defStyleAttr, defStyleRes)
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) = super.onMeasure(widthMeasureSpec, widthMeasureSpec)
【讨论】:
【参考方案6】:指定宽度的squareImageView:
public class SquareImageViewByWidth extends AppCompatImageView
public SquareImageViewByWidth(Context context)
super(context);
public SquareImageViewByWidth(Context context, AttributeSet attrs)
super(context, attrs);
public SquareImageViewByWidth(Context context, AttributeSet attrs, int defStyleAttr)
super(context, attrs, defStyleAttr);
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width= getMeasuredWidth();
setMeasuredDimension(width, width);
...
指定高度的squareImageView:
public class SquareImageViewByHeight extends AppCompatImageView
public SquareImageViewByHeight(Context context)
super(context);
public SquareImageViewByHeight(Context context, AttributeSet attrs)
super(context, attrs);
public SquareImageViewByHeight(Context context, AttributeSet attrs, int defStyleAttr)
super(context, attrs, defStyleAttr);
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int height = getMeasuredHeight();
setMeasuredDimension(height, height);
...
最小尺寸的 squareImageView:
public class SquareImageViewByMin extends AppCompatImageView
public SquareImageViewByHeight(Context context)
super(context);
public SquareImageViewByHeight(Context context, AttributeSet attrs)
super(context, attrs);
public SquareImageViewByHeight(Context context, AttributeSet attrs, int defStyleAttr)
super(context, attrs, defStyleAttr);
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int minSize = Math.min(width, height);
setMeasuredDimension(minSize, minSize);
...
【讨论】:
这个答案中AppCompatImageView
的使用很重要。【参考方案7】:
如果有人希望视图不是方形的,而是按比例调整高度(例如,16/9 或 1/3),您可以这样做:
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
heightMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth()/3, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
【讨论】:
【参考方案8】:单线解决方案-
layout.setMinimumHeight(layout.getWidth());
【讨论】:
【参考方案9】:Kotlin 的快速解决方案(Material.ShapeableImageView 可以改为 ImageView)
class SquareImageView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : ShapeableImageView(context, attrs, defStyleAttr)
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int)
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
setMeasuredDimension(measuredWidth, measuredWidth)
【讨论】:
【参考方案10】:这里都没有必要将其超类称为onMeasure
。这是我的实现
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int size = Math.min(width, height);
setMeasuredDimension(size, size);
【讨论】:
以上是关于ImageView 是动态宽度的正方形?的主要内容,如果未能解决你的问题,请参考以下文章