软件编程
位置:首页>> 软件编程>> Android编程>> Android 类似UC浏览器的效果:向上滑动地址栏隐藏功能

Android 类似UC浏览器的效果:向上滑动地址栏隐藏功能

作者:stwstw0123  发布时间:2023-01-29 05:01:41 

标签:android,滑动,隐藏,向上滑动

思路

要求

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控件


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="@+id/root"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<samples.zjc.com.testbrowserfeature.MyScrollView
 android:id="@+id/scrollView"
 android:scrollbars="none"
 android:layout_width="match_parent"
 android:layout_height="match_parent">
 <LinearLayout
  android:orientation="vertical"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
  <LinearLayout
   android:id="@+id/toolBar"
   android:background="#5ff0"
   android:orientation="horizontal"
   android:layout_width="match_parent"
   android:layout_height="wrap_content">
   <EditText
    android:id="@+id/urlEdit"
    android:layout_weight="1"
    android:layout_width="0dp"
    android:layout_height="wrap_content"/>
   <Button
    android:id="@+id/goButton"
    android:text="Go"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
  </LinearLayout>
  <samples.zjc.com.testbrowserfeature.MyWebView
   android:id="@+id/webView"
   android:layout_width="match_parent"
   android:layout_height="100dp" />
 </LinearLayout>
</samples.zjc.com.testbrowserfeature.MyScrollView>
</RelativeLayout>

ScrollView继承自 ScrollView


onTouchEvent 中阻止 MotionEvent.ACTION_MOVE 事件
public class MyScrollView extends ScrollView {
public MyScrollView(Context context) {
 super(context);
}
public MyScrollView(Context context, AttributeSet attrs) {
 super(context, attrs);
}
public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
 super(context, attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
 super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
 if(ev.getAction() == MotionEvent.ACTION_MOVE) {
  return true;
 }
 return super.onTouchEvent(ev);
}
}

MyWebView继承自 WebView

onTouchEvent 中阻止 MotionEvent.ACTION_MOVE 事件

onDrawListner

计算竖直滚动范围


public class MyWebView extends WebView {
public interface MyWebViewListener {
 void afterDraw(WebView webView);
}
private MyWebViewListener mListener;
private int mMoveCheckedCnt;
public MyWebView(Context context) {
 super(context);
}
public MyWebView(Context context, AttributeSet attrs) {
 super(context, attrs);
}
public MyWebView(Context context, AttributeSet attrs, int defStyleAttr) {
 super(context, attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public MyWebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
 super(context, attrs, defStyleAttr, defStyleRes);
}
public MyWebView(Context context, AttributeSet attrs, int defStyleAttr, boolean privateBrowsing) {
 super(context, attrs, defStyleAttr, privateBrowsing);
}
public void setListener(MyWebViewListener listener) {
 mListener = listener;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
 switch (event.getAction()) {
  case MotionEvent.ACTION_DOWN:
   mMoveCheckedCnt = 0;
   flingScroll(0, 0);
   break;
  case MotionEvent.ACTION_MOVE:
   mMoveCheckedCnt++;
   return false;
  case MotionEvent.ACTION_UP:
   if(mMoveCheckedCnt >= 2) {
    event.setAction(MotionEvent.ACTION_CANCEL);
    mMoveCheckedCnt = 0;
   }
   break;
 }
 return super.onTouchEvent(event);
}
@Override
protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);
 MyWebViewListener listener = mListener;
 if(listener != null) {
  listener.afterDraw(this);
 }
}
public int getVScrollRange() {
 int v = computeVerticalScrollRange() - computeVerticalScrollExtent();
 if(v < 0) {
  v = 0;
 }
 return v;
}
}

主窗口

GlobalLayoutListener 获取地址栏和滚动视图高度

GestureDetector 逻辑分发 - 决定是滑动webview还是改变webview高度从而改变ScrollView滚动范围(ScrollView总是滚动到最底)

WebView 重画之后检测当前地址栏偏移


public class MainActivity extends AppCompatActivity implements MyWebView.MyWebViewListener {
MyWebView mWebView;
GestureDetector mGesture = null;
View mToolBar;
int mToolBarHeight;
MyScrollView mScrollView;
int mScrollViewHeight;
int mScrollOffset;
EditText mUrlEdit;
@Override
protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 mWebView = (MyWebView) findViewById(R.id.webView);
 mWebView.setWebViewClient(new WebViewClient() {
  @Override
  public boolean shouldOverrideUrlLoading(WebView view, String url) {
   return false;
  }
 });
 mWebView.setListener(this);
 mWebView.loadUrl("http://www.sohu.com");
 mUrlEdit = (EditText) findViewById(R.id.urlEdit);
 findViewById(R.id.goButton).setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
   String url = 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);
 ScrollView scrollView = (ScrollView) mScrollView;
 findViewById(R.id.root).getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
  @Override
  public void onGlobalLayout() {
   mToolBarHeight = mToolBar.getHeight();
   mScrollViewHeight = mScrollView.getHeight();
   adjustScrollView();
  }
 });
 mGesture = new GestureDetector(this, new GestureListener());
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
 mGesture.onTouchEvent(ev);
 return super.dispatchTouchEvent(ev);
}
@Override
public void afterDraw(WebView webView) {
 if (mWebView.getVScrollRange() < mScrollOffset) {
  mScrollOffset = mWebView.getVScrollRange();
  adjustScrollView();
 }
}
class GestureListener extends GestureDetector.SimpleOnGestureListener {
 @Override
 public boolean onDoubleTap(MotionEvent e) {
  Log.e("Temp", "onDoubleTap");
  return super.onDoubleTap(e);
 }
 @Override
 public boolean onDown(MotionEvent e) {
  Log.e("Temp", "onDown");
  return super.onDown(e);
 }
 @Override
 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
       float velocityY) {
  Log.e("Temp", "onFling:velocityX = " + velocityX + " velocityY" + velocityY);
  int effectX = (int) velocityX;
  int effectY = (int) velocityY;
  if (effectOnScrollViewByScroll((velocityY < 0 ? 1 : -1) * 8000)) {
   effectY = 0;
  }
  mWebView.flingScroll(-effectX, -effectY);
  return super.onFling(e1, e2, velocityX, velocityY);
 }
 @Override
 public void onLongPress(MotionEvent e) {
  Log.e("Temp", "onLongPress");
  super.onLongPress(e);
 }
 @Override
 public boolean onScroll(MotionEvent e1, MotionEvent e2,
       float distanceX, float distanceY) {
  Log.e("Temp", "onScroll:distanceX = " + distanceX + " distanceY = " + distanceY);
  int effectX = (int) distanceX;
  int effectY = (int) distanceY;
  if (effectOnScrollViewByScroll((int) distanceY)) {
   effectY = 0;
  }
  mWebView.scrollBy(effectX, effectY);
  return super.onScroll(e1, e2, distanceX, distanceY);
 }
 @Override
 public boolean onSingleTapUp(MotionEvent e) {
  Log.e("Temp", "onSingleTapUp");
  return super.onSingleTapUp(e);
 }
}
private boolean effectOnScrollViewByScroll(int distanceY) {
 if (distanceY > 0) {
  // scroll up, the web will scroll down
  if (mScrollOffset >= mToolBarHeight || mScrollOffset >= mWebView.getVScrollRange()) {
   return false;
  }
  mScrollOffset += distanceY;
  if (mScrollOffset > mToolBarHeight) {
   mScrollOffset = mToolBarHeight;
  }
  if (mScrollOffset > mWebView.getVScrollRange()) {
   mScrollOffset = mWebView.getVScrollRange();
  }
 } else {
  if (mScrollOffset <= 0) {
   return false;
  }
  mScrollOffset += distanceY;
  if (mScrollOffset <= 0) {
   mScrollOffset = 0;
  }
 }
 adjustScrollView();
 return true;
}
private void adjustScrollView() {
 Log.e("Temp", "offset is " + mScrollOffset);
 ViewGroup.LayoutParams layoutParams = mWebView.getLayoutParams();
 int newHeight = (mScrollViewHeight - mToolBarHeight) + mScrollOffset;
 Log.e("Temp", "newHeight is " + newHeight + ", layoutParams.height" + layoutParams.height);
 if (newHeight != layoutParams.height) {
  layoutParams.height = newHeight;
  mWebView.setLayoutParams(layoutParams);
  new Handler(Looper.getMainLooper()).post(new Runnable() {
   @Override
   public void run() {
    mScrollView.fullScroll(ScrollView.FOCUS_DOWN);
   }
  });
 }
}
}

总结

以上所述是小编给大家介绍的Android 类似UC浏览器的效果:向上滑动地址栏隐藏功能网站的支持!

来源:http://blog.csdn.net/stwstw0123/article/details/49335303

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com