Determining the size of an Android view at runtime

前端 未结 12 1999
陌清茗
陌清茗 2020-11-22 09:59

I am trying to apply an animation to a view in my Android app after my activity is created. To do this, I need to determine the current size of the view, and then set up an

12条回答
  •  闹比i
    闹比i (楼主)
    2020-11-22 10:25

    There are actually multiple solutions, depending on the scenario:

    1. The safe method, will work just before drawing the view, after the layout phase has finished:
    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); 
    }
    

    Sample usage:

        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
            }
        });
    
    1. On some cases, it's enough to measure the size of the view manually:
    view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
    int width=view.getMeasuredWidth(); 
    int height=view.getMeasuredHeight();
    

    If you know the size of the container:

        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
    
    1. if you have a custom view that you've extended, you can get its size on the "onMeasure" method, but I think it works well only on some cases :
    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);
    }
    
    1. 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) :

    android {
        kotlinOptions {
            jvmTarget = "1.8"
        }
    }
    
    implementation 'androidx.core:core-ktx:#.#'
    

提交回复
热议问题