溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Android如何實現(xiàn)類似UC瀏覽器的效果向上滑動地址欄隱藏功能

發(fā)布時間:2021-07-21 14:40:00 來源:億速云 閱讀:159 作者:小新 欄目:移動開發(fā)

這篇文章主要介紹了Android如何實現(xiàn)類似UC瀏覽器的效果向上滑動地址欄隱藏功能,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

思路

要求

ScrollView 嵌套 地址欄 和 WebView

手指滑屏向下滾動(網(wǎng)頁向上),如果網(wǎng)頁有滾動條,首先把 地址欄 滾動到消失,然后 WebView 才開始滾動;

手指滑屏向上滾動(網(wǎng)頁向下),如果地址欄隱藏,那么 地址欄 首先慢慢顯示,然后 WebView 才開始滾動。

實現(xiàn)方案

  • 根據(jù) View 的 onInterceptTouchEvent 和 onTouchEvent 原理。把 ScrollView 設(shè)置為 WebView 的一個變量,在 WebView的 onInterceptTouchEvent 方法里檢測到 MotionEvent.ACTION_DOWN 事件后中斷事件,在 WebView 的 onTouchEvent 事件中根據(jù)具體情況決定是把 MotionEvent.ACTION_MOVE 事件傳送給 ScrollView 還是留給自己

  • 由于MotionEvent.ACTION_MOVE 事件傳送給 ScrollView 后無法在一次 Touch 事件中再接收,所以會導(dǎo)致如果有地址欄,向下滑動第一次只能滑動到 ScrollView 消失

  • +

  • Hack網(wǎng)頁,加入JS腳本,前行讓網(wǎng)頁頂部空出來一段空白,空白處覆蓋地址欄

  • 優(yōu)點是WebView大小不變化,容易控制

  • 缺點是比較復(fù)雜要處理各種網(wǎng)頁元素,各種 position 情況,實現(xiàn)復(fù)雜,效率低

  • 由手勢接管所有觸發(fā)操作,再由它分發(fā)給需要滾動的控件

本文方法

資源

SrollView下面包含節(jié)點地址欄,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 邏輯分發(fā) - 決定是滑動webview還是改變webview高度從而改變ScrollView滾動范圍(ScrollView總是滾動到最底)

WebView 重畫之后檢測當(dāng)前地址欄偏移

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);
    }
   });
  }
 }
}

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“Android如何實現(xiàn)類似UC瀏覽器的效果向上滑動地址欄隱藏功能”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI