Я создаю все элементы в моем проекте Android динамически. Я пытаюсь получить ширину и высоту кнопки, чтобы я мог вращать эту кнопку вокруг. Я просто пытаюсь научиться работать с языком Android. Тем не менее, он возвращает 0.
Я провел некоторое исследование и понял, что это нужно сделать где-то, кроме onCreate()
метода. Если кто-то может дать мне пример того, как это сделать, это было бы здорово.
Вот мой текущий код:
package com.animation;
import android.app.Activity;
import android.os.Bundle;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.Button;
import android.widget.LinearLayout;
public class AnimateScreen extends Activity {
//Called when the activity is first created.
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout ll = new LinearLayout(this);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(30, 20, 30, 0);
Button bt = new Button(this);
bt.setText(String.valueOf(bt.getWidth()));
RotateAnimation ra = new RotateAnimation(0,360,bt.getWidth() / 2,bt.getHeight() / 2);
ra.setDuration(3000L);
ra.setRepeatMode(Animation.RESTART);
ra.setRepeatCount(Animation.INFINITE);
ra.setInterpolator(new LinearInterpolator());
bt.startAnimation(ra);
ll.addView(bt,layoutParams);
setContentView(ll);
}
Любая помощь приветствуется.
источник
Основная проблема заключается в том, что вам нужно дождаться фазы рисования для фактических измерений (особенно с динамическими значениями, такими как
wrap_content
илиmatch_parent
), но обычно эта фаза не завершенаonResume()
. Так что вам нужен обходной путь для ожидания этого этапа. Существуют различные возможные решения этого:1. Прослушивание событий Draw / Layout: ViewTreeObserver
ViewTreeObserver запускается для различных событий рисования. Обычно
OnGlobalLayoutListener
это то, что вы хотите получить для измерения, поэтому код в слушателе будет вызываться после фазы компоновки, поэтому измерения готовы:Примечание. Слушатель будет немедленно удален, поскольку в противном случае он будет срабатывать при каждом событии макета. Если вам нужно поддерживать приложения SDK Lvl <16, используйте это, чтобы отменить регистрацию слушателя:
public void removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim)
2. Добавьте исполняемый файл в очередь макетов: View.post ()
Не очень известное и мое любимое решение. По сути, просто используйте метод post представления View с вашим собственным runnable. Это в основном ставит ваш код в очередь после измерения представления, макета и т. Д., Как заявлено Romain Guy :
Пример:
Преимущество перед
ViewTreeObserver
:Ссылки:
3. Перезаписать метод onLayout в представлениях
Это практично только в определенных ситуациях, когда логика может быть заключена в самом представлении, в противном случае это довольно многословный и громоздкий синтаксис.
Также учтите, что onLayout будет вызываться много раз, поэтому будьте внимательны, что вы делаете в методе, или отключите свой код после первого раза.
4. Проверьте, прошел ли этап макета
Если у вас есть код, который выполняется несколько раз при создании пользовательского интерфейса, вы можете использовать следующий метод поддержки v4 lib:
Дополнительно: получение статически определенных измерений
Если достаточно просто получить статически определенную высоту / ширину, вы можете сделать это с помощью:
View.getMeasuredWidth()
View.getMeasuredHeigth()
Но учтите, что это может отличаться от фактической ширины / высоты после рисования. Javadoc отлично описывает разницу:
источник
runOnUiThread(new Runnable() {...}
. В настоящее время я использую изменение 1 - го метода:addOnLayoutChangeListener
. Не забудьте затем удалить его изнутри: removeOnLayoutChangeListener. Это работает из фоновой темы, а также.android:visibility="gone"
, а в другом проекте свойство видимости былоinvisible
. Если видимость будетgone
ширина, то всегда будет 0.Мы можем использовать
источник
Я использовал это решение, которое я считаю лучше, чем onWindowFocusChanged (). Если вы откроете DialogFragment, а затем поверните телефон, onWindowFocusChanged будет вызываться только тогда, когда пользователь закрывает диалоговое окно):
Изменить: так как removeGlobalOnLayoutListener устарела, теперь вы должны сделать:
источник
Как утверждает Ян в этой теме для разработчиков Android :
источник
Bottom line, if you call getWidth() etc. in a constructor, it will return zero.
это бинго Корень моих проблем.Если вам нужно получить ширину какого-либо виджета до его отображения на экране, вы можете использовать getMeasuredWidth () или getMeasuredHeight ().
источник
Я бы предпочел использовать
OnPreDrawListener()
вместоaddOnGlobalLayoutListener()
, так как он вызывается немного раньше, чем другие слушатели.источник
return false
средства для отмены текущего чертежа пасса . Чтобы продолжить,return true
вместо этого.Расширение Kotlin для наблюдения за глобальным макетом и выполнения заданной задачи, когда высота готова динамически.
Применение:
Реализация:
источник
AndroidX имеет несколько функций расширения, которые помогут вам с такой работой, внутри
androidx.core.view
Вы должны использовать Kotlin для этого.
То, что лучше всего подходит здесь
doOnLayout
:В вашем примере:
Зависимость:
androidx.core:core-ktx:1.0.0
источник
Один лайнер, если вы используете RxJava & RxBindings . Подобный подход без шаблонного. Это также решает проблему с подавлением предупреждений, как в ответе Тима Аутина .
Это оно. Не нужно отписываться, даже если никогда не звонил.
источник
Это происходит потому, что для представления нужно больше времени надувать. Таким образом, вместо вызова
view.width
иview.height
в главном потоке, вы должны использовать,view.post { ... }
чтобы убедиться, что вашview
уже раздули. В Котлине:В Java вы также можете позвонить
getWidth()
иgetHeight()
методы вRunnable
и передатьRunnable
вview.post()
метод.источник
.post
не гарантирует, что представление будет размечено.Высота и ширина равны нулю, поскольку представление не было создано к тому времени, когда вы запрашиваете его высоту и ширину. Одним из самых простых решений является
Этот метод хорош по сравнению с другими методами, поскольку он короткий и четкий.
источник
Может быть, это кому-то поможет
Создать функцию расширения для класса View
Это может быть использовано в любом представлении с:
источник
post
Неверный ответ , потому что размер не может быть пересчитан.Еще одна важная вещь заключается в том, что вид и все его предки должны быть видны . Для этого я использую свойство
View.isShown
.Вот моя функция kotlin, которую можно разместить где-нибудь в утилитах:
И использование это:
источник
Если вы используете Kotlin
источник
Прошедшие просмотры возвращают 0 как высоту, если приложение в фоновом режиме. Это мой код (1оо% работает)
источник
Нужно дождаться, когда вид будет нарисован. Для этого используйте OnPreDrawListener. Пример Kotlin:
источник