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浏览器的效果:向上滑动地址栏隐藏功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!