Android WebView加载位置不正确
我有一个应用程序可以在三个Android WebView加载位置不正确,android,html,android-layout,scroll,android-webview,Android,Html,Android Layout,Scroll,Android Webview,我有一个应用程序可以在三个网络视图中加载HTML内容。为了简单起见,我们将它们称为顶部、中间和底部 用户总是查看中间的WebView。当用户到达页面顶部并向下滑动时,三个Web视图的布局将发生变化,从而使顶部视图可见。相反,当用户到达页面底部并向上滑动时,底部页面进入视图 想象一个100x100的屏幕。坐标0,0是屏幕的左上角,100100是屏幕的右下角。顶视图的布局顶部为-105,因此不可见,中间视图将占据屏幕,底视图的布局顶部为105,因此也不可见 topLayout.topMargin =
网络视图中加载HTML内容。为了简单起见,我们将它们称为顶部、中间和底部
用户总是查看中间的WebView
。当用户到达页面顶部并向下滑动时,三个Web视图的布局将发生变化,从而使顶部视图可见。相反,当用户到达页面底部并向上滑动时,底部页面进入视图
想象一个100x100的屏幕。坐标0,0是屏幕的左上角,100100是屏幕的右下角。顶视图的布局顶部为-105,因此不可见,中间视图将占据屏幕,底视图的布局顶部为105,因此也不可见
topLayout.topMargin = -105;
middleLayout.topMargin = 0;
bottomLayout.topMargin = 105;
top.setLayoutParams(topLayout);
middle.setLayoutParams(middleLayout);
bottom.setLayoutParams(bottomLayout);
内容是书籍,因此当用户更改页面时,内容应按逻辑流动。向后(向上)滚动时,应显示上一页的底部。向前(向下)滚动时,应显示下一页的顶部。这是通过使用scrollTo(x,y)
设置网络视图的滚动位置来实现的。代码如下所示,a
表示内容的底部,b
表示内容的顶部:
top.scrollTo(0, a);
middle.scrollTo(0, {a,b}); // a for previous page; b for next page
bottom.scrollTo(0, b);
当用户滑动到上一页时,topWebView
的布局更改为top of 0以占据屏幕;中间部分改为105,底部改为-105并加载不同的内容,因此应用程序将为将来的前一次刷卡做好准备。
现在我们来谈谈我的问题。除了Android 4.4(KitKat)之外,它的工作原理与预期完全一致。在KitKat中,它可以在任意方向上进行两次滑动,但在同一方向上进行第三次滑动和后续滑动时,内容加载到错误的位置。当向后滚动时,内容开始加载,显示顶部。向前滚动时,内容开始加载,显示底部
我已经通过调试程序,注意到布局设置正确,滚动位置设置正确。然后,在设置这些值之后,但在实际绘制内容之前,堆栈中会发生一些更改滚动位置的事情
这就是我完全迷路的地方。为什么滚动值设置正确,然后在绘制屏幕之前神奇地改变
我已经尝试使用了一个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);
}
}
公共类MyWebView扩展了WebView{
//假设这是实例化的;在需要它的时候是实例化的
私有列表视图数组=新列表(3);
私有类CustomGestureListener扩展
GestureDetector.SimpleOnGestureListener{
私有静态最终字符串调试_TAG=“手势”;
私人触摸屏;
私隐释放;
@凌驾
公共布尔onFling(MotionEvent1、MotionEvent2、,
浮动速度x,浮动速度y){
Log.d(DEBUG_标记,“onFling:+event1.toString()
+事件2.toString());
Log.i(调试标签,“onFling:vX[”+velocityX
+“],vY[“+velocityY+””);
scrollYOnRelease=getScrollY();
int bottomOfPage=scrollYOnTouch+getMeasuredHeight();
int endOfContent=(int)Math.floor(getContentHeight()*getScale());
int接近度=endOfContent-页面底部;
底部布尔值=接近速度(阈值)
&&(scrollYOnRelease=scrollYOnTouch)和底部(&A){
//用户在页面底部时猛然向上移动。
//转到下一页。
更改页面(下一页);
}
返回true;
}
}//CustomGestureListener结束
@凌驾
公共布尔onTouchEvent(运动事件){
//将事件发送到我们的手势检测器
//如果它被实现,将有一个返回值
this.mDetector.onTouchEvent(事件);
//如果检测到的手势未实现,则将其发送到超类
返回super.onTouchEvent(事件);
}
@凌驾
公共无效更改页(int方向){
int screenWidth=getScreenWidth();
int screenHeight=getScreenHeight();
垂直分页WebView上一页;
垂直分页网络视图当前;
垂直分页网络视图下一步;
如果(方向==下一页){
//重新排列webview数组中的元素
//下一页变为当前页,
//当前变为先前,
//上一个变成下一个。
集合交换(viewArray,0,1);
集合交换(viewArray,1,2);
previous=viewArray.get(0);
当前=viewArray.get(1);
next=viewArray.get(2);
//准备下一页
loadData(htmlContent,“text/html”,null);
}else if(方向==上一页){
//重新排列webview数组中的元素
//上一页变为当前页,
//当前成为下一个,
//下一个变成上一个。
集合交换(viewArray,1,2);
集合交换(viewArray,0,1);
previous=viewArray.get(0);
当前=viewArray.get(1);
next=viewArray.get(2);
//准备上一页
loadData(htmlContent,“text/html”,null);
}
LayoutParams previousLayout=(LayoutParams)previous.getLayoutParams();
previousLayout.leftMargin=左对齐;
previousLayout.topMargin=-屏幕高度-顶部空白;
previous.setLayoutParams(previousLayout