Getmeasuredheight() и getmeasuredwidth() возвращает 0 после View.measure()
После измерения View
с постоянными размерами с view.measure()
, getMeasuredHeight()
и getMeasureWidth()
возвращает 0.
layout_view.xml, макет, который раздувается, чтобы создать представление
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="100dp"
android:layout_height="100dp">
</FrameLayout>
которая измеряет размеры
public void measureView(Context context){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.layout_view,null,false);
view.measure( View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
Log.d(TAG,"Error width : " + view.getMeasuredWidth());
Log.d(TAG,"Error heeght : " + view.getMeasuredHeight());
}
Ответы
Ответ 1
Когда вы вызываете view.getMeasuredWidth()
в onCreate()
или onCreateView()
, view
еще не нарисовано. Таким образом, вам нужно добавить слушателя и получить обратный вызов при view
представления. Как и в моем коде:
final ViewTreeObserver vto = view.getViewTreeObserver();
if (vto.isAlive()) {
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int viewWidth = view.getMeasuredWidth();
// handle viewWidth here...
if (Build.VERSION.SDK_INT < 16) {
vto.removeGlobalOnLayoutListener(this);
} else {
vto.removeOnGlobalLayoutListener(this);
}
}
});
}
ПРИМЕЧАНИЕ. Снимите прослушиватель для лучшей производительности!
Не вызывайте vto.removeOnGlobalLayoutListener(this)
чтобы удалить слушателя. Назовите это так:
vto.getViewTreeObserver()
Ответ 2
Вы измеряете представление в onCreate()
. Представление еще не нарисовано. Вы должны подождать до тех пор, пока изображение не будет нарисовано, прежде чем вы сможете его измерить.
Простое решение для этого - отправить runnable в макет. Запуск будет выполнен после того, как макет произошел.
Для получения дополнительной информации См. это сообщение
Edit
попробуйте изменить
view.measure( View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
к
view.measure( View.MeasureSpec.EXACTLY, View.MeasureSpec.EXACTLY);
Ответ 3
Попробуйте этот путь, надеюсь, что это поможет вам решить вашу проблему.
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
}
});
Ответ 4
если ваш измеренный вид имеет видимость, установленную для удаления, измерение вернет 0. Вы можете установить его на видимое, измерить, а затем вернуть обратно, все из кода.
Ответ 5
Вы не можете использовать View.MeasureSpec.*
Непосредственно в вызове measure
. Вместо этого сначала makeMeasureSpec()
а затем используйте его для вызова measure()
:
final int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(ViewGroup.LayoutParams.WRAP_CONTENT/*can be match_parent or some exact value*/, View.MeasureSpec.UNSPECIFIED);
final int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(ViewGroup.LayoutParams.WRAP_CONTENT/*can be match_parent or some exact value*/, View.MeasureSpec.UNSPECIFIED);
view.measure(widthMeasureSpec, heightMeasureSpec);
Ответ 6
На всякий случай кто-то сталкивался с этой проблемой с ImageView:
Я заметил, что если ваш ImageView не имеет набора "android: src" (т.е. вы меняете его динамически), он всегда будет возвращать ноль из getMeasuredWidth/Height.
Простым обходным решением было бы установить заполнитель для представления.
Ответ 7
Вы можете использовать getViewTreeObserver
в onCreate/onCreateView
и других событиях.
fun setGlobalLayoutListener(view: View, method: () -> Unit) {
val vto1 = view.viewTreeObserver
if (vto1.isAlive) {
vto1.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
val vto2 = view.viewTreeObserver
if (vto2.isAlive) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
vto2.removeOnGlobalLayoutListener(this)
} else {
@Suppress("DEPRECATION")
vto2.removeGlobalOnLayoutListener(this)
}
// Your actions are here:
method()
}
}
})
}
}
И назовите его: setGlobalLayoutListener(view) {updateUI(view)}
.
Я тоже пробовал
view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
и затем вызвал view.control.measuredWidth
в onCreateView()/onViewCreated()
. Но в некоторых эмуляторах (API 19) он дал неверные результаты.