ScrollView作为一个支持可以垂直滑动的容器控件,如果不对它进行拓展,而是简单使用的话那确实比较简单。但是,它虽然简单,拓展性能却很强。比如可以实现阻尼效果,可以监听滑动情况,可以解决滑动冲突问题等。那下面就开始逐一讲解一下。

有时候我们需要监听ScroView的滑动情况,比如滑动了多少距离,是否滑到布局的顶部或者底部。可惜的是SDK并没有相应的方法,不过倒是提供了一个

protected void onScrollChanged(int x, int y, int oldx, int oldy)

方法,显然这个方法是不能被外界调用的,因此就需要把它暴露出去,方便使用。解决方式就是写一个接口,

package com.example.demo1;public interface ScrollViewListener {void onScrollChanged(ObservableScrollView scrollView, int x, int y, int oldx, int oldy);}

然后重写ScrollView类,给它提供上面写的回调接口。

package com.example.demo1;import android.content.Context;
import android.util.AttributeSet;
import android.widget.ScrollView;public class ObservableScrollView extends ScrollView {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;}@Overrideprotected 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布局的时候,不要写错了包。

<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"android:orientation="horizontal"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context=".MainActivity" ><com.example.demo1.ObservableScrollViewandroid:id="@+id/view1"android:layout_width="wrap_content"android:layout_height="match_parent" ><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="match_parent"android:orientation="vertical" ><TextViewandroid:layout_width="100dp"android:layout_height="100dp"android:text="试试1" /><TextViewandroid:layout_width="100dp"android:layout_height="100dp"android:text="试试2" /><TextViewandroid:layout_width="100dp"android:layout_height="100dp"android:text="试试3" /><TextViewandroid:layout_width="100dp"android:layout_height="100dp"android:text="试试4" /><TextViewandroid:layout_width="100dp"android:layout_height="100dp"android:text="试试5" /><TextViewandroid:layout_width="100dp"android:layout_height="100dp"android:text="试试6" /></LinearLayout></com.example.demo1.ObservableScrollView><com.example.demo1.ObservableScrollViewandroid:id="@+id/view2"android:layout_width="wrap_content"android:layout_height="match_parent" ><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="match_parent"android:orientation="vertical" ><TextViewandroid:layout_width="100dp"android:layout_height="100dp"android:text="试试1" /><TextViewandroid:layout_width="100dp"android:layout_height="100dp"android:text="试试2" /><TextViewandroid:layout_width="100dp"android:layout_height="100dp"android:text="试试3" /><TextViewandroid:layout_width="100dp"android:layout_height="100dp"android:text="试试4" /><TextViewandroid:layout_width="100dp"android:layout_height="100dp"android:text="试试5" /><TextViewandroid:layout_width="100dp"android:layout_height="100dp"android:text="试试6" /></LinearLayout></com.example.demo1.ObservableScrollView></LinearLayout>

最后activity代码如下,

package com.example.demo1;import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;public class MainActivity extends Activity implements ScrollViewListener {private ObservableScrollView scrollView1 = null;private ObservableScrollView scrollView2 = null;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);scrollView1 = (ObservableScrollView) findViewById(R.id.view1);scrollView1.setScrollViewListener(this);scrollView2 = (ObservableScrollView) findViewById(R.id.view2);scrollView2.setScrollViewListener(this);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}@Overridepublic void onScrollChanged(ObservableScrollView scrollView, int x, int y,int oldx, int oldy) {if (scrollView == scrollView1) {scrollView2.scrollTo(x, y);} else if (scrollView == scrollView2) {scrollView1.scrollTo(x, y);}}}

上面这种方法主要是通过重写ScrollView来实现的,在主程序中无需再做额外操作。另外,还要一个方法就是不改动ScrollView,而是在主程序中进行操作,方式就是在触摸监听事件中,设立对手势的监听,在手指离开屏幕后用

 handler.sendMessageDelayed(handler.obtainMessage(TOUCH_EVENT_ID,scroller), 5);

每隔5毫秒getScrollY()一次,然后比较getScrollY()的值,直到与上次得到的相等时,就是scrollview停止滑动了。

mScrollView.setOnTouchListener(new OnTouchListener() {private int lastY = 0;private static final int TOUCH_EVENT_ID = 1;@Overridepublic boolean onTouch(View v, MotionEvent event) {// TODO Auto-generated method stubif(event.getAction() == MotionEvent.ACTION_UP) {//触摸松手时handler.sendMessageDelayed(handler.obtainMessage(TOUCH_EVENT_ID,v), 5);}return false;}Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);View scroller = (View)msg.obj;if(msg.what==TOUCH_EVENT_ID) {if(lastY ==scroller.getScrollY()) {handleStop(scroller);//调用停止时处理方法}else {handler.sendMessageDelayed(handler.obtainMessage(TOUCH_EVENT_ID,scroller), 5);lastY = scroller.getScrollY();}}}};

//这里写真正的事件

      private void handleStop(Object view) {//滑动停止时要进行的处理ScrollView scroller = (ScrollView) view;scroller.scrollTo(0, mScrollOffset);}

当然,也可以把他们都封装在一起,方便使用:

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ScrollView;public class LazyScrollView extends ScrollView{private static final String tag="LazyScrollView";private Handler handler;private View view;public LazyScrollView(Context context) {super(context);// TODO Auto-generated constructor stub}public LazyScrollView(Context context, AttributeSet attrs) {super(context, attrs);// TODO Auto-generated constructor stub}public LazyScrollView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);// TODO Auto-generated constructor stub}//这个获得总的高度public int computeVerticalScrollRange(){return super.computeHorizontalScrollRange();}public int computeVerticalScrollOffset(){return super.computeVerticalScrollOffset();}private void init(){this.setOnTouchListener(onTouchListener);handler=new Handler(){@Overridepublic void handleMessage(Message msg) {// process incoming messages heresuper.handleMessage(msg);switch(msg.what){case 1:if(view.getMeasuredHeight() <= getScrollY() + getHeight()) {if(onScrollListener!=null){onScrollListener.onBottom();}}else if(getScrollY()==0){if(onScrollListener!=null){onScrollListener.onTop();}}else{if(onScrollListener!=null){onScrollListener.onScroll();}}break;default:break;}}};}OnTouchListener onTouchListener=new OnTouchListener(){@Overridepublic boolean onTouch(View v, MotionEvent event) {// TODO Auto-generated method stubswitch (event.getAction()) {case MotionEvent.ACTION_DOWN:break;case MotionEvent.ACTION_UP:if(view!=null&&onScrollListener!=null){handler.sendMessageDelayed(handler.obtainMessage(1), 200);}break;default:break;}return false;}};/*** 获得参考的View,主要是为了获得它的MeasuredHeight,然后和滚动条的ScrollY+getHeight作比较。*/public void getView(){this.view=getChildAt(0);if(view!=null){init();}}/*** 定义接口* @author admin**/public interface OnScrollListener{void onBottom();void onTop();void onScroll();}private OnScrollListener onScrollListener;public void setOnScrollListener(OnScrollListener onScrollListener){this.onScrollListener=onScrollListener;}
}

通常这样使用:

scrollView=(LazyScrollView)findViewById(R.id.scrollView);scrollView.getView();scrollView.setOnScrollListener(new OnScrollListener() {@Overridepublic void onTop() {// TODO Auto-generated method stubLog.d(tag,"------滚动到最上方------");}@Overridepublic void onScroll() {// TODO Auto-generated method stubLog.d(tag,"没有到最下方,也不是最上方");}@Overridepublic void onBottom() {// TODO Auto-generated method stubLog.d(tag,"------滚动到最下方------");}});

Android ScrollView用法实例汇总相关推荐

  1. android 用户界面教程实例汇总

    1.android用户界面之WebView教程实例汇总 http://www.apkbus.com/android-51718-1-1.html 2.android用户界面之Notification教 ...

  2. Python中Text函数常用增删改查阅用法实例汇总

    本篇文章:主要讲解python的Text函数的常见用法,说明了常见用法的相关实例教程 日期:2022年1月27日 Text函数的显示 以下参数和信息为部分Text的函数参数,汇总的一些常用的参数和实例 ...

  3. html鼠标键弹起事件,js鼠标按键事件和键盘按键事件用法实例汇总

    本文实例讲述了js鼠标按键事件和键盘按键事件用法.分享给大家供大家参考,具体如下: keydown,keyup,keypress:属于你的键盘按键 mousedown,mouseup:属于你的鼠标按键 ...

  4. mysql list dbs 代替_mysql_list_dbs函数的用法实例汇总

    这篇文章主要介绍了php mysql_list_dbs()函数用法,简单介绍了mysql_list_dbs()函数的功能及列出mysql所有数据库的实现技巧,需要的朋友可以参考下本文实例讲述了php ...

  5. js鼠标按键事件和键盘按键事件用法实例汇总

    http://blog.csdn.net/xiaoya_syt/article/details/69951398 转载于:https://www.cnblogs.com/xiaobai-y/p/696 ...

  6. android网络通信之HTTP协议教程实例汇总

    在现在的开发和应用中,网络通讯是必不可少的.虽然还是比较怀念小时候,抱着一台95在那里玩单机游戏玩的天昏地暗的时光,但是,现在,就算一个幼儿园的小盆友如果问你要手机玩游戏,突然发现居然买不了冰激凌草莓 ...

  7. Android知识点及资料汇总(不断更新中)

    /// //版本:0.1 //主要内容:根据思维导图的知识点,对之前收藏夹的内容进行分类. /// 之前转载过一篇题目为<一张思维导图,告诉你Android新手如何快速入门>的文章,这篇文 ...

  8. Android系统学习(37)---Android知识点及资料汇总

    Android知识点及资料汇总 废话不多说,直接上总结: Android入门方法和经验之谈 如何自学 Android 编程? 如何零基础学习安卓开发? 我是如何自学,资料分享 一张Android学习的 ...

  9. Android 开源项目分类汇总(下)

    Android 开源项目分类汇总(下) 九.ScrollView Discrollview 支持滚动时 Item 淡入淡出,平移,缩放效果的 ScrollView 项目地址:https://githu ...

最新文章

  1. mega_[MEGA DEAL]完整的Java捆绑包(96%折扣)
  2. 绿色计算在数据中心的应用及节能效果浅析
  3. 【系列7】使用Dockerfile创建带mysql的Centos Docker镜像
  4. JavaScript内存管理
  5. 【luogu P4114 Qtree1】 题解
  6. .NET配置文件的10大安全漏洞
  7. 【云栖精选】6篇深度!解除MySQL数据同步疑惑+Docker技术示例
  8. Mendix的Hybrid App本地开发最佳实践
  9. macos设置环境变量path详解
  10. 车牌识别ocr为何物—科技普及大讲堂1
  11. 【云原生之Docker实战】使用Docker部署OpenKM文档管理系统
  12. python怎么交换xy轴_matplotlib Y轴和X轴交换
  13. 二叉搜索树(城市数据库)
  14. Excel 用函数自定义验证数据的有效性
  15. 【OpenCV入门教程之一】 安装OpenCV:OpenCV 3.0、OpenCV 2.4.8、OpenCV 2.4.9 +VS 开发环境配置
  16. 【Proteus仿真】键盘矩阵扫描+LCD128x64显示
  17. Spring-aop面向切面
  18. 解决win11/win10在登陆界面(解锁界面)点击获取每日壁纸无效的问题 - get Daily Lockscreen and Wallpaper - Win11/10的登录界面背景图片在哪里?
  19. Python将csv文件以某列为条件分类切割
  20. 一串单精度字符存入文件c语言,C语言文件选择题

热门文章

  1. [Vue warn]: Attribute id is ignored on component div because the component is a fragment instanc
  2. iOS - Swift 与 Objective-C 互相操作
  3. DB2数据库指定时间点恢复案例
  4. 第三讲:tapestry增删改查---查询数据
  5. 利用SAN做数字化世界的基石
  6. px、pt、em、rem 的区别
  7. CentOS 6.5 64位 安装zabbix-2.2.0
  8. 【原创】Kakfa api包源代码分析
  9. 主日--使徒行传--20150419
  10. 设置时区,时间,日期的脚本