为什么在缩放缩放手势期间调用setScaleX会导致闪烁?

时间:2013-06-30 22:59:53

标签: android performance android-ui hardware-acceleration

我正在尝试创建一个可缩放的容器,我的目标是API 14 +

在我的onScale中(我使用ScaleGestureDetector来检测捏缩放)我正在做这样的事情:

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

   return true;
};

它可以工作,但变焦不平滑。事实上,它明显闪烁。

我也尝试过硬件层认为一旦纹理上传就会在GPU上进行缩放,因此速度非常快。但它并没有什么区别 - 变焦不是很平滑,有时候也很奇怪。

我做错了什么?

3 个答案:

答案 0 :(得分:5)

闪烁是否看起来像视图在缩放和未缩放之间来回翻转?这是因为ScaleGestureDetector处理来自同一视图的setScaleX()处理动作事件而导致的。当你FrameLayout改变触摸的坐标时,会触发一个新的触摸事件,被解释为反转刚刚应用的缩放。

将可缩放视图的内容放在单个子{{1}}中,然后在该视图上设置缩放。

我在这里发布了一个工作的缩放缩放布局:https://gist.github.com/anorth/9845602

答案 1 :(得分:0)

根据您的问题,方法setScaleXsetScaleY会闪烁,因为它们会在"绘制到视图"内部执行。上下文(setScaleXsetScaleY属于View)。文档说:

  

选项" a,"当您想要绘制不需要动态更改且不属于性能密集型游戏的简单图形时,绘制到视图是最佳选择。例如,如果要在静态应用程序中显示静态图形或预定义动画,则应将图形绘制到视图中。

另一方面,如果你按照@ g00dy的答案,你将在"绘制到画布"上下文(scale()属于Canvas)。文档说:

  

选项" b,"当您的应用程序需要定期重新绘制自己时,绘制到Canvas会更好。视频游戏等应用程序应该自行绘制到Canvas。

捏合手势很密集,因此需要在选项b 中执行...所以你应该使用@ g00dy解决方案或任何类似的方法。

Here是引用的文档。

我希望它可以帮到你。

答案 2 :(得分:0)

我遇到了同样的问题。任务是:

  • 创建画布(在View或SurfaceView的子类中,无关紧要)
  • 在其上绘制一些图片和图形基元(使用方法drawBitmap(),drawLine()...)
  • 使画布可滚动和可伸缩

我想,不需要在这里显示所有类代码。

在scalling手势期间闪烁问题的解决方案非常简单。 只需将缩放过程放入 onScaleEnd()方法。

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
     }
} 

在真实设备上测试三星GALAXY S III mini。