ImageView是具有动态宽度的正方形吗?


73

我有一个带有ImageViews的GridView。我每行有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));

我正在适配器内做。

Answers:


170

最好的选择是继承ImageView自己的子类,覆盖度量传递:

public class SquareImageView  extends ImageView {

  ...

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    int width = getMeasuredWidth();
    setMeasuredDimension(width, width);
  }

  ...

}

1
太棒了!非常感谢您,我没有想到这种可能性
Andrea

如果我设置padding //页边距,则会得到一个白色边框。
Waza_Be

2
android:adjustViewBounds =“ true” android:scaleType =“ centerCrop” @Waza_Be
Kaloyan

2
难道不应该将其设置为min(width,height)吗?
Android开发人员

1
这是一个很小的优化,但是检查宽度和高度是否不同可以防止再次进行测量。@Override受保护的void onMeasure(int widthMeasureSpec,int heightMeasureSpec){super.onMeasure(widthMeasureSpec,heightMeasureSpec); int width = getMeasuredWidth(); int height = getMeasuredHeight(); //优化,因此除非需要if(width!= height){setMeasuredDimension(width,width); }}
Chantell Osejo 2015年

98

另一个答案很好。这只是bertucci解决方案的扩展,以使ImageView的宽度和高度相对于xml膨胀的布局为正方形。

创建一个类,说一个SquareImageView这样扩展ImageView,

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_width="fill_parent"
            android:layout_height="fill_parent" />

如果您需要不在程序中动态创建ImageView而不是在xml中进行固定,则此实现将很有帮助。


1
太好了,谢谢安德罗。这正是我想要的。再次感谢您抽出宝贵时间提供完整的答案。
塔里亚登

1
这应该标记为正确的完整解决方案。
JRod 2014年

26

更简单:

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); }
Jan Rabe'3

11

前面的几个答案就足够了。我在这里为@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);
        }
    }

}

3

对于那些寻找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)
}

3

指定宽度的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这个答案是重要的一点。
理查德·勒·马修里尔

1

如果有人希望视图不为正方形,而是按比例调整高度(例如16/9或1/3),则可以这样做:

@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    heightMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth()/3, MeasureSpec.AT_MOST);
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

0

单线解决方案-

layout.setMinimumHeight(layout.getWidth());

-1

这里所有不必要的调用其超类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);
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.