How can I draw an animated view in Android?

I created a custom view from scratch. Extended View and overridden onDraw() . When a view animation occurs, I generate a custom animation using offsets. eg.

 while(!isOnTop){ mOffset++; //draw the component aa it higher using the offset if(position == 0) isOnTop==true; invalidate(); } 

The thought that my frames come from invalidity. The problem is that the invalidity of this view can only happen by scrolling through the list on the same screen.

This "shared invalidation ()" causes lagging behind my animation. So is there a way out of this delay?

Do you have any other suggestion for animation in this general environment? Creating animations using a separate thread that calculates the offset also requires forced invalidation () calls to display the animation (correct me if I'm wrong).

Is the only solution to perform animation, for example, for 10 invalidation requests with a large step? This will ease the lag, but I think I can use a different approach.

+8
android android-layout android-canvas android-view
source share
2 answers

“Which is better,” of course, depends heavily on what you are trying to do. You did not say what you are trying to achieve, so we can only guess what might be best for you.

Here are some simple things:

This simply repeats invalidate using the Handler:

 long mAnimStartTime; Handler mHandler = new Handler(); Runnable mTick = new Runnable() { public void run() { invalidate(); mHandler.postDelayed(this, 20); // 20ms == 60fps } } void startAnimation() { mAnimStartTime = SystemClock.uptimeMillis(); mHandler.removeCallbacks(mTick); mHandler.post(mTick); } void stopAnimation() { mHandler.removeCallbacks(mTick); } 
+23
source share

Since this question is of some interest, I will answer.

The best way to do this is to create a separate canvas stream. A “stand-alone” canvas can only be achieved with SurfaceView . LunarLanding is a great example of this use. Each frame is calculated separately than the main view, dividing only the processor time, and not the drawing time. Therefore, faster, even with a combination, for example, from the usual view at the top and animating view below.

But you must set the interval if you are in this shared environment. This interval is used for the FPS cover. If you do not install the FPS cap, then the CPU will operate flawlessly to get good animation for the SurfaceView if it were one. Capping it at a speed of 60 frames per second or less will do the trick to efficiently use all the views without overloading the CPU.

So, look at the Moon Landing drawing drawing from the API demos and set the FPS cap.

 private long timeNow; private long timeDelta; private long timePrevFrame; private void capFps(int fps) { timeNow = System.currentTimeMillis(); timeDelta = timeNow - timePrevFrame; try { 

// ps you can always set 16 instead of 1000 / fps for 60FPS to avoid calculating every time

 Thread.sleep((1000 / fps) - timeDelta); } catch (InterruptedException e) { } timePrevFrame = System.currentTimeMillis(); } 

and then the drawing thread will look something like this:

 @Override public void run() { Canvas c; while (run) { c = null; sleepFps(60, false); try { synchronized (surfaceHolder) { c = surfaceHolder.lockCanvas(null); widgetView.doDraw(c); } } finally { if (c != null) { surfaceHolder.unlockCanvasAndPost(c); } } } } 
+4
source share

All Articles