Определение размера представления Android во время выполнения
Я пытаюсь применить анимацию к представлению в моем приложении для Android после создания моей активности. Для этого мне нужно определить текущий размер представления, а затем настроить анимацию для масштабирования от текущего размера до нового размера. Эта часть должна быть выполнена во время выполнения, так как вид масштабируется до разных размеров в зависимости от ввода от пользователя. Мой макет определен в XML.
это кажется легкой задачей, и есть много так вопросов относительно этого, хотя никто что, очевидно, решило мою проблему. Так что, возможно, я упускаю что-то очевидное. Я получаю ручку к моему взгляду:
ImageView myView = (ImageView)getWindow().findViewById(R.id.MyViewID);
это работает нормально, но при вызове getWidth(),getHeight(),getMeasuredWidth(),getLayoutParams().width и т. д. все они возвращают 0. Я также попытался вручную позвонить measure() на вид с последующим вызовом getMeasuredWidth(), но это не имеет никакого эффекта.
Я попытался вызвать эти методы и проверить объект в отладчике в моей деятельности onCreate() и onPostCreate(). Как может Я выясняю точные размеры этого представления во время выполнения?
10 ответов:
используйте ViewTreeObserver на представлении, чтобы дождаться первого макета. Только после того, как первый макет будет getWidth()/getHeight()/getMeasuredWidth()/getMeasuredHeight() работы.
ViewTreeObserver viewTreeObserver = view.getViewTreeObserver(); if (viewTreeObserver.isAlive()) { viewTreeObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { view.getViewTreeObserver().removeOnGlobalLayoutListener(this); viewWidth = view.getWidth(); viewHeight = view.getHeight(); } }); }
Существует несколько решений, в зависимости от сценария:
- безопасный метод, будет работать непосредственно перед рисованием Вида, после завершения этапа компоновки:
public static void runJustBeforeBeingDrawn(final View view, final Runnable runnable) { final OnPreDrawListener preDrawListener = new OnPreDrawListener() { @Override public boolean onPreDraw() { view.getViewTreeObserver().removeOnPreDrawListener(this); runnable.run(); return true; } }; view.getViewTreeObserver().addOnPreDrawListener(preDrawListener); }пример использования:
ViewUtil.runJustBeforeBeingDrawn(yourView, new Runnable() { @Override public void run() { //Here you can safely get the view size (use "getWidth" and "getHeight"), and do whatever you wish with it } });
- в некоторых случаях, достаточно измерить размер вручную:
view.measure(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT); int width=view.getMeasuredWidth(); int height=view.getMeasuredHeight();
- если у вас есть пользовательский вид, который вы расширили, вы можете получите его размер по методу "onMeasure", но я думаю, что он хорошо работает только в некоторых случаях:
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { final int newHeight= MeasureSpec.getSize(heightMeasureSpec); final int newWidth= MeasureSpec.getSize(widthMeasureSpec); super.onMeasure(widthMeasureSpec, heightMeasureSpec); }
если вы пишете в Kotlin, вы можете использовать следующую функцию, которая за кулисами работает точно так же, как
runJustBeforeBeingDrawnчто я написал:view.doOnPreDraw { actionToBeTriggered() }обратите внимание, что вам нужно добавить это в gradle (найдено через здесь):
implementation 'androidx.core:core-ktx:#.#'
ты называешь
getWidth()прежде чем вид на самом деле выложен на экране?распространенной ошибкой новых разработчиков Android является использование ширины и высота вида внутри его конструктора. Когда представление конструктор называется, Android еще не знает, насколько большой вид будет быть, поэтому размеры установлены на ноль. Реальные размеры рассчитываются во время этап компоновки, который происходит после строительства, но перед чем-либо почерпнутый. Вы можете использовать
onSizeChanged()метод уведомления значения, когда они известны, или вы можете использоватьgetWidth()иgetHeight()методы позже, например вonDraw()метод.
на основе рекомендаций @mbaird, я нашел приемлемое решение путем создания подклассов
ImageViewкласса и переопределениеonLayout(). Затем я создал интерфейс наблюдателя, который моя активность реализовала и передала ссылку на себя классу, что позволило ему сообщить активность, когда она была фактически завершена.Я не на 100% убежден, что это лучшее решение (поэтому я пока не отмечаю этот ответ как правильный), но он работает и согласно документации первый раз, когда можно найти фактический размер представления.
вот код для получения макета путем переопределения представления, если API
public class CustomListView extends ListView { private OnLayoutChangedListener layoutChangedListener; public CustomListView(Context context) { super(context); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { if (layoutChangedListener != null) { layoutChangedListener.onLayout(changed, l, t, r, b); } super.onLayout(changed, l, t, r, b); } public void setLayoutChangedListener( OnLayoutChangedListener layoutChangedListener) { this.layoutChangedListener = layoutChangedListener; } } public interface OnLayoutChangedListener { void onLayout(boolean changed, int l, int t, int r, int b); }
вы можете проверить этот вопрос. Вы можете использовать
View' s post () метод.
это работает для меня в моем
onClickListener:yourView.postDelayed(new Runnable() { @Override public void run() { yourView.invalidate(); System.out.println("Height yourView: " + yourView.getHeight()); System.out.println("Width yourView: " + yourView.getWidth()); } }, 1);
Я тоже потерялся вокруг
getMeasuredWidth()иgetMeasuredHeight()getHeight()иgetWidth()в течение длительного времени.......... позже я обнаружил, что получение ширины и высоты вonSizeChanged()это лучший способ, чтобы сделать это........ вы можете динамически получить текущую ширину и текущую высоту вашего представления, переопределивonSizeChanged() метод.возможно, вы захотите взглянуть на это, у которого есть сложный фрагмент кода. Новое сообщение в блоге: Как получить размеры ширины и высоты customView (extends View) в Android http://syedrakibalhasan.blogspot.com/2011/02/how-to-get-width-and-height-dimensions.html
используйте ниже код, это дает размер представления.
@Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); Log.e("WIDTH",""+view.getWidth()); Log.e("HEIGHT",""+view.getHeight()); }
работает perfekt для меня:
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) { base.OnElementPropertyChanged(sender, e); CTEditor ctEdit = Element as CTEditor; if (ctEdit == null) return; if (e.PropertyName == "Text") { double xHeight = Element.Height; double aHaight = Control.Height; double height; Control.Measure(LayoutParams.MatchParent,LayoutParams.WrapContent); height = Control.MeasuredHeight; height = xHeight / aHaight * height; if (Element.HeightRequest != height) Element.HeightRequest = height; } }
Comments