滚动监听的一些

参考:
RecyclerView的滚动事件分析
判断view能否上滑

listview的分页
android - 标题栏随ScrollView滚动变色(仿知乎)
ViewPager的setOnPageChangeListener方法详解

一、ListView的滚动监听

布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    tools:context="com.example.lenovo.myscrolltest.MainActivity">

    <ListView
        android:id="@+id/lv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:entries="@array/sports" />

</LinearLayout>

res/values/arrays:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="sports">
        <item>1</item>
        <item>2</item>
        <item>3</item>
        <item>4</item>
        <item>5</item>
        <item>6</item>
        <item>7</item>
        <item>8</item>
        <item>9</item>
        <item>10</item>
        <item>11</item>
        <item>12</item>
        <item>13</item>
        <item>14</item>
        <item>15</item>
        <item>16</item>
        <item>17</item>
        <item>18</item>
        <item>19</item>
        <item>20</item>
        <item>21</item>
        <item>22</item>
        <item>23</item>
        <item>24</item>
        <item>25</item>
        <item>26</item>
        <item>27</item>
        <item>28</item>
        <item>29</item>
        <item>30</item>
    </string-array>
</resources>

测试MainActivity


public class MainActivity extends AppCompatActivity {

    private ListView mLv;

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

        mLv = ((ListView) this.findViewById(R.id.lv));

        //滚动位移的监听
        mLv.setOnScrollChangeListener(new View.OnScrollChangeListener() {
            @Override
            public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
                //ListView无水平滑动,scrollX和oldScrollX均为零
//                    Log.e("333333", "scrollX==" + scrollX);
//                    Log.e("333333", "oldScrollX====" + oldScrollX);
                Log.e("333333", "scrollY==" + scrollY);
                Log.e("333333", "oldScrollY===" + oldScrollY);
                Log.e("333333", "v instanceof ListView===" + (v instanceof ListView));
                Log.e("333333", "============================================");
            }
        });

        //滚动状态和位置监听
        mLv.setOnScrollListener(new AbsListView.OnScrollListener() {

            /**
             * 监听着ListView的滑动状态改变
             * @param view
             * @param scrollState
             */
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                switch (scrollState) {
                    //页面正被用户拖拽(手指未离开)
                    case SCROLL_STATE_TOUCH_SCROLL:
                        Log.e("222222", "111===SCROLL_STATE_TOUCH_SCROLL===");
                        break;

                    //页面自行滑动,有动画效果(手指已离开):
                    //如果手指拖动离开后页面也停止,则不会调用,除非离开后页面还有惯性滑动
                    case SCROLL_STATE_FLING:
                        Log.e("222222", "222===SCROLL_STATE_FLING===");
                        break;

                    //页面停滞,无动画效果
                    case SCROLL_STATE_IDLE:
                        Log.e("222222", "333===SCROLL_STATE_IDLE===");
                        break;
                }
            }

            /**
             * 监听滑动位置
             * @param view
             * @param firstVisibleItem
             * @param visibleItemCount
             * @param totalItemCount
             */
            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                //firstVisibleItem和view.getFirstVisiblePosition()的值相同,表示第一个看到的item位置,半个也算
                Log.e("111111", "===firstVisibleItem==" + firstVisibleItem);//0
                Log.e("111111", "===getFirstVisiblePosition==" + view.getFirstVisiblePosition());//0

                //visibleItemCount==ListView可见的item总数,半个也算
                Log.e("111111", "===visibleItemCount==" + visibleItemCount);//11

                //totalItemCount==ListView的全部item总数(包括可见+不可见)
                Log.e("111111", "===totalItemCount==" + totalItemCount);//30

                //表示最后看到的item位置,半个也算
                Log.e("111111", "===getLastVisiblePosition==" + view.getLastVisiblePosition());//10

                //判断是否到了底部
                boolean isBottom = (firstVisibleItem + visibleItemCount) == totalItemCount;//19 + 11 == 30
                Log.e("111111", "===isBottom=====" + isBottom);

                Log.e("111111", "============================================");
            }
        });
    }

    /**
     * 下拉刷新时,判断控件是否可以上滑
     * 1、API大于等于14:调用canScrollVertically,当direction>0时,判断是否可以下滑,当direction<0时,判断是否可以上滑
     * 2、API小于14:自己判断
     *
     * @param view
     * @return
     */
    public boolean canChildScrollUp(View view) {
        if (android.os.Build.VERSION.SDK_INT < 14) {
            if (view instanceof AbsListView) {
                final AbsListView absListView = (AbsListView) view;
                return absListView.getChildCount() > 0
                        && (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0).getTop() < absListView.getPaddingTop());
            } else {
                return view.getScrollY() > 0;
            }
        } else {
            return view.canScrollVertically(-1);
        }
    }
}

注意:

canScrollVertically,当direction>0时,判断是否可以下滑,当direction<0时,判断是否可以上滑

二、ScrollView的滚动监听:

自定义带滚动监听的ScrollView

/**
 * 带滚动监听的ScrollView
 * 
 */
public class ObservableScrollView extends ScrollView {

    public interface ScrollViewListener {

        void onScrollChanged(ObservableScrollView scrollView, int x, int y, int oldx, int oldy);

    }

    private ScrollViewListener scrollViewListener = null;

    public ObservableScrollView(Context context) {
        super(context);
    }

    public ObservableScrollView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public ObservableScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setScrollViewListener(ScrollViewListener scrollViewListener) {
        this.scrollViewListener = scrollViewListener;
    }

    @Override
    protected void onScrollChanged(int x, int y, int oldx, int oldy) {
        super.onScrollChanged(x, y, oldx, oldy);
        if (scrollViewListener != null) {
            scrollViewListener.onScrollChanged(this, x, y, oldx, oldy);
        }
    }

}

布局:

<?xml version="1.0" encoding="utf-8"?>
<com.example.lenovo.myscrolltest.ObservableScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/scrollView"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="5dp"
            android:text="1"
            android:textColor="#ff0000"
            android:textSize="25sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="5dp"
            android:text="2"
            android:textColor="#ff0000"
            android:textSize="25sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="5dp"
            android:text="3"
            android:textColor="#ff0000"
            android:textSize="25sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="5dp"
            android:text="4"
            android:textColor="#ff0000"
            android:textSize="25sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="5dp"
            android:text="5"
            android:textColor="#ff0000"
            android:textSize="25sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="5dp"
            android:text="6"
            android:textColor="#ff0000"
            android:textSize="25sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="5dp"
            android:text="7"
            android:textColor="#ff0000"
            android:textSize="25sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="5dp"
            android:text="8"
            android:textColor="#ff0000"
            android:textSize="25sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="5dp"
            android:text="9"
            android:textColor="#ff0000"
            android:textSize="25sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="5dp"
            android:text="10"
            android:textColor="#ff0000"
            android:textSize="25sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="5dp"
            android:text="11"
            android:textColor="#ff0000"
            android:textSize="25sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="5dp"
            android:text="12"
            android:textColor="#ff0000"
            android:textSize="25sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="5dp"
            android:text="13"
            android:textColor="#ff0000"
            android:textSize="25sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="5dp"
            android:text="14"
            android:textColor="#ff0000"
            android:textSize="25sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="5dp"
            android:text="15"
            android:textColor="#ff0000"
            android:textSize="25sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="5dp"
            android:text="16"
            android:textColor="#ff0000"
            android:textSize="25sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="5dp"
            android:text="17"
            android:textColor="#ff0000"
            android:textSize="25sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="5dp"
            android:text="18"
            android:textColor="#ff0000"
            android:textSize="25sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="5dp"
            android:text="19"
            android:textColor="#ff0000"
            android:textSize="25sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="5dp"
            android:text="20"
            android:textColor="#ff0000"
            android:textSize="25sp" />

    </LinearLayout>
</com.example.lenovo.myscrolltest.ObservableScrollView>

测试MainActivityI


public class MainActivityI extends AppCompatActivity {

    private ListView mLv;
    private ObservableScrollView scrollview;

    @SuppressLint("NewApi")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maini);

        //一般View都有滚动监听,比如:RecyclerView,ListView
        RecyclerView recyclerView = new RecyclerView(this);
        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
            }

            //dy > 0 时为向上滚动
            //dy < 0 时为向下滚动
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
            }
        });
        //表示是否滚动到顶部,当direction>0时,判断是否可以下滑,当direction<0时,判断是否可以上滑
        recyclerView.canScrollVertically(-1);//View的内部方法

        ListView listView = new ListView(this);
        listView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
            @Override
            public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {

            }
        });
        //表示是否滚动到顶部,当direction>0时,判断是否可以下滑,当direction<0时,判断是否可以上滑
        listView.canScrollVertically(-1);//View的内部方法

        //ScrollView需要自己定义滚动监听
        scrollview = ((ObservableScrollView) this.findViewById(R.id.scrollView));

        scrollview.setOnScrollChangeListener(new View.OnScrollChangeListener() {
            @Override
            public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
                //水平无滚动,均为0
//                Log.e("000000", "111scrollX==" + scrollX);
//                Log.e("000000", "111oldScrollX==" + oldScrollX);
//                Log.e("000000", "111scrollX-oldScrollX==" + (scrollX - oldScrollX));

                //竖直滚动:scrollY为滚动的当前绝对位置,oldScrollY为上次滚动停止时的绝对位置
                Log.e("000000", "222scrollY==" + scrollY);
                Log.e("000000", "222oldScrollY==" + oldScrollY);
                //差值不为零表示有滚动操作,大于0上滑,小于0下滑
                Log.e("000000", "222scrollY-oldScrollY==" + (scrollY - oldScrollY));
//                Log.e("000000", "v instanceof ScrollView==" + (v instanceof ScrollView));
                Log.e("000000", "======================================================");
            }
        });
    }
}

注意:

//竖直滚动:
scrollY为滚动的当前绝对位置,起始为0
oldScrollY为上次滚动停止时的绝对位置

//差值不为零表示有滚动操作,大于0上滑,小于0下滑
dx = scrollX-oldScrollX
dy = scrollY-oldScrollY

打印log如下:

898 222scrollY==73
898 222oldScrollY==0
898 222scrollY-oldScrollY==73

915 222scrollY==281
915 222oldScrollY==73
915 222scrollY-oldScrollY==208

931 222scrollY==482
932 222oldScrollY==281
932 222scrollY-oldScrollY==201

948 222scrollY==665
948 222oldScrollY==482
948 222scrollY-oldScrollY==183
962 222scrollY==758
962 222oldScrollY==665
962 222scrollY-oldScrollY==93

965 222scrollY==796
965 222oldScrollY==758
965 222scrollY-oldScrollY==38
965 222scrollY==796
965 222oldScrollY==758
965 222scrollY-oldScrollY==38

982 222scrollY==1009
982 222oldScrollY==796
982 222scrollY-oldScrollY==213

982 222scrollY==1009
982 222oldScrollY==796
982 222scrollY-oldScrollY==213

999 222scrollY==1066
999 222oldScrollY==1009
999 222scrollY-oldScrollY==57

999 222scrollY==1066
999 222oldScrollY==1009
999 222scrollY-oldScrollY==57

033 222scrollY==1065
033 222oldScrollY==1066
033 222scrollY-oldScrollY==-1

033 222scrollY==1065
033 222oldScrollY==1066
033 222scrollY-oldScrollY==-1

050 222scrollY==1063
050 222oldScrollY==1065
050 222scrollY-oldScrollY==-2

050 222scrollY==1063
050 222oldScrollY==1065
050 222scrollY-oldScrollY==-2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现滚动监听到锚点,可以使用Vue的指令和一些JavaScript代码。 首先,我们可以使用Vue的指令来绑定滚动事件。在模板中,我们可以这样使用指令: ```html <div v-scroll="handleScroll"> <!-- content --> </div> ``` 然后,在Vue实例中,我们需要定义handleScroll方法来处理滚动事件。在这个方法中,我们可以使用JavaScript来获取到当前滚动的位置,再根据锚点的位置来判断是否需要触发滚动监听事件。代码如下: ```javascript methods: { handleScroll() { const anchors = document.querySelectorAll('a[id]') const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop for (let i = 0; i < anchors.length; i++) { const anchor = anchors[i] const offsetTop = anchor.getBoundingClientRect().top + scrollTop if (offsetTop <= scrollTop + 100) { // 触发滚动监听事件 this.$emit('scroll', anchor.getAttribute('id')) } } } } ``` 在这个方法中,我们首先使用document.querySelectorAll方法获取到所有带有id属性的锚点。然后,使用window.pageYOffset、document.documentElement.scrollTop和document.body.scrollTop来获取到当前的滚动位置。接着,遍历所有锚点,使用getBoundingClientRect方法获取到锚点相对于视口的位置,再加上scrollTop,就可以获取到锚点相对于文档的位置。如果当前滚动位置加上一个偏移量(这里是100)大于等于锚点的位置,就触发滚动监听事件。 最后,我们可以在父组件中监听scroll事件,来处理滚动到特定锚点的逻辑。代码如下: ```html <template> <div> <div v-scroll="handleScroll"> <!-- content --> </div> <div v-for="anchor in anchors" :key="anchor"> <a :href="'#' + anchor">{{ anchor }}</a> </div> </div> </template> <script> export default { data() { return { anchors: ['anchor1', 'anchor2', 'anchor3'] } }, methods: { handleScroll(anchor) { console.log('scroll to', anchor) } } } </script> ``` 在这个例子中,我们在父组件中定义了一个anchors数组,它包含了所有锚点的id。然后,在模板中,我们使用v-for指令来生成所有锚点的链接。当触发scroll事件时,我们可以获取到当前滚动到的锚点的id,并且在控制台输出它的值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值