首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法在webview中滚动图像

无法在webview中滚动图像
EN

Stack Overflow用户
提问于 2019-07-19 11:51:03
回答 3查看 1.9K关注 0票数 2

我为安卓和iOS开发了一个webview应用程序。我注意到我不能在android应用程序中滚动特定的html元素,而它在iOS上工作。

这是网站

问题是在产品图像上,但只有在产品详细信息页面上,您可以购买该产品并将其放入您的购物车中。

HTML

代码语言:javascript
复制
<div class="magic-slide mt-active" data-magic-slide="zoom">
    <a id="MagicZoomPlusImage286" class="MagicZoom" href="https://www.blizz-z.de/media/catalog/product/cache/2/image/0dc2d03fe217f8c83829496872af24a0/f/l/fliesenkleber-proflex-fix-1303_1.jpg" data-options="selectorTrigger:hover;textHoverZoomHint:Hovern zum Zoomen;textClickZoomHint:Berühren zum Zoomen;textExpandHint:Vergrößern;"
        data-mobile-options="textHoverZoomHint:Berühren zum Zoomen;textClickZoomHint:Doppeltippe zum Zoomen;textExpandHint:Vergrößern;">
        <figure class="mz-figure mz-hover-zoom mz-ready"><img itemprop="image" src="https://www.blizz-z.de/media/catalog/product/cache/2/image/450x450/0dc2d03fe217f8c83829496872af24a0/f/l/fliesenkleber-proflex-fix-1303_1.jpg" alt="Fliesenkleber proflex fix Schnell-Fliesenkleber - nach 3 Stunden begehbar"
                style="max-width: 450px; max-height: 450px;">
            <div class="mz-lens" style="top: 0px; transform: translate(-10000px, -10000px); width: 122px; height: 122px;"><img src="https://www.blizz-z.de/media/catalog/product/cache/2/image/450x450/0dc2d03fe217f8c83829496872af24a0/f/l/fliesenkleber-proflex-fix-1303_1.jpg" style="position: absolute; top: 0px; left: 0px; width: 349px; height: 349px; transform: translate(-1px, -132px);"></div>
            <div
                class="mz-loading"></div>
<div class="mz-hint mz-hint-hidden"><span class="mz-hint-message">Vergrößern</span></div>
</figure>
</a>
</div>

如果我从智能手机的chrome浏览器访问这个网站,那么它可以工作,所以它一定是webview中的一个bug?

图像是一个滑块,我可以左右滑动,但是如果我在图像上滚动,我不能向下滚动页面。

FullscreenActivity.java:

代码语言:javascript
复制
package de.blizz_z.onlineshop;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.graphics.Bitmap;
import android.webkit.URLUtil;
import android.net.Uri;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Build;
import android.os.Handler;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.webkit.WebChromeClient;
import android.widget.Button;
import android.util.Log;
import android.webkit.HttpAuthHandler;
import android.webkit.ValueCallback;

/**
 * An example full-screen activity that shows and hides the system UI (i.e.
 * status bar and navigation/system bar) with user interaction.
 */
public class FullscreenActivity extends AppCompatActivity
{
    private WebView blizzView;
    private Button backButton;
    private String website;

    /**
     * Whether or not the system UI should be auto-hidden after
     * {@link #AUTO_HIDE_DELAY_MILLIS} milliseconds.
     */
    private static final boolean AUTO_HIDE = true;

    /**
     * If {@link #AUTO_HIDE} is set, the number of milliseconds to wait after
     * user interaction before hiding the system UI.
     */
    private static final int AUTO_HIDE_DELAY_MILLIS = 3000;

    /**
     * Some older devices needs a small delay between UI widget updates
     * and a change of the status and navigation bar.
     */
    private static final int UI_ANIMATION_DELAY = 300;
    private final Handler mHideHandler = new Handler();
    private final Runnable mHidePart2Runnable = new Runnable()
    {
        @SuppressLint("InlinedApi")
        @Override
        public void run() {

        }
    };

    private final Runnable mShowPart2Runnable = new Runnable()
    {
        @Override
        public void run() {
            // Delayed display of UI elements
            ActionBar actionBar = getSupportActionBar();
            if (actionBar != null) {
                actionBar.show();
            }
        }
    };
    private boolean mVisible;
    private final Runnable mHideRunnable = new Runnable() {
        @Override
        public void run() {
            hide();
        }
    };

    /**
     * Touch listener to use for in-layout UI controls to delay hiding the
     * system UI. This is to prevent the jarring behavior of controls going away
     * while interacting with activity UI.
     */
    private final View.OnTouchListener mDelayHideTouchListener = new View.OnTouchListener()
    {
        @Override
        public boolean onTouch(View view, MotionEvent event)
        {

            Log.i("debug_log", "touch");

            if (AUTO_HIDE) {
                delayedHide(AUTO_HIDE_DELAY_MILLIS);
            }

            int x = (int) event.getX();
            int y = (int) event.getY();

            Log.i("debug_log", "moving: (" + x + ", " + y + ")");

            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    Log.i("debug_log", "touched down");
                    break;
                case MotionEvent.ACTION_MOVE:
                    Log.i("debug_log", "moving: (" + x + ", " + y + ")");
                    break;
                case MotionEvent.ACTION_UP:
                    Log.i("debug_log", "touched up");
                    break;
            }

            return true;
        }

    };

    @SuppressLint("ClickableViewAccessibility")
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fullscreen);

        mVisible = true;
        website = "https://www.blizz-z.de";
        blizzView = findViewById(R.id.blizzView);

        WebSettings settings = blizzView.getSettings();
        settings.setJavaScriptEnabled(true);

        // https://developer.android.com/reference/android/webkit/WebViewClient
        blizzView.setWebViewClient(new WebViewClient() {

            @Override
            public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
                super.onReceivedHttpError(view, request, errorResponse);

                Log.i("debug_log", errorResponse.getReasonPhrase());
            }

            @Override
            public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm)
            {
                super.onReceivedHttpAuthRequest(view, handler, host, realm);

                view.setHttpAuthUsernamePassword(host, realm, "macs", "20macs14");
            }

            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon)
            {
                // check here the url
                if (url.endsWith(".pdf")) {
                    Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
                    startActivity(browserIntent);
                } else {
                    super.onPageStarted(view, url, favicon);
                }
            }

            @Override
            // Notify the host application that a page has finished loading.
            public void onPageFinished(WebView view, String url)
            {
                super.onPageFinished(view, url);

                 // Hide/Show back button
                backButton = findViewById(R.id.backButton);
                backButton.setEnabled(blizzView.canGoBack());

                if (blizzView.canGoBack()) {
                    backButton.setVisibility(View.VISIBLE);
                } else {
                    backButton.setVisibility(View.INVISIBLE);
                }

                js(blizzView, "jQuery(document).ready(function() {"

                                        + "setInterval(function() {"
                                            + "jQuery('#myInput').css('background', '#'+(Math.random()*0xFFFFFF<<0).toString(16));"

                                            + "jQuery('a').each(function() {"
                                                + "jQuery(this).removeAttr('download');"
                                            + "});"
                                        + "}, 1000);"
                                    + "});");

            }

            // Give the host application a chance to take control when a URL is about to be loaded in the current WebView.
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url)
            {
                Log.i("debug_log", "shouldOverrideUrlLoading");

                //view.loadDataWithBaseURL("https://www.blizz-z.de", );

            // Allow download of .pdf files
                if (url.endsWith(".pdf")) {
                    startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
                    // if want to download pdf manually create AsyncTask here
                    // and download file
                    return true;
                }

            // Also allow urls not starting with http or https (e.g. tel, mailto, ...)
                if( URLUtil.isNetworkUrl(url) ) {
                    return false;
                } else {
                    startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
                }

                return true;
            }

        });

        blizzView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {

                int x = (int) event.getX();
                int y = (int) event.getY();

                //WebView.HitTestResult hr = blizzView.getHitTestResult();
                //Log.i("debug_log", "getExtra = "+ hr.getExtra() + " Type= " + hr.getType());

                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        Log.i("debug_log", "touched down");
                        break;
                    case MotionEvent.ACTION_MOVE:
                        Log.i("debug_log", "moving: (" + x + ", " + y + ")");
                        break;
                    case MotionEvent.ACTION_UP:
                        Log.i("debug_log", "touched up");
                        break;
                }

                return false;
            }

        });

        // URL laden:
        blizzView.loadUrl(website);
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState)
    {
        Log.i("debug_log", "onPostCreate");
        super.onPostCreate(savedInstanceState);

        // Trigger the initial hide() shortly after the activity has been
        // created, to briefly hint to the user that UI controls
        // are available.
        delayedHide(100);
    }

    private void toggle()
    {
        if (mVisible) {
            hide();
        } else {
            show();
        }
    }

    private void hide()
    {
        // Hide UI first
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.hide();
        }
        mVisible = false;

        // Schedule a runnable to remove the status and navigation bar after a delay
        mHideHandler.removeCallbacks(mShowPart2Runnable);
        mHideHandler.postDelayed(mHidePart2Runnable, UI_ANIMATION_DELAY);
    }

    @SuppressLint("InlinedApi")

    private void show()
    {
        // Show the system bar
        mVisible = true;

        // Schedule a runnable to display UI elements after a delay
        mHideHandler.removeCallbacks(mHidePart2Runnable);
        mHideHandler.postDelayed(mShowPart2Runnable, UI_ANIMATION_DELAY);
    }

    /**
     * Schedules a call to hide() in delay milliseconds, canceling any
     * previously scheduled calls.
     */
    private void delayedHide(int delayMillis)
    {
        mHideHandler.removeCallbacks(mHideRunnable);
        mHideHandler.postDelayed(mHideRunnable, delayMillis);
    }

    public void js(WebView view, String code)
    {
        String javascriptCode = "javascript:" + code;
        if (Build.VERSION.SDK_INT >= 19) {
            view.evaluateJavascript(javascriptCode, new ValueCallback<String>() {

                @Override
                public void onReceiveValue(String response) {
                    Log.i("debug_log", response);
                }
            });
        } else {
            view.loadUrl(javascriptCode);
        }
    }

    // Event Listener ------------------------------------------------------------------------------

            public void goBack(android.view.View view)
            {
                blizzView.goBack();
            }

        // If back button of smartphone is pressed, then go back in browser history
            @Override
            public boolean onKeyDown(int keyCode, KeyEvent event)
            {
                Log.i("debug_log", "KeyDown");
                if (event.getAction() == KeyEvent.ACTION_DOWN) {
                    switch (keyCode) {
                        case KeyEvent.KEYCODE_BACK:
                            if (blizzView.canGoBack())
                                blizzView.goBack();
                            else
                                finish();
                            return true;
                    }
                }

                return super.onKeyDown(keyCode, event);
            }

}

activity_fullscreen.xml

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/relativeLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:visibility="visible"
    tools:context="de.blizz_z.onlineshop.FullscreenActivity">

    <WebView
        android:id="@+id/blizzView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:keepScreenOn="true"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

    </WebView>

    <Button
        android:id="@+id/backButton"
        android:layout_width="90dp"
        android:layout_height="39dp"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginBottom="16dp"
        android:background="#F5EA01"
        android:enabled="false"
        android:onClick="goBack"
        android:text="Zurück"
        android:visibility="invisible"
        app:layout_constraintBottom_toBottomOf="@+id/blizzView"
        app:layout_constraintStart_toStartOf="@+id/blizzView" />

</android.support.constraint.ConstraintLayout>
EN

回答 3

Stack Overflow用户

发布于 2019-07-19 11:54:55

你试过把这个设置成你的webView吗?

代码语言:javascript
复制
 webview.setVerticalScrollBarEnabled(true);
 webview.setHorizontalScrollBarEnabled(true);
票数 0
EN

Stack Overflow用户

发布于 2019-07-24 13:28:56

一开始删除整个部分,

代码语言:javascript
复制
@Override
        public void onPageFinished(WebView view, String url)
        {
            super.onPageFinished(view, url);

            //blizzView.Settings.setSupportZoom(true);

            blizzView.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY);

            blizzView.getSettings().setSupportZoom(true);
            blizzView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);

            blizzView.loadUrl(
                    "javascript:(function() {"


                            //+ "jQuery('.logo').remove();" //Einige Funktionen wie z.B. alert() sind scheinbar aus Sicherheits-/Missbrauchsgründen nicht verfügbar; jQuery kann man natürlich nur nutzen wenn es eingebunden ist. Möglicherweise kann man es auch selbst einbinden.
                    + "})()"
            );

            // Hide/Show back button
            backButton = findViewById(R.id.backButton);
            backButton.setEnabled(blizzView.canGoBack());

            if (blizzView.canGoBack()) {
                backButton.setVisibility(View.VISIBLE);
            } else {
                backButton.setVisibility(View.INVISIBLE);
            }

            blizzView.setVerticalScrollBarEnabled(true);
            blizzView.setHorizontalScrollBarEnabled(true);

        }

因为不能依赖onPageFinished,所以应该实现shouldOverrideUrlLoading。我会把我的完整代码张贴在这里。

代码语言:javascript
复制
public class TempWebActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_temp_web);

    WebView webView = findViewById(R.id.wv_scroller);
    webView.getSettings().setJavaScriptEnabled(true);

    webView.loadUrl("https://www.blizz-z.de");

    webView.setWebViewClient(new WebViewClient() {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            return true;
        }
    });
    }
}

这是活动的布局

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".TempWebActivity">

<WebView 
android:id="@+id/wv_scroller"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

</ScrollView>

要实现这一点,关键是使用ScrollView包装器和WebView,如果某些Javascript可以拦截一些触摸事件。还要确保将WebView的高度保持为wrap_content。快乐编码兄弟!:)

票数 0
EN

Stack Overflow用户

发布于 2019-07-24 10:27:39

尝试在此示例中添加webview。

代码语言:javascript
复制
  <NestedScrollViewHome
            android:id="@+id/scroll_nested_journey"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@id/toolbar">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:descendantFocusability="blocksDescendants"
                android:orientation="vertical">

    //  add Webview here

     </LinearLayout>

        </NestedScrollViewHome>

NestedScrollViewHome.java

代码语言:javascript
复制
public class NestedScrollViewHome  extends NestedScrollView {
    @SuppressWarnings("unused")
    private int slop;
    @SuppressWarnings("unused")
    private float mInitialMotionX;
    @SuppressWarnings("unused")
    private float mInitialMotionY;
    public NestedScrollViewHome(Context context) {
        super(context);
        init(context);
    }

    private boolean enableScrolling = true;

    public boolean isEnableScrolling() {
        return enableScrolling;
    }

    public void setEnableScrolling(boolean enableScrolling) {
        this.enableScrolling = enableScrolling;
    }


    private void init(Context context) {
        ViewConfiguration config = ViewConfiguration.get(context);
        slop = config.getScaledEdgeSlop();
    }
    public NestedScrollViewHome(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }
    public NestedScrollViewHome(Context context, AttributeSet attrs,
                              int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }
    private float xDistance, yDistance, lastX, lastY;
    @SuppressWarnings("unused")
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
      if (isEnableScrolling())
      {
          final float x = ev.getX();
          final float y = ev.getY();
          switch (ev.getAction()) {
              case MotionEvent.ACTION_DOWN:
                  xDistance = yDistance = 0f;
                  lastX = ev.getX();
                  lastY = ev.getY();
                  // This is very important line that fixes
                  computeScroll();
                  break;
              case MotionEvent.ACTION_MOVE:
                  final float curX = ev.getX();
                  final float curY = ev.getY();
                  xDistance += Math.abs(curX - lastX);
                  yDistance += Math.abs(curY - lastY);
                  lastX = curX;
                  lastY = curY;
                  if (xDistance > yDistance) {
                      return false;
                  }
          }
          return super.onInterceptTouchEvent(ev);
      }else
          return false;
    }
    public interface OnScrollChangedListener {
        void onScrollChanged(NestedScrollView who, int l, int t, int oldl,
                             int oldt);
    }
    private OnScrollChangedListener mOnScrollChangedListener;
    public void setOnScrollChangedListener(OnScrollChangedListener listener) {
        mOnScrollChangedListener = listener;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (isEnableScrolling()) {
            return super.onTouchEvent(ev);
        } else {
            return false;
        }
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (mOnScrollChangedListener != null) {
            mOnScrollChangedListener.onScrollChanged(this, l, t, oldl, oldt);
        }
    }
}
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57111942

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档