ImageView-это квадрат с динамической шириной?


У меня есть 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));

Я делаю это внутри адаптера.

8 64

8 ответов:

лучший вариант-подкласс ImageView самостоятельно, заменив измерения:

public class SquareImageView  extends ImageView {

  ...

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

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

  ...

}

другой ответ работает нормально. Это просто расширение решения bertucci, чтобы сделать ImageView с квадратной шириной и высотой по отношению к xml-раздутому макету.

создать класс, сказать 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_width="fill_parent"
            android:layout_height="fill_parent" />

Если вам нужно, чтобы ImageView не создавался динамически в программе, а был исправлен в xml, то эта реализация будет полезна.

еще проще:

public class SquareImageView extends ImageView {
    ...
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, widthMeasureSpec);
    }    
}

нескольких предыдущих ответов вполне достаточно. Я просто добавляю небольшую оптимизацию к решениям @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);
        }
    }

}

для тех, кто ищет решение Котлин:

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)
}

если кто-то хочет, чтобы вид был не квадратным, а пропорционально изменен по высоте (например, 16/9 или 1/3), вы можете сделать это следующим образом:

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

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 widthMeasureSpec) {
        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);
        }

       ...
    }

здесь все ненужные вызовы своего суперкласса для 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);
    }