安卓捏合缩放

49

我的布局包含了按钮、文本视图等元素。是否可以在我的布局中实现双指缩放功能?

7个回答

43

23
一旦链接失效,这个回答就毫无价值了。至少引用相关部分即可。 - Lukas Knuth
4
FYI,这个答案已经过时了。ScaleGestureDetector是Android的API 8及以上版本中用于捏合缩放的解决方案。请参考Emanuel的回答 - ToolmakerSteve

38

对于Android 2.2+(API level 8),您可以使用ScaleGestureDetector。

您需要一个成员:

private ScaleGestureDetector mScaleDetector;

在你的构造函数(或onCreate()函数)中添加:

mScaleDetector = new ScaleGestureDetector(context, new OnScaleGestureListener() {
    @Override
    public void onScaleEnd(ScaleGestureDetector detector) {
    }
    @Override
    public boolean onScaleBegin(ScaleGestureDetector detector) {
        return true;
    }
    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        Log.d(LOG_KEY, "zoom ongoing, scale: " + detector.getScaleFactor());
        return false;
    }
});

你需要重写 onTouchEvent 方法:

@Override
public boolean onTouchEvent(MotionEvent event) {
    mScaleDetector.onTouchEvent(event);
    return true;
}

如果您手动绘制View,则在onScale()中可能会将比例因子存储在成员变量中,然后调用invalidate()并在onDraw()中绘制时使用该比例因子。

否则,您可以直接在onScale()中修改字体大小或类似的内容。


1
请参阅Android文档-拖动和缩放以获取更多信息。特别注意示例代码,展示了如何将平移(滚动)与缩放(捏合缩放)结合使用。 - ToolmakerSteve

16

我使用这个教程,为我的TextView实现了一个捏合缩放功能。最终的代码如下:

private GestureDetector gestureDetector;
private View.OnTouchListener gestureListener;

并且在onCreate()方法中:

    // Zoom handlers
    gestureDetector = new GestureDetector(new MyGestureDetector());
    gestureListener = new View.OnTouchListener() {

        // We can be in one of these 2 states
        static final int NONE = 0;
        static final int ZOOM = 1;
        int mode = NONE;

        static final int MIN_FONT_SIZE = 10;
        static final int MAX_FONT_SIZE = 50;

        float oldDist = 1f;

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            TextView textView = (TextView) findViewById(R.id.text);

            switch (event.getAction() & MotionEvent.ACTION_MASK) {
                case MotionEvent.ACTION_POINTER_DOWN:
                    oldDist = spacing(event);
                    Log.d(TAG, "oldDist=" + oldDist);
                    if (oldDist > 10f) {
                       mode = ZOOM;
                       Log.d(TAG, "mode=ZOOM" );
                    }
                    break;
                case MotionEvent.ACTION_POINTER_UP:
                    mode = NONE;
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (mode == ZOOM) {
                        float newDist = spacing(event);
                        // If you want to tweak font scaling, this is the place to go.
                        if (newDist > 10f) {
                            float scale = newDist / oldDist;

                            if (scale > 1) {
                                scale = 1.1f;
                            } else if (scale < 1) {
                                scale = 0.95f;
                            }

                            float currentSize = textView.getTextSize() * scale;
                            if ((currentSize < MAX_FONT_SIZE && currentSize > MIN_FONT_SIZE)
                                    ||(currentSize >= MAX_FONT_SIZE && scale < 1)
                                    || (currentSize <= MIN_FONT_SIZE && scale > 1)) {
                                textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, currentSize);
                            }
                        }
                    }
                    break;
                }
            return false;
        }

经验法则选择了魔术常量1.1和0.95(使用scale变量可能会使我的TextView表现出奇怪的行为)。


5
当然,我可以翻译您的 MyGestureDetector() 类。 - Praveenkumar
1
@Renanlf 那已经是一年多以前的事了。抱歉,我甚至不再为Android编写代码了。我也没有那些资源。 - George
2
MyGestureDetector()在这里不相关;由于声明GestureDetector(GestureDetector.OnGestureListener listener),我们得出结论它是GestureDetector.OnGestureListener的误称子类。而该类检测到的事件与缩放无关。 - 18446744073709551615
在这行代码中:switch (event.getAction() & MotionEvent.ACTION_MASK),ACTION_MASK会变成255(ff),那么添加MotionEvent.ACTION_MASK的意义是什么?如果不添加MotionEvent.ACTION_MASK,switch (event.getAction())是否足够?如果不够,请解释一下。 - answer88
@folone 你能帮我解决这个问题吗?这个问题和我面临的情况类似。 - user3265443
代码似乎无法工作。MyGestureDetector未定义,代码中的其他内容也是如此,例如spacingTAG等。 - Alex

5

4

仅提供链接的答案变得毫无价值,因为链接可能会失效。尝试在回答中添加一些与链接无关的主要关键点。 - Sambhav Khandelwal

1
我创建了一个支持Android 2.1及以上版本基本pinch-zoom的项目。 此处可用。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接