【问题标题】:How to detect a swipe gesture on webview如何在 webview 上检测滑动手势
【发布时间】:2012-09-25 08:22:26
【问题描述】:

我正在开发一个简单的 android 应用程序,其中包含 RelativeLayoutWebView

我必须检测仅在屏幕左侧 20% 的区域从下到上滑动。因此,当用户在该空间中从下到上滑动时,我必须显示一个自定义对话框。

我尝试的是:

import android.app.Activity;
import android.view.MotionEvent;
import android.view.View;

public class ActivitySwipeDetector implements View.OnTouchListener {

    static final String logTag = "ActivitySwipeDetector";
    private Activity activity;
    static final int MIN_DISTANCE = 100;
    private float downY, upY;

    public ActivitySwipeDetector(Activity activity){
        this.activity = activity;
    }

    public void onRightToLeftSwipe(){

    }

    public void onLeftToRightSwipe(){

    }

    public void onTopToBottomSwipe(){

    }

    public void onBottomToTopSwipe(){
        System.out.println("BOTTOM TO TOP SWIPE DONE!");
    }

    public boolean onTouch(View v, MotionEvent event) {
        switch(event.getAction()){
        case MotionEvent.ACTION_DOWN: {
            downY = event.getY();
            return true;
        }
        case MotionEvent.ACTION_UP: {
            upY = event.getY();
            float deltaY = downY - upY;
            if(Math.abs(deltaY) > MIN_DISTANCE){
                if(deltaY > 0) { this.onBottomToTopSwipe(); return true; }
            }
            else {
                return false;
            }

            return true;
        }
        }
        return false;
    }

}

    layout = (RelativeLayout)this.findViewById(R.id.layout);
    layout.setOnTouchListener(activitySwipeDetector);

但它什么也不做!

所以我尝试以这种方式创建自定义 webview:

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.webkit.WebView;

public class MyWebView extends WebView {
    public MyWebView(Context context) {
        super(context);
    }
    public MyWebView(Context context,AttributeSet set){
        super(context,set);
    }



    @Override 
    public boolean onTouchEvent(MotionEvent evt) {   

        boolean consumed = super.onTouchEvent(evt); 
        if (isClickable()) { 
            switch (evt.getAction()) { 
            case MotionEvent.ACTION_DOWN:  
                lastTouchY = evt.getY();
                downTime = evt.getEventTime();
                hasMoved = false; 
                break; 
            case MotionEvent.ACTION_MOVE: 
                hasMoved = moved(evt); 
                break; 
            case MotionEvent.ACTION_UP: 
                float actualTouchY = evt.getY();
                long currentTime = evt.getEventTime();
                float difference = Math.abs(lastTouchY - actualTouchY);
                long time = currentTime - downTime;

                if ( (lastTouchY < actualTouchY) && (time < 220) && (difference > 100) ) {
                    System.out.println("SWIPE1");
                }
                if ( (lastTouchY > actualTouchY) && (time < 220) && (difference > 100) ) {
                    System.out.println("SWIPE2");
                }
                break; 
            } 
        } 
        return consumed || isClickable(); 
    } 
    long downTime;
    private float lastTouchY; 
    private boolean hasMoved = false; 
    private boolean moved(MotionEvent evt) { 
        return hasMoved || 
                Math.abs(evt.getY() - lastTouchY) > 10.0; 
    }

}

但是没有成功!!!有人能帮我吗??谢谢!!!!! :)

【问题讨论】:

    标签: android webview gesture swipe


    【解决方案1】:

    GestureDetector 与自定义网络视图一起使用..

    webView.setGestureDetector(new GestureDetector(new CustomeGestureDetector()));   
    

    手势检测器:

    private class CustomeGestureDetector extends SimpleOnGestureListener {      
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            if(e1 == null || e2 == null) return false;
            if(e1.getPointerCount() > 1 || e2.getPointerCount() > 1) return false;
            else {
                try { // right to left swipe .. go to next page
                    if(e1.getX() - e2.getX() > 100 && Math.abs(velocityX) > 800) {
                        //do your stuff
                        return true;
                    } //left to right swipe .. go to prev page
                    else if (e2.getX() - e1.getX() > 100 && Math.abs(velocityX) > 800) {
                        //do your stuff
                        return true;
                    } //bottom to top, go to next document
                    else if(e1.getY() - e2.getY() > 100 && Math.abs(velocityY) > 800 
                            && webView.getScrollY() >= webView.getScale() * (webView.getContentHeight() - webView.getHeight())) {
                        //do your stuff
                        return true;
                    } //top to bottom, go to prev document
                    else if (e2.getY() - e1.getY() > 100 && Math.abs(velocityY) > 800 ) {
                        //do your stuff
                        return true;
                    } 
                } catch (Exception e) { // nothing
                }
                return false;
            }
        }
    }
    

    自定义网页视图:

    public final class CustomWebView extends WebView {
    
    private GestureDetector gestureDetector;
    
    /**
     * @param context
     * @param attrs
     * @param defStyle
     */
    public CustomWebView(Context context) {
        super(context);
    }
    
    /**
     * @param context
     * @param attrs
     * @param defStyle
     */
    public CustomWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    
    /**
     * @param context
     * @param attrs
     * @param defStyle
     */
    public CustomWebView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }
    
    /* 
     * @see android.webkit.WebView#onScrollChanged(int, int, int, int)
     */
    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
    }
    
    /* 
     * @see android.webkit.WebView#onTouchEvent(android.view.MotionEvent)
     */
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return gestureDetector.onTouchEvent(ev) || super.onTouchEvent(ev);
    }
    
    public void setGestureDetector(GestureDetector gestureDetector) {
        this.gestureDetector = gestureDetector;
    }
    }
    

    正如Андрей Москвичёв所说:

    可以通过注册触摸监听器webview.setOnTouchListener(new OnTouchListener() ...)并从中调用gestureDetector.onTouchEvent(ev)来解决,无需派生WebView类。

    【讨论】:

    • 太棒了!!!!我删除了除自下而上的所有内容(我需要什么),我看到如果我离开 webView.getScrollY() >= webView.getScale() * (webView.getContentHeight() - webView.getHeight() 它给了我例外。但效果很好!!!!!!!我能告诉我如何只在屏幕的一部分上识别那个手势吗?谢谢!
    • 类似 if(e1.getX() > yourLimit || e2.getX() > yourLimit) return false; (//不处理)
    • 感谢您的信息。无需派生 WebView 类即可解决,方法是注册触摸监听器:webview.setOnTouchListener(new OnTouchListener() ...) 并从中调用gestureDetector.onTouchEvent(ev)。
    • 嗨,如何在此添加捏缩放。它现在不工作了。
    • @Nermeen 如何实现内部活动你能帮忙提供完整的代码吗?
    【解决方案2】:

    'webView.setGestureDetector(new GestureDetector(' 解决方案已弃用。

    下一个解决方案很容易实现。滚动,点击链接仍然有效。

    1 - 将此添加到您的 webView:

    webView.setOnTouchListener( new OnSwipeWebviewTouchListener( getActivity(), this));
    

    “this”表示您的调用类实现了 TouchListener 接口方法。您可以通过 onSwipeRight() 和 onSwipeLeft() 方法实现您的导航。

    2 - 使用这个 OnTouchListener:

    public class OnSwipeWebviewTouchListener implements View.OnTouchListener {
        private final GestureDetector gestureDetector;
        public OnSwipeWebviewTouchListener(Context ctx, TouchListener touchListener) {
            gestureDetector = new GestureDetector(ctx, new GestureListener(touchListener));
        }
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return gestureDetector.onTouchEvent(event);
        }
        private final class GestureListener extends GestureDetector.SimpleOnGestureListener {
            private TouchListener touchListener;
            GestureListener(TouchListener touchListener) {
                super();
                this.touchListener = touchListener;
            }
            @Override
            public boolean onDown(MotionEvent e) {
                return false;  // THIS does the trick
            }
            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                boolean result = false;
                try {
                    float diffY = e2.getY() - e1.getY();
                    float diffX = e2.getX() - e1.getX();
                    if (Math.abs(diffX) > Math.abs(diffY)) {
                        // You can customize these settings, so 30 is an example
                        if (Math.abs(diffX) > 30 && Math.abs(velocityX) > 30) {
                            if (diffX > 0) {
                                touchListener.onSwipeRight();
                            } else {
                                touchListener.onSwipeLeft();
                            }
                            result = true;
                        }
                    } else {
                        result = false;
                    }
                } catch (Exception exception) {
                    exception.printStackTrace();
                }
                return result;
            }
        }
    }
    

    3 - TouchListner 的一个示例可能是:

    public interface TouchListener  {
        default void onSwipeLeft() {
            Logger.d( "Swipe left");
        }
        default void onSwipeRight() {
            Logger.d( "Swipe right");
        }
    }
    

    【讨论】:

      【解决方案3】:

      我已经尝试了很多尝试来让这个 webview 和 swipe 正常工作。经过一番折腾,我写了一个简单有效的解决方案。

      我使用了以下两篇stackoverflow文章来编写代码 Android left/right swipe gesture in WebView activity...Fling Gesture and Webview in Android

      首先将项目设置为空项目,然后添加第一个代码。

      import androidx.appcompat.app.AppCompatActivity;
      import android.os.Bundle;
      
      import android.webkit.WebView;
      import android.webkit.WebViewClient;
      import android.content.Context;
      import android.view.MotionEvent;
      import android.view.GestureDetector;
      import android.view.GestureDetector.SimpleOnGestureListener;
      import android.widget.Toast;
      
      
      public class MainActivity extends AppCompatActivity {
      
          @Override
          public void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
      
              MyWebView webView = new MyWebView(this);
              setContentView(webView);
      
              //setContentView(R.layout.activity_main);
              //webView = findViewById(R.id.web);
      
              webView.setInitialScale(1);
              webView.getSettings().setJavaScriptEnabled(true);
              webView.getSettings().setLoadWithOverviewMode(true);
              webView.getSettings().setUseWideViewPort(true);
              webView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
              webView.setScrollbarFadingEnabled(false);
              webView.getSettings().setBuiltInZoomControls(true);
              webView.getSettings().setDomStorageEnabled(true);
              webView.setWebViewClient(new WebViewClient());
              webView.loadUrl("http://example.com");
      
          }
      

      然后你想创建一个自定义的 WebView。

              class MyWebView extends WebView {
                  Context context;
                  GestureDetector gd;
                  public MyWebView mywebview;
      
                  private static final int SWIPE_DISTANCE_THRESHOLD = 100;
                  private static final int SWIPE_VELOCITY_THRESHOLD = 100;
      
                  public MyWebView(Context context) {
                      super(context);
                      this.context = context;
                      gd = new GestureDetector(context, sogl);
                      mywebview = this;
                  }
      
                  @Override
                  public boolean onTouchEvent(MotionEvent event) {
                      gd.onTouchEvent(event);
                      return super.onTouchEvent(event);
                  }
      
                  GestureDetector.SimpleOnGestureListener sogl = new SimpleOnGestureListener() {
                      public boolean onDown(MotionEvent event) {
                          return true;
                      }
      
                      @Override
                      public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                          float distanceX = e2.getX() - e1.getX();
                          float distanceY = e2.getY() - e1.getY();
                          if (Math.abs(distanceX) > Math.abs(distanceY) && Math.abs(distanceX) > SWIPE_DISTANCE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                              if (distanceX > 0) {
                                  mywebview.goForward();
                                  show_toast("swipe right");
                              }
                              else {
                                  mywebview.goBack();
                                  show_toast("swipe left");
                              }
                              return true;
                          }
                          return false;
                      }
      
                  };
      
                  void show_toast(final String text) {
                      Toast t = Toast.makeText(context, text, Toast.LENGTH_SHORT);
                      t.show();
                  }
      
              }
      
          @Override
          public void onBackPressed() {  // navigation bar
              webView.goBack();
              //super.onBackPressed();
          }
      
      }   // END ... MainActivity extends AppCompatActivity
      

      我已经在他们的模拟器中的 android 2020.3.1 和 android 手机和 webview 上运行了这段代码,并且左右滑动可以正常工作。这个版本的 onFling 方法可以更好地在页面中移动。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-07-30
        • 2011-05-15
        • 2012-08-28
        • 1970-01-01
        • 1970-01-01
        • 2017-10-18
        相关资源
        最近更新 更多