8

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

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

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

   return true;
};

它可以工作,但缩放不流畅。事实上,它明显闪烁。

我还尝试了硬件层,认为一旦纹理上传,缩放就会在 GPU 上发生,因此会非常快。但这并没有什么不同——变焦不平滑,有时会奇怪地闪烁。

我究竟做错了什么?

4

3 回答 3

8

闪烁是否看起来像在缩放和未缩放之间来回翻转的视图?这是由于ScaleGestureDetector从您正在缩放的​​同一视图中处理运动事件引起的。当您setScaleX()更改触摸的坐标时,会触发一个新的触摸事件,该事件被解释为反转您刚刚应用的缩放。

将可缩放视图的内容放在单个子视图中FrameLayout,然后在该视图上设置比例。

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

于 2014-03-29T00:07:01.130 回答
0

According with your question, the methods setScaleX and setScaleY flicker because they perform inside the "drawing to a View" context (setScaleX and setScaleY belong to View). Documentation says:

Option "a," drawing to a View, is your best choice when you want to draw simple graphics that do not need to change dynamically and are not part of a performance-intensive game. For example, you should draw your graphics into a View when you want to display a static graphic or predefined animation, within an otherwise static application.

On the other hand, if you follow the @g00dy answer, you will be performing inside the "drawing to a Canvas" context (scale() belongs to Canvas). Documentation says:

Option "b," drawing to a Canvas, is better when your application needs to regularly re-draw itself. Applications such as video games should be drawing to the Canvas on its own.

A pinch gesture is intensive, so it needs to be performed in Option b... so you should use the @g00dy solution or any approach like that.

Here is the documentation cited.

I hope it helps you.

于 2013-07-05T23:40:26.273 回答
0

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

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

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

缩放手势期间闪烁问题的解决方案非常简单。只需将缩放过程放入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。

于 2014-09-27T20:53:20.153 回答