1. 程式人生 > >Android中ScrollView如何監聽滑動距離(總結)

Android中ScrollView如何監聽滑動距離(總結)

需求:想實現像美團中列表下拉後出現懸浮窗的效果。

思路:首先對ScrollView進行滑動監聽,然後在onScrollChanged()方法中獲取到滑動的Y值,接著進行相關操作即可。

實現步驟:

1、自定義MyScrollView

(1)重寫onScrollChanged()獲取Y值。

(2)自定義滑動監聽介面onScrollListener並公開此介面。

public class MyScrollView extends ScrollView {

    private OnScrollListener onScrollListener;

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

    @Override
    protected int computeVerticalScrollRange() {
        return super.computeVerticalScrollRange();
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (onScrollListener != null) {
            onScrollListener.onScroll(t);
        }
    }

    /**
     * 介面對外公開
     * @param onScrollListener
     */
    public void setOnScrollListener(OnScrollListener onScrollListener) {
        this.onScrollListener = onScrollListener;
    }

    /**
     *
     * 滾動的回撥介面
     *
     * @author xiaanming
     *
     */
    public interface OnScrollListener{
        /**
         * 回撥方法, 返回MyScrollView滑動的Y方向距離
         * @param scrollY
         *              、
         */
        void onScroll(int scrollY);
    }
}

2、佈局檔案如下:

(主要是建立兩個相同的佈局,頂部一個,相應的位置一個,後面有用)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:id="@+id/parent_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <com.deepreality.myscrollviewxfdemo.MyScrollView
        android:id="@+id/Main_SView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <ImageView
                    android:layout_width="match_parent"
                    android:layout_height="150dp"
                    android:scaleType="fitXY"
                    android:src="@mipmap/img2" />

                <RelativeLayout
                    android:id="@+id/Main_rView1"
                    android:layout_width="match_parent"
                    android:layout_height="50dp"
                    android:background="@color/colorWhite">

                    <ImageView
                        android:layout_width="50dp"
                        android:layout_height="50dp"
                        android:layout_alignParentLeft="true"
                        android:layout_centerVertical="true"
                        android:padding="10dp"
                        android:scaleType="fitXY"
                        android:src="@mipmap/icon_user_nickname" />

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="你好"
                        android:layout_centerInParent="true"/>

                    <ImageView
                        android:layout_width="50dp"
                        android:layout_height="50dp"
                        android:layout_alignParentRight="true"
                        android:layout_centerVertical="true"
                        android:padding="10dp"
                        android:scaleType="fitXY"
                        android:src="@mipmap/tips" />

                </RelativeLayout>

                <ImageView
                    android:layout_width="match_parent"
                    android:layout_height="150dp"
                    android:layout_marginTop="10dp"
                    android:scaleType="fitXY"
                    android:src="@mipmap/img2" />
                
                ……(程式碼省略)
                
            </LinearLayout>

            <RelativeLayout
                android:id="@+id/Main_rView"
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:background="@color/colorWhite">

                <ImageView
                    android:layout_width="50dp"
                    android:layout_height="50dp"
                    android:layout_alignParentLeft="true"
                    android:layout_centerVertical="true"
                    android:padding="10dp"
                    android:scaleType="fitXY"
                    android:src="@mipmap/icon_user_nickname" />

                <ImageView
                    android:layout_width="50dp"
                    android:layout_height="50dp"
                    android:layout_alignParentRight="true"
                    android:layout_centerVertical="true"
                    android:padding="10dp"
                    android:scaleType="fitXY"
                    android:src="@mipmap/tips" />

            </RelativeLayout>

        </FrameLayout>

    </com.deepreality.myscrollviewxfdemo.MyScrollView>

</LinearLayout>

3、MainActivity.java的程式碼如下:

public class MainActivity extends AppCompatActivity implements MyScrollView.OnScrollListener {

    private Context mContext;

    private RelativeLayout rTopView, rView1;
    private MyScrollView myScrollView;
    private LinearLayout lLayoutParent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        baseDataInit();
        bindViews();
        viewsAddListener();

    }

    private void baseDataInit() {
        mContext = this;
    }

    private void bindViews() {
        rTopView = findViewById(R.id.Main_rView);
        rView1 = findViewById(R.id.Main_rView1);
        myScrollView = findViewById(R.id.Main_SView);
        lLayoutParent = findViewById(R.id.parent_layout);
    }

    private void viewsAddListener() {
        //當佈局的狀態或者控制元件的可見性發生改變回調的介面
        lLayoutParent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                //這一步很重要,使得上面的購買佈局和下面的購買佈局重合
                onScroll(myScrollView.getScrollY());
            }
        });
        myScrollView.setOnScrollListener(this);
    }

    @Override
    public void onScroll(int scrollY) {
        int mBuyLayout2ParentTop = Math.max(scrollY, rView1.getTop());
        rTopView.layout(0, mBuyLayout2ParentTop, rTopView.getWidth(), mBuyLayout2ParentTop + rTopView.getHeight());
    }
}

其中,onScroll()介面方法中監聽到的是垂直方向滑動的距離Y,可以根據自己的需要進行佈局的其他操作。