tomwyr
tomwyr

Reputation: 1409

Resizing Views before drawing

In my layout I have a GridView containing 4 custom ImageViews. I'm setting GridView's visibility to invisible until all ImageViews are resized at first but when the GridView is shown, there's a short blink with ImageViews still unchanged.

blink for a split second

views are resized in a moment

Each ImageView creates separate listener in order to scale its size:

//Setting new params as half of parent's size and increasing counter  

if (getViewTreeObserver().isAlive()) {
        final ViewTreeObserver viewTreeObserver = getViewTreeObserver();
        viewTreeObserver.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
        @Override
        public boolean onPreDraw() {
            getViewTreeObserver().removeOnPreDrawListener(this);

            View parent = (View) getParent();
            int dimension = Math.min(parent.getWidth(), parent.getHeight()) / 2;
            mThisImageView.setLayoutParams(new AbsListView.LayoutParams(dimension, dimension));
            ResizeCounter.setCounter(ResizeCounter.getCounter() + 1);

            return true;
        }
    });
}
//Activity listens to the moment when all ImageViews have been resized  

ResizeCounter.addCounterListener(new OnResizeCounterChangeListener() {
    @Override
    public void onResizeCounterChanged() {
        if (ResizeCounter.getCounter() == 4) {
            mAnswerGridView.setVisibility(View.VISIBLE);
        }
    }
});

I've also tried to resize them in onGlobalLayout method (same result) and to override onMeasure method (parent View is still null at this point).
I suspect that it's too late to change views in onPreDraw() but is there a method that can be called earlier inside which I can be sure that all views have been measured?

Upvotes: 0

Views: 173

Answers (2)

tomwyr
tomwyr

Reputation: 1409

I've created a handler that schedules setting visibility right after calling requestLayout.
Works well in this case.

ResizeCounter.addCounterListener(new OnResizeCounterChangeListener() {
    @Override
    public void onResizeCounterChanged() {
        if (ResizeCounter.getCounter() == 4) {
            mAnswerGridView.requestLayout();

            Handler handler = new Handler();
            handler.post(new Runnable() {
                @Override
                public void run() {
                    mAnswerGridView.setVisibility(View.VISIBLE);
                }
            });
        }
    }
});

Upvotes: 1

John
John

Reputation: 1314

Try to call mAnswerGridView.requestLayout() before mAnswerGridView.setVisibility(View.VISIBLE);

This may not work because as it's stated at Android Developers

This will schedule a layout pass of the view tree.

So you may better force relayout:

relayoutChildren(View view) {
view.measure(
    View.MeasureSpec.makeMeasureSpec(view.getMeasuredWidth(), View.MeasureSpec.EXACTLY),
    View.MeasureSpec.makeMeasureSpec(view.getMeasuredHeight(), View.MeasureSpec.EXACTLY));
view.layout(view.getLeft(), view.getTop(), view.getRight(), view.getBottom()); }

Upvotes: 1

Related Questions