지금까지 저는 iPhone 개발자 일 뿐이었고 지금은 Android에 소용돌이를 주기로 결정했습니다. 내가 안드로이드에서 알아낼 수 없었던 것은 프로그래밍 방식으로 스크롤을 방지하는 방법입니다 WebView
.
iPhones와 유사한 onTouchMove
이벤트 예방이 좋을 것입니다!
답변:
다음은 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);
수직 스크롤 스크롤 뷰로 웹뷰 를 래핑 하고 웹뷰에서 모든 스크롤링을 비활성화 할 수도 있습니다 .
<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의 콘텐츠 스크롤을 허용합니다.
MotionEvent.ACTION_MOVE
이벤트 를 처리해야하는 경우 WebView
아래 내 대답을 참조하십시오.
ACTION_MOVE
온 setOnTouchListener
나는이 대답을 권하고 싶지 않다 있도록 이벤트가 부작용이있다; 1. 빠른 스 와이프는 onclick
페이지에 대한 이벤트로 계산됩니다 . 2. 페이지 요소의 오버 플로우 스크롤을 방지합니다. 이는 사이트에 따라 적절한 상호 작용을 위해 필요할 수 있습니다. 3. JS touchmove
이벤트. @GDanger에는 다른 부작용이 없기 때문에 overScrollBy
확장하여 재정의하는 정답이 있으며 WebView
페이지 스크롤을 방지합니다. stackoverflow.com/a/26129301/1244574
여전히 필요한지 여부는 모르겠지만 해결책은 다음과 같습니다.
appView = (WebView) findViewById(R.id.appView);
appView.setVerticalScrollBarEnabled(false);
appView.setHorizontalScrollBarEnabled(false);
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
}
}
소스 를 보면 overScrollByWebView
를 onTouchEvent
호출 doDrag
하는 호출을 볼 수 있습니다 .
본문에 여백 세부 정보를 추가하면 콘텐츠가 올바르게 래핑 된 경우 스크롤되지 않습니다.
<body leftmargin="0" topmargin="0" rightmargin="0" bottommargin="0">
충분히 쉽고 코드 + 버그 오버 헤드가 훨씬 적습니다. :)
WebView에 리스너를 설정하십시오.
webView.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
return(event.getAction() == MotionEvent.ACTION_MOVE));
}
});
return
줄 끝에 추가 괄호 가 있습니다. 또한 이것은 HTML5 캔버스 및 JavaScript 터치 이벤트를 중단합니다.
event.getAction() != MotionEvent.ACTION_MOVE
뿐만 아니라 시도return true
return false
아니라 return true
입니다.
아직이 문제가 발생하지 않았기 때문에 시도하지 않았지만 onScroll 함수를 무시할 수 있습니까?
@Override
public void scrollTo(int x, int y){
super.scrollTo(0,y);
}
더럽지 만 구현하기 쉽고 잘 작동하는 솔루션 :
단순히 스크롤 뷰 안에 웹뷰를 넣으십시오. 웹뷰를 가능한 콘텐츠보다 너무 크게 만듭니다 (요구 사항에 따라 하나 또는 두 차원 모두에서). .. 그리고 원하는대로 스크롤 뷰의 스크롤바를 설정합니다.
웹뷰에서 수평 스크롤바를 비활성화하는 예 :
<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>
이게 도움이 되길 바란다 ;)
깜박임 및 자동 스크롤을 다음과 같이 해결했습니다.
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를 확장 할 것을 제안합니다.
이것이 문제의 원인은 아니지만 iPhone에서 잘 작동하는 내 응용 프로그램으로 인해 Android 브라우저가 지속적으로 수직 / 수평 스크롤 막대를 표시하고 실제로 페이지를 이동시키는 이유를 추적하는 데 몇 시간을 보냈습니다. 높이와 너비가 100 %로 설정된 html body 태그가 있었고 본문에는 여러 위치에있는 다양한 태그가 가득했습니다. 내가 무엇을 시도하든 안드로이드 브라우저는 스크롤 막대를 표시하고 페이지를 조금만 움직일 것입니다. 특히 빠른 스 와이프를 할 때 그렇습니다. APK에서 아무것도 할 필요없이 나를 위해 일한 솔루션은 body 태그에 다음을 추가하는 것이 었습니다.
leftmargin="0" topmargin="0"
바디 태그의 기본 여백이 드로이드에 적용되었지만 아이폰에서는 무시 된 것 같습니다
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);
}
...
위의 답변을 공부하면 거의 효과가 있었지만 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);
}
}
이것은 완전한 대답이어야합니다. @GDanger가 제안한대로. 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);