我有一个应用程序可以在三个WebViews
中加载HTML内容。为简单起见,我们将它们称为顶部,中部和底部。
用户始终在查看中间WebView
。当用户到达页面顶部并向下滑动时,三个WebView的布局会发生变化,以便顶视图可见。相反,当用户到达页面底部并向上滑动时,底部页面就会显示出来。
想象一下100x100的屏幕。坐标0,0是屏幕的左上角,100,100是屏幕的右下角。顶部视图将具有顶部为-105的布局,因此它不可见,中间视图将占据屏幕,底部视图将具有顶部为105的布局,因此它也是不可见的
topLayout.topMargin = -105;
middleLayout.topMargin = 0;
bottomLayout.topMargin = 105;
top.setLayoutParams(topLayout);
middle.setLayoutParams(middleLayout);
bottom.setLayoutParams(bottomLayout);
内容是书籍,因此当用户更改页面时,内容应该在逻辑上流动。向后(向上)滚动时,应显示上一页的底部。向前(向下)滚动时,应显示下一页的顶部。这是通过使用scrollTo(x,y)
设置WebView的滚动位置来完成的。代码如下所示,其中a
代表内容的底部,b
代表内容的顶部:
top.scrollTo(0, a);
middle.scrollTo(0, {a,b}); // a for previous page; b for next page
bottom.scrollTo(0, b);
当用户滑动到上一页时,顶部WebView
的布局会更改为顶部为0以占据屏幕;中间变为105,底部变为-105并加载不同的内容,以便应用程序为将来的滑动做好准备。
我已经通过调试器并注意到布局设置正确,然后正确设置了滚动位置。然后,在设置这些值之后,但在实际绘制内容之前,堆栈中会发生一些更改滚动位置的事件。
这是我完全迷失的地方。为什么滚动值设置正确,然后在绘制屏幕之前神奇地改变?
我已经尝试使用onLayoutCompleteListener
,但它没有用。我将在收到答案时更新所尝试的事项列表并尝试建议。提前感谢您提供任何帮助。
以下是我正在做的更改网页的摘要:
public class MyWebView extends WebView {
// Assume this is instantiated; it is by the time it is needed
private List<MyWebView> viewArray = new List<MyWebView>(3);
private class CustomGestureListener extends
GestureDetector.SimpleOnGestureListener {
private static final String DEBUG_TAG = "Gestures";
private int scrollYOnTouch;
private int scrollYOnRelease;
@Override
public boolean onFling(MotionEvent event1, MotionEvent event2,
float velocityX, float velocityY) {
Log.d(DEBUG_TAG, "onFling: " + event1.toString()
+ event2.toString());
Log.i(DEBUG_TAG, "onFling: vX[" + velocityX
+ "], vY[" + velocityY + "]");
scrollYOnRelease = getScrollY();
int bottomOfPage = scrollYOnTouch + getMeasuredHeight();
int endOfContent = (int) Math.floor(getContentHeight() * getScale());
int proximity = endOfContent - bottomOfPage;
boolean atBottom = proximity <= 1;
Log.i(DEBUG_TAG, "atBottom = (" + proximity + " <= 1)");
if ((velocityY > VELOCITY_THRESHOLD)
&& (scrollYOnRelease <= 0) && (scrollYOnTouch == 0)) {
// User flung down while at the top of the page.
// Go to the previous page.
changePages(PREVIOUS_PAGE);
} else if ((velocityY < -VELOCITY_THRESHOLD)
&& (scrollYOnRelease >= scrollYOnTouch) && atBottom) {
// User flung up while at the bottom of the page.
// Go to the next page.
changePages(NEXT_PAGE);
}
return true;
}
} // end of CustomGestureListener
@Override
public boolean onTouchEvent(MotionEvent event) {
// Send the event to our gesture detector
// If it is implemented, there will be a return value
this.mDetector.onTouchEvent(event);
// If the detected gesture is unimplemented, send it to the superclass
return super.onTouchEvent(event);
}
@Override
public void changePages(int direction) {
int screenWidth = getScreenWidth();
int screenHeight = getScreenHeight();
VerticalPagingWebView previous;
VerticalPagingWebView current;
VerticalPagingWebView next;
if (direction == NEXT_PAGE) {
// Rearrange elements in webview array
// Next page becomes current page,
// current becomes previous,
// previous becomes next.
Collections.swap(viewArray, 0, 1);
Collections.swap(viewArray, 1, 2);
previous = viewArray.get(0);
current = viewArray.get(1);
next = viewArray.get(2);
// Prepare the next page
next.loadData(htmlContent, "text/html", null);
} else if (direction == PREVIOUS_PAGE) {
// Rearrange elements in webview array
// Previous page becomes current page,
// current becomes next,
// next becomes previous.
Collections.swap(viewArray, 1, 2);
Collections.swap(viewArray, 0, 1);
previous = viewArray.get(0);
current = viewArray.get(1);
next = viewArray.get(2);
// Prepare the previous page
previous.loadData(htmlContent, "text/html", null);
}
LayoutParams previousLayout = (LayoutParams) previous.getLayoutParams();
previousLayout.leftMargin = LEFT_MARGIN;
previousLayout.topMargin = -screenHeight - TOP_MARGIN;
previous.setLayoutParams(previousLayout);
LayoutParams currentLayout = (LayoutParams) current.getLayoutParams();
currentLayout.leftMargin = LEFT_MARGIN;
currentLayout.topMargin = 0;
current.setLayoutParams(currentLayout);
LayoutParams nextLayout = (LayoutParams) next.getLayoutParams();
nextLayout.leftMargin = LEFT_MARGIN;
nextLayout.topMargin = screenHeight + TOP_MARGIN;
next.setLayoutParams(nextLayout);
previous.scrollToBottom();
next.scrollToTop();
// I'm unsure if this is needed, but it works on everything but KitKat
if (direction == NEXT_PAGE) {
current.scrollToTop();
} else {
current.scrollToBottom();
}
} // end of changePages
public void scrollToPageStart() {
scrollTo(0,0);
}
public void scrollToPageBottom() {
// I know getScale() is deprecated; I take care of it.
// This method works fine.
int endOfContent = (int) Math.floor(getContentHeight() * getScale());
int webViewHeight = getMeasuredHeight();
scrollTo(0, endOfContent - webViewHeight);
}
}
答案 0 :(得分:1)
您可能在完成加载内容之前滚动WebView。问题是,在页面加载期间的某个时刻,WebView会重置滚动(这是有意的,当您在页面之间导航时,您不希望滚动偏移持续存在),有时在您调用{{1 }}
要解决此问题,您有两种选择:
scrollTo
无法可靠地工作)。一种选择是在进行滚动之前轮询onPageFinished
方法何时返回内容的高度。