Reputation: 4503
I have a GridView with ImageViews inside. I have 3 of them for each row. I can set correctly the width with WRAP_CONTENT and scaleType = CENTER_CROP, but I don't know how to set the ImageView's size to be a square. Here's what I did until now, it seems to be ok except the height, that is "static":
imageView = new ImageView(context);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setLayoutParams(new GridView.LayoutParams(GridView.LayoutParams.WRAP_CONTENT, 300));
I'm doing it inside an adapter.
Upvotes: 76
Views: 55714
Reputation: 39
Fast solution for Kotlin (Material.ShapeableImageView can be changed to 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)
}
}
Upvotes: 0
Reputation: 746
Here all are unnecessary calling its superclass for onMeasure
. Here is my implementation
@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);
}
Upvotes: -1
Reputation: 2827
Single line solution -
layout.setMinimumHeight(layout.getWidth());
Upvotes: 0
Reputation: 3623
An squareImageView by specified width:
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);
}
...
}
An squareImageView by specified height:
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);
}
...
}
An squareImageView by minimum of dimentions:
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);
}
...
}
Upvotes: 3
Reputation: 1543
if someone wants the view to be not square, but proportionally resized in height (for example, 16/9 or 1/3), you can do it like this:
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth()/3, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
Upvotes: 1
Reputation: 879
For those looking for a Kotlin solution:
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)
}
Upvotes: 3
Reputation: 25876
Even more simple:
public class SquareImageView extends ImageView {
...
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
}
Upvotes: 27
Reputation: 1536
Several of the previous answers are perfectly sufficient. I'm just adding a small optimization to both @Andro Selva and @a.bertucci's solutions here:
It's a tiny optimization, but checking that the width and the height are different could prevent another measurement pass.
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);
}
}
}
Upvotes: 11
Reputation: 54330
The other answer works fine. This is just an extension of bertucci's solution to make an ImageView with square width and height with respect to xml inflated layout.
Create a class, say a SquareImageView extending ImageView like this,
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);
}
}
Now, in your xml do this,
<com.packagepath.tothis.SquareImageView
android:id="@+id/Imageview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
If you need an ImageView not to be dynamically created in program, instead, to be fixed in xml, then this implementation will be helpful.
Upvotes: 102
Reputation: 12142
The best option is to subclass ImageView
yourself, overriding the 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);
}
...
}
Upvotes: 170