WebView getting rid of double tap zoom.

后端 未结 6 965
悲&欢浪女
悲&欢浪女 2020-12-19 03:18

I read many tickets on the topic of Zooming in WebViews and didnt came to an answer for my case.

Here´s my setup:

I´m using a custom webview with generally

6条回答
  •  没有蜡笔的小新
    2020-12-19 03:27

    Another approach (the only one that worked for me) would be to simulate distant intermediate taps between double taps so that the WebView doesn't recongnize them as consequent. Negative coordinates can be used for this purpose, although anything less than -1 would slow down or even break the process. So we need at least two points, say (0, -1) and (2*d+1, -1) where d is the maximum distance between taps for them to be considered double tap.

    webView.setOnTouchListener(new View.OnTouchListener() {
            private long lastUp = -1000;
            private float lastDownX = -1000;
            private float lastDownY = -1000;
            private int dtDistance = 0;         
            private int dtDistanceSquared = 0;
            private long dtTime = 0;
    
            private void performTap(View v, int x, int y, long t) {             
                MotionEvent e_down = MotionEvent.obtain(t, t, MotionEvent.ACTION_DOWN, x, y, 0);
                v.dispatchTouchEvent(e_down);
                e_down.recycle();
    
                MotionEvent e_up = MotionEvent.obtain(t, t, MotionEvent.ACTION_UP, x, y, 0);
                v.dispatchTouchEvent(e_up);
                e_up.recycle();
            }
    
            private int getRemoteX(float x) {
                return Math.round(x > dtDistance + 0.5 ? 0 : 2 * dtDistance + 1);
            }
    
            private boolean inRadius(int x0, int y0, float x1, float y1) {
                boolean result = (x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1) <= dtDistanceSquared;
                return result;
            }
    
            @Override
            public boolean onTouch(View v, MotionEvent event) { 
                if (event.getY() >= 0)  // Otherwise it's a fake tap we simulated
                {               
                    if (dtTime == 0)
                    {
                        dtDistance = ViewConfiguration.get(v.getContext()).getScaledDoubleTapSlop();    // Maximum distance between taps for them to be considered double tap
                        dtDistanceSquared = dtDistance * dtDistance;
                        dtTime = ViewConfiguration.getDoubleTapTimeout();   // Maximum time elapsed between taps for them to be considered double tap
                    }
    
                    switch (event.getAction())
                    {
                        case MotionEvent.ACTION_UP:
                            lastUp = event.getEventTime();
                            break;
                        case MotionEvent.ACTION_DOWN:
                            long t = event.getEventTime(); 
                            if (t - lastUp < dtTime * 4/3)  // Very rarely just (t - lastUp <= dtTime) doesn't work
                            {
                                int x = getRemoteX(event.getX());
                                if (inRadius(x, -1, lastDownX, lastDownY))
                                    performTap(v, getRemoteX(lastDownX), -1, t);    // Otherwise our fake tap would constitute a double tap with the previous real tap
                                performTap(v, x, -1, t);                                
                            }
                            lastDownX = event.getX();
                            lastDownY = event.getY();
                            break;                      
                    }
                }
    
                return false;                                   
            }
        });
    

提交回复
热议问题