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 ответов:
лучший вариант-подкласс
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); }