Android 类似UC浏览器的效果:向上滑动地址栏隐藏功能
思路
要求
ScrollView嵌套地址栏和WebView
手指滑屏向下滚动(网页向上),如果网页有滚动条,首先把地址栏滚动到消失,然后WebView才开始滚动;
手指滑屏向上滚动(网页向下),如果地址栏隐藏,那么地址栏首先慢慢显示,然后WebView才开始滚动。
实现方案
- 根据View的onInterceptTouchEvent和onTouchEvent原理。把ScrollView设置为WebView的一个变量,在WebView的onInterceptTouchEvent方法里检测到MotionEvent.ACTION_DOWN事件后中断事件,在WebView的onTouchEvent事件中根据具体情况决定是把MotionEvent.ACTION_MOVE事件传送给ScrollView还是留给自己
- 由于MotionEvent.ACTION_MOVE事件传送给ScrollView后无法在一次Touch事件中再接收,所以会导致如果有地址栏,向下滑动第一次只能滑动到ScrollView消失
- +
- Hack网页,加入JS脚本,前行让网页顶部空出来一段空白,空白处覆盖地址栏
- 优点是WebView大小不变化,容易控制
- 缺点是比较复杂要处理各种网页元素,各种position情况,实现复杂,效率低
- 由手势接管所有触发操作,再由它分发给需要滚动的控件
本文方法
资源
SrollView下面包含节点地址栏,WebView控件
ScrollView继承自ScrollView
onTouchEvent中阻止MotionEvent.ACTION_MOVE事件
publicclassMyScrollViewextendsScrollView{
publicMyScrollView(Contextcontext){
super(context);
}
publicMyScrollView(Contextcontext,AttributeSetattrs){
super(context,attrs);
}
publicMyScrollView(Contextcontext,AttributeSetattrs,intdefStyleAttr){
super(context,attrs,defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
publicMyScrollView(Contextcontext,AttributeSetattrs,intdefStyleAttr,intdefStyleRes){
super(context,attrs,defStyleAttr,defStyleRes);
}
@Override
publicbooleanonTouchEvent(MotionEventev){
if(ev.getAction()==MotionEvent.ACTION_MOVE){
returntrue;
}
returnsuper.onTouchEvent(ev);
}
}
MyWebView继承自WebView
onTouchEvent中阻止MotionEvent.ACTION_MOVE事件
onDrawListner
计算竖直滚动范围
publicclassMyWebViewextendsWebView{
publicinterfaceMyWebViewListener{
voidafterDraw(WebViewwebView);
}
privateMyWebViewListenermListener;
privateintmMoveCheckedCnt;
publicMyWebView(Contextcontext){
super(context);
}
publicMyWebView(Contextcontext,AttributeSetattrs){
super(context,attrs);
}
publicMyWebView(Contextcontext,AttributeSetattrs,intdefStyleAttr){
super(context,attrs,defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
publicMyWebView(Contextcontext,AttributeSetattrs,intdefStyleAttr,intdefStyleRes){
super(context,attrs,defStyleAttr,defStyleRes);
}
publicMyWebView(Contextcontext,AttributeSetattrs,intdefStyleAttr,booleanprivateBrowsing){
super(context,attrs,defStyleAttr,privateBrowsing);
}
publicvoidsetListener(MyWebViewListenerlistener){
mListener=listener;
}
@Override
publicbooleanonTouchEvent(MotionEventevent){
switch(event.getAction()){
caseMotionEvent.ACTION_DOWN:
mMoveCheckedCnt=0;
flingScroll(0,0);
break;
caseMotionEvent.ACTION_MOVE:
mMoveCheckedCnt++;
returnfalse;
caseMotionEvent.ACTION_UP:
if(mMoveCheckedCnt>=2){
event.setAction(MotionEvent.ACTION_CANCEL);
mMoveCheckedCnt=0;
}
break;
}
returnsuper.onTouchEvent(event);
}
@Override
protectedvoidonDraw(Canvascanvas){
super.onDraw(canvas);
MyWebViewListenerlistener=mListener;
if(listener!=null){
listener.afterDraw(this);
}
}
publicintgetVScrollRange(){
intv=computeVerticalScrollRange()-computeVerticalScrollExtent();
if(v<0){
v=0;
}
returnv;
}
}
主窗口
GlobalLayoutListener获取地址栏和滚动视图高度
GestureDetector逻辑分发-决定是滑动webview还是改变webview高度从而改变ScrollView滚动范围(ScrollView总是滚动到最底)
WebView重画之后检测当前地址栏偏移
publicclassMainActivityextendsAppCompatActivityimplementsMyWebView.MyWebViewListener{
MyWebViewmWebView;
GestureDetectormGesture=null;
ViewmToolBar;
intmToolBarHeight;
MyScrollViewmScrollView;
intmScrollViewHeight;
intmScrollOffset;
EditTextmUrlEdit;
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView=(MyWebView)findViewById(R.id.webView);
mWebView.setWebViewClient(newWebViewClient(){
@Override
publicbooleanshouldOverrideUrlLoading(WebViewview,Stringurl){
returnfalse;
}
});
mWebView.setListener(this);
mWebView.loadUrl("http://www.sohu.com");
mUrlEdit=(EditText)findViewById(R.id.urlEdit);
findViewById(R.id.goButton).setOnClickListener(newView.OnClickListener(){
@Override
publicvoidonClick(Viewv){
Stringurl=mUrlEdit.getText().toString();
if(!url.startsWith("http://")&&!url.startsWith("https://")){
url="http://"+url;
}
mWebView.loadUrl(url);
}
});
mToolBar=findViewById(R.id.toolBar);
mScrollView=(MyScrollView)findViewById(R.id.scrollView);
ScrollViewscrollView=(ScrollView)mScrollView;
findViewById(R.id.root).getViewTreeObserver().addOnGlobalLayoutListener(newViewTreeObserver.OnGlobalLayoutListener(){
@Override
publicvoidonGlobalLayout(){
mToolBarHeight=mToolBar.getHeight();
mScrollViewHeight=mScrollView.getHeight();
adjustScrollView();
}
});
mGesture=newGestureDetector(this,newGestureListener());
}
@Override
publicbooleandispatchTouchEvent(MotionEventev){
mGesture.onTouchEvent(ev);
returnsuper.dispatchTouchEvent(ev);
}
@Override
publicvoidafterDraw(WebViewwebView){
if(mWebView.getVScrollRange()0){
//scrollup,thewebwillscrolldown
if(mScrollOffset>=mToolBarHeight||mScrollOffset>=mWebView.getVScrollRange()){
returnfalse;
}
mScrollOffset+=distanceY;
if(mScrollOffset>mToolBarHeight){
mScrollOffset=mToolBarHeight;
}
if(mScrollOffset>mWebView.getVScrollRange()){
mScrollOffset=mWebView.getVScrollRange();
}
}else{
if(mScrollOffset<=0){
returnfalse;
}
mScrollOffset+=distanceY;
if(mScrollOffset<=0){
mScrollOffset=0;
}
}
adjustScrollView();
returntrue;
}
privatevoidadjustScrollView(){
Log.e("Temp","offsetis"+mScrollOffset);
ViewGroup.LayoutParamslayoutParams=mWebView.getLayoutParams();
intnewHeight=(mScrollViewHeight-mToolBarHeight)+mScrollOffset;
Log.e("Temp","newHeightis"+newHeight+",layoutParams.height"+layoutParams.height);
if(newHeight!=layoutParams.height){
layoutParams.height=newHeight;
mWebView.setLayoutParams(layoutParams);
newHandler(Looper.getMainLooper()).post(newRunnable(){
@Override
publicvoidrun(){
mScrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
});
}
}
}
总结
以上所述是小编给大家介绍的Android类似UC浏览器的效果:向上滑动地址栏隐藏功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!