ปิดการเลื่อนใน webview ไหม


86

จนถึงตอนนี้ฉันเป็นนักพัฒนา iPhone เท่านั้นและตอนนี้ฉันตัดสินใจที่จะให้ Android เป็นแบบหมุน สิ่งที่ฉันไม่สามารถเข้าใจได้ใน Android คือวิธีการป้องกันการเลื่อนโดยใช้โปรแกรมโดยใช้โปรแกรมWebView?

สิ่งที่คล้ายกับ iPhones การป้องกันonTouchMoveเหตุการณ์จะดีมาก!

คำตอบ:


179

นี่คือรหัสของฉันสำหรับปิดการใช้งานการเลื่อนทั้งหมดใน webview:

  // disable scroll on touch
  webview.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
      return (event.getAction() == MotionEvent.ACTION_MOVE);
    }
  });

หากต้องการซ่อนเฉพาะแถบเลื่อน แต่ไม่ปิดใช้งานการเลื่อน:

WebView.setVerticalScrollBarEnabled(false);
WebView.setHorizontalScrollBarEnabled(false);

หรือคุณสามารถลองใช้เลย์เอาต์คอลัมน์เดียวแต่ใช้ได้กับเพจธรรมดาเท่านั้นและปิดใช้งานการเลื่อนแนวนอน

   //Only disabled the horizontal scrolling:
   webview.getSettings().setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);

คุณยังสามารถลองรวมwebview ของคุณด้วยการเลื่อน scrollview ในแนวตั้งและปิดใช้งานการเลื่อนทั้งหมดบน webview:

<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbars="vertical"    >
  <WebView
    android:id="@+id/mywebview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:scrollbars="none" />
</ScrollView>

และตั้งค่า

webview.setScrollContainer(false);

อย่าลืมเพิ่มwebview.setOnTouchListener(...)โค้ดด้านบนเพื่อปิดใช้งานการเลื่อนทั้งหมดใน webview ScrollView แนวตั้งจะช่วยให้สามารถเลื่อนเนื้อหาของ WebView ได้


ใช้งานได้ดี แต่หลังจากนั้นไม่กี่วินาทีทำให้เกิดความผิดพลาดใน Samsung i5700 spica ใน /system/lib/libwebcore.so
Lukas

LayoutAlgorithm.SINGLE_COLUMN หรือ webview.setOnTouchListener?
peceps

3
หากคุณใส่ WebView ใน ScrollView ให้ตั้งค่าแอตทริบิวต์ android: isScrollContainer ของ WebView เป็น "false" แทนที่จะตั้งค่า android: scrollbars เป็น "none" สิ่งนี้มีผลในการปิดใช้งานการจัดการการเลื่อนของ webview โดยสิ้นเชิงและอนุญาตให้ขยายตามเนื้อหา จากนั้น Scroll จะถูกจัดการโดย ScrollView หลัก
BladeCoder

1
หากคุณต้องการจัดการMotionEvent.ACTION_MOVEเหตุการณ์ในของคุณWebViewโปรดดูคำตอบของฉันด้านล่าง
GDanger

1
การเพิกเฉยACTION_MOVEต่อsetOnTouchListenerเหตุการณ์นั้นมีผลข้างเคียงดังนั้นฉันไม่แนะนำคำตอบนี้ 1. การปัดอย่างรวดเร็วจะนับเป็นonclickเหตุการณ์ในหน้า 2. ป้องกันไม่ให้มีการเลื่อนองค์ประกอบบนหน้ามากเกินไปซึ่งอาจจำเป็นสำหรับการโต้ตอบที่เหมาะสมขึ้นอยู่กับไซต์ 3. touchmoveเหตุการณ์JS @GDanger มีคำตอบที่ถูกต้องซึ่งจะแทนที่overScrollByโดยการขยายWebViewเนื่องจากไม่มีเอฟเฟกต์อื่น ๆ เพียงแค่ป้องกันการเลื่อนหน้า stackoverflow.com/a/26129301/1244574
jkasten

22

ฉันไม่รู้ว่าคุณยังต้องการหรือไม่ แต่นี่คือวิธีแก้ปัญหา:

appView = (WebView) findViewById(R.id.appView); 
appView.setVerticalScrollBarEnabled(false);
appView.setHorizontalScrollBarEnabled(false);

18
ตกลง. สิ่งนี้จะปิดใช้งานแถบเลื่อน แต่ไม่ได้ป้องกันการเลื่อนโดยการลาก ดูเหมือนว่า html จะต้องพอดีด้วย ...
rdmueller

หากคุณกำลังออกแบบหน้าเว็บของคุณสำหรับการดูเว็บของ Android เท่านั้นฉันขอแนะนำให้สร้างหน้าเว็บของคุณเป็นตาราง ความกว้างควรเป็นเช่น width = "100%" และเท่ากันสำหรับความสูง ดังนั้นจะไม่มีการลากอีกต่อไป
umar

width = 100% ไม่ได้ผลเสมอไปตัวอย่างเช่นstackoverflow.com/questions/6460871/…
NoBugs

สุดยอด .. มันคือสิ่งที่ฉันต้องการ ขอบคุณ
Peter

21

การWebViewเพิกเฉยต่อเหตุการณ์การเคลื่อนไหวเป็นวิธีที่ผิดในการดำเนินการดังกล่าว จะเป็นอย่างไรหากWebViewจำเป็นต้องได้ยินเกี่ยวกับเหตุการณ์เหล่านี้

แทนคลาสย่อยWebViewและแทนที่วิธีการเลื่อนแบบไม่เป็นส่วนตัว

public class NoScrollWebView extends WebView {
    ...
    @Override
    public boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, 
                                int scrollRangeX, int scrollRangeY, int maxOverScrollX, 
                                int maxOverScrollY, boolean isTouchEvent) {
        return false;
    }

    @Override
    public void scrollTo(int x, int y) {
        // Do nothing
    }

    @Override
    public void computeScroll() {
        // Do nothing
    }
}

ถ้าคุณมองไปที่แหล่งที่มาสำหรับWebViewคุณจะเห็นว่าonTouchEventสายdoDragที่เรียกoverScrollBy


1
หากคุณต้องการปิดการใช้งาน / เปิดใช้งานการเลื่อนโดยใช้โปรแกรมให้ดูที่ส่วนสำคัญที่ฉันสร้างขึ้น
GDanger

1
วิธีการของคุณใช้ได้ผลสำหรับฉัน และฉันค่อนข้างเห็นด้วยกับคุณ ในกรณีของฉันฉันไม่สามารถลากแถบความคืบหน้าของวิดีโอและเสียงที่ฝังใน WebView โดยใช้คำตอบยอมรับ
codezjx

นี่คือคำตอบที่ใช่ แม้ว่าจะต้องมีการปรับแต่งบางอย่างเกี่ยวกับตัวสร้างที่ลบล้าง โปรดดูคำตอบทั้งหมดของฉันด้านล่าง stackoverflow.com/a/51936944/393502
Vansi

14

การเพิ่มรายละเอียดระยะขอบให้กับเนื้อหาจะทำให้ไม่สามารถเลื่อนได้หากเนื้อหาของคุณห่อหุ้มอย่างถูกต้องดังนี้:

<body leftmargin="0" topmargin="0" rightmargin="0" bottommargin="0">

ง่ายพอและโค้ดน้อยลงมาก + ค่าใช้จ่ายบั๊ก :)


1
ยอดเยี่ยม! +1 สำหรับโซลูชัน HTML แบบธรรมดาเท่านั้น บางครั้งฉันก็หวังว่ารูปแบบใน Android ก็ง่ายเหมือน css ...
Pritesh Desai

ดูดีในเบราว์เซอร์ android แต่ดูเหมือนจะไม่ทำงานใน Firefox (Fennec) ... แม้ว่าจะไม่มีอะไรให้เลื่อนไปในแนวนอน แต่ Firefox ก็ยังให้ฉันเลื่อนไปทางขวาจนถึงจุดที่เนื้อหาทั้งหมดเลื่อนไป ปิดหน้าจอ
Michael

1
ไม่ทำงานบน WebView ที่ทันสมัย ​​(Android 5 ขึ้นไป)
Roel

8

ตั้งค่าผู้ฟังบน WebView ของคุณ:

webView.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                return(event.getAction() == MotionEvent.ACTION_MOVE));
            }
        });

3
มีวงเล็บเสริมที่ท้ายreturnบรรทัด นอกจากนี้ยังแบ่งแคนวาส HTML5 และเหตุการณ์การสัมผัส JavaScript
Rohan Singh

สิ่งนี้ปิดการใช้งานอย่างแน่นอน แต่ฉันจะฆ่าผู้ฟังในภายหลังเพื่อเปลี่ยนอินพุตได้อย่างไร ฉันพยายามevent.getAction() != MotionEvent.ACTION_MOVEเช่นเดียวกับreturn true
CQM

กรณี "ไม่ทำอะไร" มาตรฐานคือreturn falseไม่ใช่return trueไม่
Matthew อ่าน

6

ฉันยังไม่ได้ลองทำเพราะยังไม่พบปัญหานี้ แต่บางทีคุณอาจใช้ฟังก์ชัน onScroll มากเกินไป?

@Override
public void scrollTo(int x, int y){
super.scrollTo(0,y);
}

นี่คือสิ่งที่เราเรียกในอินเดียว่า Jugaad ... แม้ว่าจะใช้งานได้ดี
R4chi7

4

โซลูชันที่สกปรก แต่ใช้งานง่ายและใช้งานได้ดี:

เพียงใส่ webview ไว้ใน scrollview ทำให้มุมมองเว็บใหญ่เกินกว่าเนื้อหาที่เป็นไปได้ (ในมิติเดียวหรือทั้งสองมิติขึ้นอยู่กับข้อกำหนด) .. และตั้งค่าแถบเลื่อนของ scrollview ตามที่คุณต้องการ

ตัวอย่างการปิดใช้งานแถบเลื่อนแนวนอนบนเว็บวิว:

<ScrollView
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:scrollbars="vertical"
>
    <WebView
        android:id="@+id/mywebview"
        android:layout_width="1000dip"
        android:layout_height="fill_parent"
    />
</ScrollView>

ฉันหวังว่านี่จะช่วยได้ ;)


ใช่ แต่ขนาดการเลื่อนจะไม่ใหญ่เกินไปโดยมีช่องว่างด้านล่างจำนวนมาก?
Rafael Sanches

1
จะเกิดอะไรขึ้นถ้าความกว้างของเนื้อหาจะเป็น 1001dp?
Waltsu

3

ฉันแก้ไขการกะพริบและเลื่อนอัตโนมัติโดย:

webView.setFocusable(false);
webView.setFocusableInTouchMode(false);

อย่างไรก็ตามหากยังไม่ได้ผลด้วยเหตุผลบางประการเพียงแค่สร้างคลาสที่ขยาย WebView และใส่วิธีนี้:

// disable scroll on touch
  setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
      return (event.getAction() == MotionEvent.ACTION_MOVE);
    }
  });

ฉันขอแนะนำให้ขยาย WebView เพื่อให้การควบคุมมีประสิทธิภาพมากขึ้นเช่นปิด / เปิดใช้งานการปัดนิ้วเปิด / ปิดการสัมผัสผู้ฟังควบคุมการเปลี่ยนภาพเคลื่อนไหวกำหนดการตั้งค่าภายในเป็นต้น ..


3

ในการปิดใช้งานการเลื่อนให้ใช้สิ่งนี้

webView.setOnTouchListener(new View.OnTouchListener() {
    public boolean onTouch(View v, MotionEvent event) 
    {
        return (event.getAction() == MotionEvent.ACTION_MOVE);
    }
});

2

นี่อาจไม่ใช่สาเหตุของปัญหาของคุณ แต่ฉันใช้เวลาหลายชั่วโมงในการพยายามติดตามสาเหตุที่แอปพลิเคชันของฉันทำงานได้ดีบน iphone ทำให้เบราว์เซอร์ Android โยนแถบเลื่อนแนวตั้ง / แนวนอนตลอดเวลาและเลื่อนหน้า ฉันมีแท็กเนื้อหา html ที่ตั้งค่าความสูงและความกว้างไว้ที่ 100% และเนื้อหานั้นเต็มไปด้วยแท็กต่างๆในตำแหน่งต่างๆ ไม่ว่าฉันจะพยายามทำอะไรเบราว์เซอร์ Android จะแสดงแถบเลื่อนและเลื่อนหน้าเพียงเล็กน้อยโดยเฉพาะอย่างยิ่งเมื่อทำการปัดอย่างรวดเร็ว วิธีแก้ปัญหาที่ใช้ได้ผลสำหรับฉันโดยไม่ต้องทำอะไรเลยใน APK คือเพิ่มสิ่งต่อไปนี้ในแท็ก body:

leftmargin="0" topmargin="0"

ดูเหมือนว่าระยะขอบเริ่มต้นสำหรับแท็กร่างกายจะถูกนำไปใช้กับ Droid แต่ถูกละเว้นบน iPhone


1

หากคุณsubclass Webview คุณสามารถแทนที่ onTouchEvent เพื่อกรองเหตุการณ์การย้ายที่ทำให้เกิดการเลื่อน

public class SubWebView extends WebView {

    @Override
    public boolean onTouchEvent (MotionEvent ev)    {
        if(ev.getAction() == MotionEvent.ACTION_MOVE) {
            postInvalidate();
            return true;
        }
        return super.onTouchEvent(ev);
    }
    ...

0

การศึกษาคำตอบข้างต้นเกือบจะได้ผลสำหรับฉัน ... แต่ฉันยังมีปัญหาที่ฉันสามารถ 'เหวี่ยง' มุมมองบน 2.1 ได้ (ดูเหมือนจะแก้ไขด้วย 2.2 & 2.3)

นี่คือทางออกสุดท้ายของฉัน

public class MyWebView extends WebView
{
private boolean bAllowScroll = true;
@SuppressWarnings("unused") // it is used, just java is dumb
private long downtime;

public MyWebView(Context context, AttributeSet attrs)
{
    super(context, attrs);
}

public void setAllowScroll(int allowScroll)
{
    bAllowScroll = allowScroll!=0;
    if (!bAllowScroll)
        super.scrollTo(0,0);
    setHorizontalScrollBarEnabled(bAllowScroll);
    setVerticalScrollBarEnabled(bAllowScroll);
}

@Override
public boolean onTouchEvent(MotionEvent ev) 
{
    switch (ev.getAction())
    {
    case MotionEvent.ACTION_DOWN:
        if (!bAllowScroll)
            downtime = ev.getEventTime();
        break;
    case MotionEvent.ACTION_CANCEL:
    case MotionEvent.ACTION_UP:
        if (!bAllowScroll)
        {
            try {
                Field fmNumSamples = ev.getClass().getDeclaredField("mNumSamples");
                fmNumSamples.setAccessible(true);
                Field fmTimeSamples = ev.getClass().getDeclaredField("mTimeSamples");
                fmTimeSamples.setAccessible(true);
                long newTimeSamples[] = new long[fmNumSamples.getInt(ev)];
                newTimeSamples[0] = ev.getEventTime()+250;
                fmTimeSamples.set(ev,newTimeSamples);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        break;
    }
    return super.onTouchEvent(ev);
}

@Override
public void flingScroll(int vx, int vy)
{
    if (bAllowScroll)
        super.flingScroll(vx,vy);
}

@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt)
{
    if (bAllowScroll)
        super.onScrollChanged(l, t, oldl, oldt);
    else if (l!=0 || t!=0)
        super.scrollTo(0,0);
}

@Override
public void scrollTo(int x, int y)
{
    if (bAllowScroll)
        super.scrollTo(x,y);
}

@Override
public void scrollBy(int x, int y)
{
    if (bAllowScroll)
        super.scrollBy(x,y);
}
}

เพื่อแทนที่เมธอด onScrollChanged () ได้ผลสำหรับฉัน ในกรณีของฉันฉันไม่สามารถลากแถบความคืบหน้าของวิดีโอและเสียงที่ฝังใน WebView โดยใช้คำตอบยอมรับ ขอบคุณมาก!
codezjx

-1

นี่น่าจะเป็นคำตอบที่สมบูรณ์ ตามคำแนะนำของ @GDanger. ขยาย WebView เพื่อแทนที่วิธีการเลื่อนและฝัง webview ที่กำหนดเองไว้ภายใน xml โครงร่าง

public class ScrollDisabledWebView extends WebView {

    private boolean scrollEnabled = false;

    public ScrollDisabledWebView(Context context) {
        super(context);
        initView(context);
    }

    public ScrollDisabledWebView(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
        initView(context);
    }
    // this is important. Otherwise it throws Binary Inflate Exception.
    private void initView(Context context) {
        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    }

    @Override
    protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY,
                                   int scrollRangeX, int scrollRangeY, int maxOverScrollX,
                                   int maxOverScrollY, boolean isTouchEvent) {
        if (scrollEnabled) {
            return super.overScrollBy(deltaX, deltaY, scrollX, scrollY,
                    scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
        }
        return false;
    }

    @Override
    public void scrollTo(int x, int y) {
        if (scrollEnabled) {
            super.scrollTo(x, y);
        }
    }

    @Override
    public void computeScroll() {
        if (scrollEnabled) {
            super.computeScroll();
        }
    }
}

จากนั้นฝังในไฟล์เลย์เอาต์ดังนี้

<com.sample.apps.ScrollDisabledWebView
    android:id="@+id/webView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_centerInParent="true"
    tools:context="com.sample.apps.HomeActivity"/>

จากนั้นในกิจกรรมให้ใช้วิธีการเพิ่มเติมบางอย่างในการปิดใช้งานแถบเลื่อนด้วย

ScrollDisabledWebView webView = (ScrollDisabledWebView) findViewById(R.id.webView);
webView.setVerticalScrollBarEnabled(false);
webView.setHorizontalScrollBarEnabled(false);

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.