Why does setScaleX call during hard zoom zoom cause flicker?

I am trying to create a scalable container and I am targeting API 14+

In my onScale (I use ScaleGestureDetector to detect scaling) I am doing something like this:

public boolean onScale (ScaleGestureDetector detector) { float scaleFactor = detector.getScaleFactor(); setScaleX(getScaleX() * scaleFactor); setScaleY(getScaleY() * scaleFactor); return true; }; 

This works, but the zoom is not smooth. In fact, it flickers markedly.

I also tried this with the hardware layer, thinking that scaling will happen on the GPU after the texture is loaded and therefore will be very fast. But it didn’t matter - the zoom is not smooth and sometimes flickers.

What am I doing wrong?

+6
performance android android-ui hardware-acceleration
source share
3 answers

Is there a flicker that looks like the image has flipped back and forth between magnified and not magnified? This is because the ScaleGestureDetector handles motion events from the same view that you are scaling. When you setScaleX() , which changes the coordinates of a touch, which triggers a new touch event, which is interpreted as a zoom, which you just applied.

Place the contents of your scalable view inside one child FrameLayout and set the scale on that view.

I posted a working scale-out scale layout here: https://gist.github.com/anorth/9845602

+3
source share

According to your question, the setScaleX and setScaleY flicker because they execute "drawing in the view" inside the context ( setScaleX and setScaleY belong to the View ). The documentation reads:

Option "a", a drawing for presentation, is your best bet when you want to draw simple graphics that don't need dynamic changes and are not part of a high-intensity game. For example, you should draw your graphics in a view when you want to display static graphics or predefined animations in a static application.

On the other hand, if you follow @ g00dy's answer, you will be doing β€œdrawing on canvas" ( scale() belongs to Canvas ) within the context. The documentation reads:

The "b" option, drawing on canvas, is better when your application needs to re-draw itself regularly. Applications such as video games must draw on Canvas themselves.

The heavy gesture is intense, so you need to execute it in option b ... so you should use @ g00dy's solution or any such approach.

Here is the documentation provided.

Hope this helps you.

0
source share

I ran into the same problem. Task:

  • create a canvas (in a subclass of View or SurfaceView, it doesn't matter)
  • draw some graphic and graphic primitives on it (using the drawBitmap (), drawLine () ... methods)
  • make the canvas scrollable and scalable

I suppose there is no need to show all class code here.

Solving the flickering problem during gesture gestures was very simple. Just enter the scaling procedure in the onScaleEnd () method.

 private class MyScaleGestureListener implements OnScaleGestureListener { public boolean onScale(ScaleGestureDetector detector) { scaleFactor *= detector.getScaleFactor(); // class variable of type float if (scaleFactor > 5) scaleFactor = 5; // some limitations if (scaleFactor < 1) scaleFactor = 1; return true; } public boolean onScaleBegin(ScaleGestureDetector detector) { return true;} public void onScaleEnd(ScaleGestureDetector detector) { setScaleX(scaleFactor); setScaleY(scaleFactor); invalidate(); // it seems to me - no effect } } 

Tested on a real device Samsung GALAXY S III mini.

0
source share

All Articles