Intereting Posts
Как записывать видео с определенной шириной и высотой на Android-устройстве samsung? Защелка (используется для ожидающего ответа на асинхронный режим) замораживает WebView (и пользовательский интерфейс) Как отправить csv / текстовый файл с телефона Android на принтер Wi-Fi? Воспроизведение звука при нажатии кнопки мыши Ошибка в памяти при размещении большого JSON (InputStream) в String Требуется ли NDK для хорошей производительности при разработке Android-игры? Параметры функции автозаполнения в Android Studio Модуль ядра HAX не установлен Как я могу использовать SensorManager.getOrientation для управления наклоном, например «My Paper Plane»? Наберите код USSD? Показывать alertDialog с помощью радиокнопками при нажатии списка listItem Передача данных между фрагментами в действие Когда появляется мягкая клавиатура, это делает поле EditText потерянным фокусом Android Facebook SDK – ошибки при импорте SDK Аутентификация пользователя, входящего в систему с FB на моем сервере, с помощью диспетчера учетных записей Android

Почему мой андроид не является квадратным?

Я создал собственное представление для отображения игрового поля для игры, которую я разрабатываю. Игровая площадка должна быть квадратной во все времена. Таким образом, и высота должна быть одинаковой. Я последовал этому руководству, чтобы добиться этого.

Я добавил следующий код к своему пользовательскому представлению:

@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = getMeasuredWidth(); int height = getMeasuredHeight(); int widthWithoutPadding = width - getPaddingLeft() - getPaddingRight(); int heigthWithoutPadding = height - getPaddingTop() - getPaddingBottom(); int maxWidth = (int) (heigthWithoutPadding * RATIO); int maxHeight = (int) (widthWithoutPadding / RATIO); if (widthWithoutPadding > maxWidth) { width = maxWidth + getPaddingLeft() + getPaddingRight(); } else { height = maxHeight + getPaddingTop() + getPaddingBottom(); } setMeasuredDimension(width, height); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Paint p = new Paint(); p.setStyle(Paint.Style.STROKE); p.setStrokeWidth(3); canvas.drawRect(0, 0, getMeasuredWidth() - 1, getMeasuredHeight() - 1, p); } 

Макет с моим пользовательским представлением выглядит следующим образом:

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <view android:layout_width="wrap_content" android:layout_height="wrap_content" class="com.peerkesoftware.nanograms.controls.GameBoard" android:id="@+id/view" android:background="@android:color/holo_purple"/> </RelativeLayout> 

Квадрат, который нарисован в методе onDraw, всегда является квадратом. Это прекрасно работает.

В макете я добавляю пользовательский вид и даю виду цвет фона. Когда я показываю его на устройстве в портретном режиме, все работает отлично, а цвет фона заполняет квадрат, который я рисую методом onDraw.

Когда я переключаю устройство в альбомный режим, квадрат все еще квадрат, но область цвета фона больше. Он имеет ту же высоту, но имеет большую ширину. Но я понятия не имею, почему. Методы getMeasuredWidth () и getMeasuredHeight () возвращают правильные значения. Как может быть, что вид еще больше, чем это?

Solutions Collecting From Web of "Почему мой андроид не является квадратным?"

По какой-то причине ваше представление не работает в RelativeLayout. Для измерения ориентации на местности заканчиваются следующие ограничения (на моем телефоне):

Width = MeasureSpec: ТОЧНО 404; Height = MeasureSpec: AT_MOST 388

Из-за этого фактическая ширина заканчивается разной, чем измеренная ширина (на моем телефоне измерено = 388, фактическое = 404). Вот почему вы видите фон, выходящий за пределы вашего прямоугольника. Вы можете проверить это самостоятельно, добавив некоторые записи в onDraw и onMeasure.

Кроме того, соблюдение режима измерения не помогает, измерение по-прежнему заканчивается тем же результатом, что и выше.

Решение заключается в использовании другого макета. LinearLayout и FrameLayout работали для меня. Также рекомендуется использовать фактический размер представления в onDraw, с getWidth () и getHeight ().

Если вам действительно нужен RelativeLayout, вы можете добавить дочерний элемент FrameLayout, чтобы сохранить ваше представление следующим образом:

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" > <view android:id="@+id/view" android:layout_width="wrap_content" android:layout_height="wrap_content" class="com.peerkesoftware.nanograms.controls.GameBoard" android:background="@android:color/holo_purple" /> </FrameLayout> </RelativeLayout> 

Подкласс ImageView и переопределить onMeasure и перейти к

 super.onMeasure(widthMeasureSpec, widthMeasureSpec); 

Весь класс:

 public class SquaredImageView extends ImageView { public SquaredImageView(Context context) { super(context); } public SquaredImageView(Context context, AttributeSet attrs) { super(context, attrs); } public SquaredImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, widthMeasureSpec); } } 

Изменить: я попытался с нормальным представлением

 public class CustomView extends View { public CustomView(Context context) { super(context); setBackgroundColor(Color.RED); } public CustomView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = getMeasuredWidth(); int heigth = getMeasuredHeight(); int dimen = (width > heigth) ? heigth : width; setMeasuredDimension(dimen, dimen); } } 

И TestActivity

 public class TestActivity extends Activity { protected void onCreate(android.os.Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new CustomView(this)); } } 

Он рисует квадратный красный прямоугольник на экране моего мобильного устройства

Это мой код, я использую этот код, и он работает нормально. Не является то, что вы ищете, но может дать вам идею. На основе моего требования высота изображения должна быть такой же длины, как и ширина.

 public class SquareImageView extends ImageView { private static final String TAG = "SquareImageView"; 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 public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){ super.onMeasure(widthMeasureSpec, heightMeasureSpec); //int h = this.getMeasuredHeight(); int w = this.getMeasuredWidth(); setMeasuredDimension(w, w); } } 

Определено в xml как:

 <com.something.widget.SquareImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/ivProfilePicture" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:layout_alignParentTop="true" android:adjustViewBounds="true" android:scaleType="fitXY" android:background="@drawable/bg_curve_white_2" android:contentDescription="@string/general_content_description" android:src="@drawable/ic_default_logo" android:layout_marginTop="@dimen/side_margin"/> 

И, наконец, во Фрагменте это что-то вроде:

 SquareImageView ivProfilePicture = (SquareImageView) view.findViewById(R.id.ivProfilePicture); 

Я не уверен, какое решение будет удовлетворять потребность, но код из учебника имеет фундаментальную проблему дизайна – он не интерпретирует параметры MeasureSpec onMeasure() правильно. Ответ в пояснительном пояснении onMeasure объясняет правильное перепредставление этих параметров.

Что происходит в этом примере, onMeasure() вызывается дважды для каждого вхождения чертежа для пользовательского представления.

Для первого вызова оба параметра MeasureSpecs определяют режим AT_MOST и дают начальные значения без учета полей и отступов. Таким образом, код из учебника законно делает ширину и высоту соответствовать.

Однако для второго вызова, содержащий RelativeLayout, учитывает поля и дополнения и передает MeasureSpec for Width с режимом EXACT , тогда как Height передается в режиме AT_MOST .

Для вертикального экрана это работает нормально, потому что Width была уменьшена по полям, а значение для высоты по-прежнему равно высоте экрана (также уменьшено по краям). Таким образом, во время второго кода звонка законно уменьшает высоту, чтобы соответствовать теперь – меньшая ширина, и все работает правильно.

Однако для горизонтальной ориентации экрана значение «Ширина» устанавливается на значение, определенное во время первого вызова, а Height уменьшается по краям. Когда код пытается установить Width в соответствии с Height , эта операция установки не работает должным образом, потому что режим Width EXACT . В результате свойства вида Width и MeasuredWidth заканчиваются разными значениями.

Есть несколько простых способов сделать код в вопросе работы: вы можете просто удалить вертикальные поля:

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/zero" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/zero" tools:context=".MainActivity" > 

Или, если поля важны, вы можете изменить содержание макета на абсолютное:

 <AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > 

В обоих случаях представляется целесообразным изменить реализацию onMeasure() для соблюдения режима EXACT (как минимум, для регистрации проблемы).

Ваш onMeasure() не является простым. Измените свой код следующим образом и установите match_parent как width & height в xml (на самом деле это не имеет значения)

 void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); int widthWithoutPadding = width - getPaddingLeft() - getPaddingRight(); int heigthWithoutPadding = height - getPaddingTop() - getPaddingBottom(); int maxWidth = (int) (heigthWithoutPadding * RATIO); int maxHeight = (int) (widthWithoutPadding / RATIO); if (widthWithoutPadding > maxWidth) { width = maxWidth + getPaddingLeft() + getPaddingRight(); } else { height = maxHeight + getPaddingTop() + getPaddingBottom(); } setMeasuredDimension(width, height); }