Пользовательский квадрат LinearLayout. Как?
Я создаю свой собственный класс для квадратного макета:
public class SquareLayout extends LinearLayout{
public SquareLayout(Context context) {
super(context);
}
public SquareLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public SquareLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int size = width > height ? height : width;
setMeasuredDimension(size, size);
}
Затем в моем xml:
...
<com.myApp.SquareLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center_horizontal"
android:orientation="horizontal" >
<ImageView
android:id="@+id/cellImageView"
android:adjustViewBounds="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:padding="2dp"
android:scaleType="centerCrop"
android:src="@drawable/image" />
</com.myApp.SquareLayout>
...
В моем java-коде ничего больше не написано.
Но вместо этого, если мой макет и мое изображение, я вижу только белый прямоугольник...
Что я не так?
Ответы
Ответ 1
//вы забыли вызвать super.onMeasure(widthMeasureSpec, widthMeasureSpec);
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int size = width > height ? height : width;
setMeasuredDimension(size, size);
}
//xml файл
<com.example.testapplication.SquareLayout
android:id="@+id/layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center_horizontal"
android:orientation="horizontal" >
<ImageView
android:id="@+id/cellImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:adjustViewBounds="true"
android:padding="2dp"
android:scaleType="centerCrop"
android:src="@drawable/ic_launcher" />
</com.example.testapplication.SquareLayout>
Ответ 2
У меня возникли проблемы с вызовом setMeasuredDimension
непосредственно при применении той же методики к RelativeLayout. Я не смог правильно выровнять нижний край. Вместо этого переключитесь на super.onMeasure()
с новой меткой spec, которая работает лучше.
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int size = Math.min(width, height);
super.onMeasure(MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY));
}
Ответ 3
Edit:
Решение ниже устарело, поскольку ConstraintLayout стал новым стандартом и предоставляет эту функциональность.
Исходный ответ:
Оказывается, команда Android дала нам решение, но об этом никто не знает! Проверьте эти два класса из Процентная поддержка библиотеки:
Если вы хотите навязать соотношение вида, вы должны поместить его в один из этих макетов. Поэтому в этом случае вы должны поместить стандартный LinearLayout
, а не ваш подкласс, в один из этих макетов с правильным соотношением сторон. Пример, если вы хотите использовать PercentFrameLayout
:
<android.support.percent.PercentFrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_aspectRatio="100%">
<!-- Whatever subviews you want here -->
</LinearLayout>
</android.support.percent.PercentFrameLayout>
И там вы идете, все ваши взгляды будут содержаться в квадратной линейной
макет!
не забудьте добавить зависимость gradle compile 'com.android.support:percent:23.3.0'
Откорректировать номер версии по мере необходимости