런타임시 Android보기 크기 결정
활동이 작성된 후 Android 앱의보기에 애니메이션을 적용하려고합니다. 이렇게하려면 뷰의 현재 크기를 확인한 다음 현재 크기에서 새 크기로 스케일링 할 애니메이션을 설정해야합니다. 보기는 사용자의 입력에 따라 다른 크기로 조정되므로이 부분은 런타임시 수행해야합니다. 내 레이아웃은 XML로 정의됩니다.
이것은 쉬운 작업처럼 보이며, 내 문제를 해결 한 것은 없지만 이것에 관한 많은 SO 질문이 있습니다. 아마도 나는 분명한 것을 놓치고 있습니다. 나는 다음과 같이 내 견해를 파악했다.
ImageView myView = (ImageView)getWindow().findViewById(R.id.MyViewID);
이 잘 작동하지만, 호출 할 때 getWidth()
, getHeight()
, getMeasuredWidth()
, getLayoutParams().width
, 등, 그들은 모두 0을 반환은 또한 전화를 수동으로 시도 measure()
를 호출 다음에보기에 getMeasuredWidth()
,하지만 아무 효과가 없습니다.
이 메소드를 호출하고 내 활동 onCreate()
및 의 디버거에서 객체를 검사하려고 했습니다 onPostCreate()
. 런타임에이 뷰의 정확한 치수를 어떻게 알 수 있습니까?
View에서 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(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); int width=view.getMeasuredWidth(); int height=view.getMeasuredHeight();
컨테이너의 크기를 알고있는 경우 :
val widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(maxWidth, View.MeasureSpec.AT_MOST)
val heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(maxHeight, View.MeasureSpec.AT_MOST)
view.measure(widthMeasureSpec, heightMeasureSpec)
val width=view.measuredWidth
val height=view.measuredHeight
- 확장 한 사용자 정의보기가있는 경우 "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); }
If you write in Kotlin, you can use the next function, which behind the scenes works exactly like
runJustBeforeBeingDrawn
that I've written:view.doOnPreDraw { actionToBeTriggered() }
Note that you need to add this to gradle (found via here) :
implementation 'androidx.core:core-ktx:#.#'
Are you calling getWidth()
before the view is actually laid out on the screen?
A common mistake made by new Android developers is to use the width and height of a view inside its constructor. When a view’s constructor is called, Android doesn’t know yet how big the view will be, so the sizes are set to zero. The real sizes are calculated during the layout stage, which occurs after construction but before anything is drawn. You can use the
onSizeChanged()
method to be notified of the values when they are known, or you can use thegetWidth()
andgetHeight()
methods later, such as in theonDraw()
method.
Based on @mbaird's advice, I found a workable solution by subclassing the ImageView
class and overriding onLayout()
. I then created an observer interface which my activity implemented and passed a reference to itself to the class, which allowed it to tell the activity when it was actually finished sizing.
I'm not 100% convinced that this is the best solution (hence my not marking this answer as correct just yet), but it does work and according to the documentation is the first time when one can find the actual size of a view.
Here is the code for getting the layout via overriding a view if API < 11 (API 11 includes the View.OnLayoutChangedListener feature):
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);
}
You can check this question. You can use the View
's post() method.
Use below code, it is give the size of view.
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
Log.e("WIDTH",""+view.getWidth());
Log.e("HEIGHT",""+view.getHeight());
}
This works for me in my 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);
I was also lost around getMeasuredWidth()
and getMeasuredHeight()
getHeight()
and getWidth()
for a long time.......... later i found that getting the view's width and height in onSizeChanged()
is the best way to do this........ you can dynamically get your CURRENT width and CURRENT height of your view by overriding the onSizeChanged(
) method.
might wanna take a look at this which has an elaborate code snippet. New Blog Post: how to get width and height dimensions of a customView (extends View) in Android http://syedrakibalhasan.blogspot.com/2011/02/how-to-get-width-and-height-dimensions.html
works perfekt for me:
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;
}
}
참고URL : https://stackoverflow.com/questions/3779173/determining-the-size-of-an-android-view-at-runtime
'programing tip' 카테고리의 다른 글
Node.js-생성자로 module.exports 사용 (0) | 2020.07.28 |
---|---|
XML이 아닌 코드에서 RelativeLayout 레이아웃 매개 변수를 설정하는 방법은 무엇입니까? (0) | 2020.07.28 |
최대 절전 모드의 경량 대안? (0) | 2020.07.28 |
C #에서 여러 열거 형 값을 어떻게 전달합니까? (0) | 2020.07.28 |
숭고한 텍스트 편집기에서 개요보기를 얻는 방법은 무엇입니까? (0) | 2020.07.28 |