Youssef Maouche
Youssef Maouche

Reputation: 305

force layout to refresh/repaint android?

I want to change position of layout and after 75ms return it to first position to make a movement and that is my code:

for(int i = 0; i < l1.getChildCount(); i++) {  
    linear = (LinearLayout) findViewById(l1.getChildAt(i).getId());  
    LayoutParams params = new LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT);  
    params.bottomMargin = 10;  
    linear.setLayoutParams(params);  
    SystemClock.sleep(75);
}   

The problem is the app is stop for 750ms and don't do anything. I tried invalidate() , refreshDrawableState(), requestLayout(), postInvalidate(), and try to call onResume(), onRestart(), onPause() .

Upvotes: 7

Views: 32883

Answers (4)

Shihab Uddin
Shihab Uddin

Reputation: 6931

After several hours of testing, I found the solution about updating a view if you made operation with these views like adding children, visibility, rotation, etc.

We need to force update the view with the below methods.

linearSliderDots.post {
        // here linearSliderDots is a linear layout &
        // I made add & remove view option on runtime
        linearSliderDots.invalidate()
        linearSliderDots.requestLayout()
    }

Upvotes: 2

Roudi
Roudi

Reputation: 1319

You should try using an ValueAnimator (Or object animator), the below code is in kotlin but same logic would be applied for java:

val childCount = someView.childCount
    val animators = mutableListOf<ValueAnimator>()
    for (i in 0..childCount) {
        val child = (someView.getChildAt(i))
        val animator = ValueAnimator.ofInt(0, 75)
        animator.addUpdateListener {
            val curValue = it.animatedValue as Int
            (child.layoutParams as ViewGroup.MarginLayoutParams).bottomMargin = curValue
            child.requestLayout()
        }
        animator.duration = 75
        animator.startDelay = 75L * i
        animators.add(animator)
    }
    animators.forEach { animator ->
        animator.start()
    }

Basically you create a bunch of animators that have start delay proportionate to the number of children, so as soon as one animation ends, the new one starts

Upvotes: 0

Asif Alam
Asif Alam

Reputation: 69

ActivityName.this.runOnUiThread(new Runnable() {
    @Override
    public void run() {
        <code to change UI>
    }
});

Upvotes: -1

prc
prc

Reputation: 860

Maybe you need:

linear.invalidate();
linear.requestLayout();

after making the layout changes.

EDIT:

Run the code on a different thread:

new Thread() {
    @Override
    public void run() {
        <your code here>
    }
}.start();

And whenever you need to update the UI from that thread use:

activity.runOnUiThread(new Runnable() {
    @Override
    public void run() {
        <code to change UI>
    }
});

Upvotes: 22

Related Questions