91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

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

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

如何在Android中嵌套滾動NestedScroll

發布時間:2021-05-24 18:05:23 來源:億速云 閱讀:170 作者:Leah 欄目:移動開發

今天就跟大家聊聊有關如何在Android中嵌套滾動NestedScroll,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。

原理

NestedScroll的其實很簡單.

一般的觸摸消息的分發都是從外向內的,由外層的ViewGroup的dispatchTouchEvent方法調用到內層的View的dispatchTouchEvent方法.

而NestedScroll提供了一個反向的機制,內層的view在接收到ACTION_MOVE的時候,將滾動消息先傳回給外層的ViewGroup,看外層的ViewGroup是不是需要消耗一部分的移動,然后內層的View再去消耗剩下的移動.內層view可以消耗剩下的滾動的一部分,如果還沒有消耗完,外層的view可以再選擇把最后剩下的滾動消耗掉.

上面的描述可能有點繞,可以看下面的圖來幫助理解:

如何在Android中嵌套滾動NestedScroll 

具體實現

NestedScroll機制會涉及到四個類:

NestedScrollingChild, NestedScrollingChildHelper 和 NestedScrollingParent , NestedScrollingParentHelper

NestedScrollingChild和NestedScrollingParent是兩個接口,我們先看看他們的聲明:

public interface NestedScrollingChild {
  public void setNestedScrollingEnabled(boolean enabled);

  public boolean isNestedScrollingEnabled();

  public boolean startNestedScroll(int axes);

  public void stopNestedScroll();

  public boolean hasNestedScrollingParent();

  public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
      int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow);

  public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow);

  public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed);

  public boolean dispatchNestedPreFling(float velocityX, float velocityY);
}

public interface NestedScrollingParent {
  public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes);

  public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes);

  public void onStopNestedScroll(View target);

  public void onNestedScroll(View target, int dxConsumed, int dyConsumed,
      int dxUnconsumed, int dyUnconsumed);

  public void onNestedPreScroll(View target, int dx, int dy, int[] consumed);

  public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed);

  public boolean onNestedPreFling(View target, float velocityX, float velocityY);

  public int getNestedScrollAxes();
}

這里真正重要的其實是NestedScrollingParent的幾個方法,因為其他方法都能直接讓NestedScrollingChildHelper或者NestedScrollingParentHelper去代理:

  1. onStartNestedScroll 是否接受嵌套滾動,只有它返回true,后面的其他方法才會被調用

  2. onNestedPreScroll 在內層view處理滾動事件前先被調用,可以讓外層view先消耗部分滾動

  3. onNestedScroll 在內層view將剩下的滾動消耗完之后調用,可以在這里處理最后剩下的滾動

  4. onNestedPreFling 在內層view的Fling事件處理之前被調用

  5. onNestedFling 在內層view的Fling事件處理完之后調用

我們只要讓子view和父view分別實現NestedScrollingChild和NestedScrollingParent接口,然后分別調用NestedScrollingChildHelper和NestedScrollingParentHelper的對應方法去代理一些具體功能,然后在NestedScrollingChild的onTouchEvent那里根據需求調用startNestedScroll/dispatchNestedPreScroll/stopNestedScroll就能實現嵌套滾動了:

//NestedScrollingChild
private NestedScrollingChildHelper mHelper = new NestedScrollingChildHelper(this);

public boolean startNestedScroll(int axes) {
 return mHelper.startNestedScroll(axes);
}
public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
      int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) {
 return mHelper.dispatchNestedScroll(dxConsumed, dyConsumed,
       dxUnconsumed, dyUnconsumed, offsetInWindow);
}
...
//NestedScrollingParent
private NestedScrollingParentHelper mHelper = new NestedScrollingParentHelper(this);

public void onNestedScrollAccepted(View child, View target, int axes) {
 mHelper.onNestedScrollAccepted(child, target, axes);
}

public int getNestedScrollAxes() {
 return mHelper.getNestedScrollAxes();
}
...

但是如果你使用sdk21及以上的版本,NestedScroll機制已經直接集成到了View中了,你只需要直接重寫View的對應方法就好

布局

我們先看布局文件

<me.linjw.nestedscrolldemo.NestedScrollParentView xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical">

  <FrameLayout
    android:id="@+id/header"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
      android:layout_width="match_parent"
      android:layout_height="200dp"
      android:src="@mipmap/ic_launcher" />
  </FrameLayout>

  <TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/colorAccent"
    android:text="Title"
    android:textAlignment="center"
    android:textSize="20dp" />

  <android.support.v7.widget.RecyclerView
    android:id="@+id/list"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
</me.linjw.nestedscrolldemo.NestedScrollParentView>

最外層是我們自定義的NestedScrollParentView,其實它是一個LinearLayout,內部豎直排列了三個子view:

  1. 一個由FrameLayout包裹的ImageView

  2. 一個TextView

  3. 一個RecyclerView

代碼

為了簡便起見,我們先直接用sdk22的版本用重寫View方法的方式去實現它.

NestedScrollParentView中有兩個方法比較重要,嵌套滾動基本上就是由這兩個方法實現的:

@Override
 public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
   return true;
 }

 @Override
 public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
   super.onNestedPreScroll(target, dx, dy, consumed);

   boolean headerScrollUp = dy > 0 && getScrollY() < mHeaderHeight;
   boolean headerScrollDown = dy < 0 && getScrollY() > 0 && !target.canScrollVertically(-1);
   if (headerScrollUp || headerScrollDown) {
     scrollBy(0, dy);
     consumed[1] = dy;
   }
 }

onStartNestedScroll 這個方法如果返回true的話代表接受由內層傳來的滾動消息,我們直接返回true就好,否則后面的消息都接受不到

onNestedPreScroll 這個方法用于消耗內層view的一部分滾動.我們需要將消耗掉的滾動存到counsumed中讓consumed知道.例如我們這里在頂部的FrameLayout需要移動的情況下會消耗掉所有的dy,這樣內層的view(即RecyclerView)就不會滾動了.

這里的mHeaderHeight保存的是頂部的FrameLayout的高度:

@Override
  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    mHeaderHeight = mHeader.getMeasuredHeight();
  }

Android是什么

Android是一種基于Linux內核的自由及開放源代碼的操作系統,主要使用于移動設備,如智能手機和平板電腦,由美國Google公司和開放手機聯盟領導及開發。

看完上述內容,你們對如何在Android中嵌套滾動NestedScroll有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

武鸣县| 平舆县| 安龙县| 泉州市| 岫岩| 江源县| 武平县| 怀安县| 祁阳县| 绥芬河市| 西吉县| 潞西市| 西丰县| 哈密市| 唐山市| 西平县| 庄浪县| 斗六市| 蒙阴县| 广东省| 察雅县| 顺义区| 鄂尔多斯市| 凉城县| 磐石市| 玛沁县| 宜宾县| 孟州市| 广平县| 贵港市| 云霄县| 河津市| 贵南县| 穆棱市| 巴楚县| 普宁市| 资讯| 邯郸市| 利川市| 鄂伦春自治旗| 古浪县|