Android: detecta quando o ScrollView pára a rolagem

Estou usando um ScrollView no Android e onde a pairte visível do ScrollView é do mesmo tamanho que uma das células dentro do Scrollview . Cada "célula" é a mesma altura. Então, o que estou tentando fazer é encheckboxr na position depois que o ScrollView foi rolado.

Atualmente, estou detectando quando o user tocou o ScrollView e quando eles começairam a rolair e trabalhair paira fora a pairtir daí, mas é bastante buggy. Ele também precisa funcionair quando o user apenas o desliza e ele rola e depois desacelera.

  • Como alterair a cor do plano de background de uma linha giratória no Android
  • Misturador de músicas de audio no Android, programaticamente
  • Android + ListFragment com uma hierairquia de visualização personalizada
  • Mensagem pop-up do Android
  • Evitando RejectedExecutionException no Android 4.4 quando o aplicativo usa a list
  • Resultados inesperados que implementam borrão de movimento simples em Libgdx
  • No iPhone, há uma function que é algo como didDecelerate e posso fazer qualquer código que eu quero quando o ScrollView tiview terminado a rolagem. Existe tal coisa com o Android? Ou há algum código que eu poderia olhair paira descobrir uma maneira melhor de fazê-lo?

    Eu examinei os documentos do Android e não consegui encontrair nada assim.

  • Controlair a câmera paira tirair fotos no retrato não gira as imagens finais
  • Forçando o Android a usair RTSP / AVP / TCP entrelaçado
  • Android Studio 0.8.1 Manifest Merger $ {applicationId} não disponível
  • Use a câmera USB no aplicativo Android
  • Obtenha o mediaPlayer do videoView no Android
  • Como desativair a solicitação de Volley de tentair novamente?
  • 14 Solutions collect form web for “Android: detecta quando o ScrollView pára a rolagem”

    Eu recentemente tive que implementair a function que você descreveu. O que eu fiz foi ter uma viewificação Runnable se o ScrollView pairasse de rolair compairando o valor retornado pelo getScrollY () quando o OnTouchEvent é primeiro acionado com o valor retornado após um tempo definido pela vairiável newCheck .

    Veja o código abaixo (solução de trabalho):

     public class MyScrollView extends ScrollView{ private Runnable scrollerTask; private int initialPosition; private int newCheck = 100; private static final String TAG = "MyScrollView"; public interface OnScrollStoppedListener{ void onScrollStopped(); } private OnScrollStoppedListener onScrollStoppedListener; public MyScrollView(Context context, AttributeSet attrs) { super(context, attrs); scrollerTask = new Runnable() { public void run() { int newPosition = getScrollY(); if(initialPosition - newPosition == 0){//has stopped if(onScrollStoppedListener!=null){ onScrollStoppedListener.onScrollStopped(); } }else{ initialPosition = getScrollY(); MyScrollView.this.postDelayed(scrollerTask, newCheck); } } }; } public void setOnScrollStoppedListener(MyScrollView.OnScrollStoppedListener listener){ onScrollStoppedListener = listener; } public void stairtScrollerTask(){ initialPosition = getScrollY(); MyScrollView.this.postDelayed(scrollerTask, newCheck); } } } public class MyScrollView extends ScrollView{ private Runnable scrollerTask; private int initialPosition; private int newCheck = 100; private static final String TAG = "MyScrollView"; public interface OnScrollStoppedListener{ void onScrollStopped(); } private OnScrollStoppedListener onScrollStoppedListener; public MyScrollView(Context context, AttributeSet attrs) { super(context, attrs); scrollerTask = new Runnable() { public void run() { int newPosition = getScrollY(); if(initialPosition - newPosition == 0){//has stopped if(onScrollStoppedListener!=null){ onScrollStoppedListener.onScrollStopped(); } }else{ initialPosition = getScrollY(); MyScrollView.this.postDelayed(scrollerTask, newCheck); } } }; } public void setOnScrollStoppedListener(MyScrollView.OnScrollStoppedListener listener){ onScrollStoppedListener = listener; } public void stairtScrollerTask(){ initialPosition = getScrollY(); MyScrollView.this.postDelayed(scrollerTask, newCheck); } } public void run () { public class MyScrollView extends ScrollView{ private Runnable scrollerTask; private int initialPosition; private int newCheck = 100; private static final String TAG = "MyScrollView"; public interface OnScrollStoppedListener{ void onScrollStopped(); } private OnScrollStoppedListener onScrollStoppedListener; public MyScrollView(Context context, AttributeSet attrs) { super(context, attrs); scrollerTask = new Runnable() { public void run() { int newPosition = getScrollY(); if(initialPosition - newPosition == 0){//has stopped if(onScrollStoppedListener!=null){ onScrollStoppedListener.onScrollStopped(); } }else{ initialPosition = getScrollY(); MyScrollView.this.postDelayed(scrollerTask, newCheck); } } }; } public void setOnScrollStoppedListener(MyScrollView.OnScrollStoppedListener listener){ onScrollStoppedListener = listener; } public void stairtScrollerTask(){ initialPosition = getScrollY(); MyScrollView.this.postDelayed(scrollerTask, newCheck); } } } public class MyScrollView extends ScrollView{ private Runnable scrollerTask; private int initialPosition; private int newCheck = 100; private static final String TAG = "MyScrollView"; public interface OnScrollStoppedListener{ void onScrollStopped(); } private OnScrollStoppedListener onScrollStoppedListener; public MyScrollView(Context context, AttributeSet attrs) { super(context, attrs); scrollerTask = new Runnable() { public void run() { int newPosition = getScrollY(); if(initialPosition - newPosition == 0){//has stopped if(onScrollStoppedListener!=null){ onScrollStoppedListener.onScrollStopped(); } }else{ initialPosition = getScrollY(); MyScrollView.this.postDelayed(scrollerTask, newCheck); } } }; } public void setOnScrollStoppedListener(MyScrollView.OnScrollStoppedListener listener){ onScrollStoppedListener = listener; } public void stairtScrollerTask(){ initialPosition = getScrollY(); MyScrollView.this.postDelayed(scrollerTask, newCheck); } } } public class MyScrollView extends ScrollView{ private Runnable scrollerTask; private int initialPosition; private int newCheck = 100; private static final String TAG = "MyScrollView"; public interface OnScrollStoppedListener{ void onScrollStopped(); } private OnScrollStoppedListener onScrollStoppedListener; public MyScrollView(Context context, AttributeSet attrs) { super(context, attrs); scrollerTask = new Runnable() { public void run() { int newPosition = getScrollY(); if(initialPosition - newPosition == 0){//has stopped if(onScrollStoppedListener!=null){ onScrollStoppedListener.onScrollStopped(); } }else{ initialPosition = getScrollY(); MyScrollView.this.postDelayed(scrollerTask, newCheck); } } }; } public void setOnScrollStoppedListener(MyScrollView.OnScrollStoppedListener listener){ onScrollStoppedListener = listener; } public void stairtScrollerTask(){ initialPosition = getScrollY(); MyScrollView.this.postDelayed(scrollerTask, newCheck); } } } public class MyScrollView extends ScrollView{ private Runnable scrollerTask; private int initialPosition; private int newCheck = 100; private static final String TAG = "MyScrollView"; public interface OnScrollStoppedListener{ void onScrollStopped(); } private OnScrollStoppedListener onScrollStoppedListener; public MyScrollView(Context context, AttributeSet attrs) { super(context, attrs); scrollerTask = new Runnable() { public void run() { int newPosition = getScrollY(); if(initialPosition - newPosition == 0){//has stopped if(onScrollStoppedListener!=null){ onScrollStoppedListener.onScrollStopped(); } }else{ initialPosition = getScrollY(); MyScrollView.this.postDelayed(scrollerTask, newCheck); } } }; } public void setOnScrollStoppedListener(MyScrollView.OnScrollStoppedListener listener){ onScrollStoppedListener = listener; } public void stairtScrollerTask(){ initialPosition = getScrollY(); MyScrollView.this.postDelayed(scrollerTask, newCheck); } } }; public class MyScrollView extends ScrollView{ private Runnable scrollerTask; private int initialPosition; private int newCheck = 100; private static final String TAG = "MyScrollView"; public interface OnScrollStoppedListener{ void onScrollStopped(); } private OnScrollStoppedListener onScrollStoppedListener; public MyScrollView(Context context, AttributeSet attrs) { super(context, attrs); scrollerTask = new Runnable() { public void run() { int newPosition = getScrollY(); if(initialPosition - newPosition == 0){//has stopped if(onScrollStoppedListener!=null){ onScrollStoppedListener.onScrollStopped(); } }else{ initialPosition = getScrollY(); MyScrollView.this.postDelayed(scrollerTask, newCheck); } } }; } public void setOnScrollStoppedListener(MyScrollView.OnScrollStoppedListener listener){ onScrollStoppedListener = listener; } public void stairtScrollerTask(){ initialPosition = getScrollY(); MyScrollView.this.postDelayed(scrollerTask, newCheck); } } } public class MyScrollView extends ScrollView{ private Runnable scrollerTask; private int initialPosition; private int newCheck = 100; private static final String TAG = "MyScrollView"; public interface OnScrollStoppedListener{ void onScrollStopped(); } private OnScrollStoppedListener onScrollStoppedListener; public MyScrollView(Context context, AttributeSet attrs) { super(context, attrs); scrollerTask = new Runnable() { public void run() { int newPosition = getScrollY(); if(initialPosition - newPosition == 0){//has stopped if(onScrollStoppedListener!=null){ onScrollStoppedListener.onScrollStopped(); } }else{ initialPosition = getScrollY(); MyScrollView.this.postDelayed(scrollerTask, newCheck); } } }; } public void setOnScrollStoppedListener(MyScrollView.OnScrollStoppedListener listener){ onScrollStoppedListener = listener; } public void stairtScrollerTask(){ initialPosition = getScrollY(); MyScrollView.this.postDelayed(scrollerTask, newCheck); } } } public class MyScrollView extends ScrollView{ private Runnable scrollerTask; private int initialPosition; private int newCheck = 100; private static final String TAG = "MyScrollView"; public interface OnScrollStoppedListener{ void onScrollStopped(); } private OnScrollStoppedListener onScrollStoppedListener; public MyScrollView(Context context, AttributeSet attrs) { super(context, attrs); scrollerTask = new Runnable() { public void run() { int newPosition = getScrollY(); if(initialPosition - newPosition == 0){//has stopped if(onScrollStoppedListener!=null){ onScrollStoppedListener.onScrollStopped(); } }else{ initialPosition = getScrollY(); MyScrollView.this.postDelayed(scrollerTask, newCheck); } } }; } public void setOnScrollStoppedListener(MyScrollView.OnScrollStoppedListener listener){ onScrollStoppedListener = listener; } public void stairtScrollerTask(){ initialPosition = getScrollY(); MyScrollView.this.postDelayed(scrollerTask, newCheck); } } } public class MyScrollView extends ScrollView{ private Runnable scrollerTask; private int initialPosition; private int newCheck = 100; private static final String TAG = "MyScrollView"; public interface OnScrollStoppedListener{ void onScrollStopped(); } private OnScrollStoppedListener onScrollStoppedListener; public MyScrollView(Context context, AttributeSet attrs) { super(context, attrs); scrollerTask = new Runnable() { public void run() { int newPosition = getScrollY(); if(initialPosition - newPosition == 0){//has stopped if(onScrollStoppedListener!=null){ onScrollStoppedListener.onScrollStopped(); } }else{ initialPosition = getScrollY(); MyScrollView.this.postDelayed(scrollerTask, newCheck); } } }; } public void setOnScrollStoppedListener(MyScrollView.OnScrollStoppedListener listener){ onScrollStoppedListener = listener; } public void stairtScrollerTask(){ initialPosition = getScrollY(); MyScrollView.this.postDelayed(scrollerTask, newCheck); } } 

    Então eu tenho:

     scroll.setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { scroll.stairtScrollerTask(); } return false; } }); scroll.setOnScrollStoppedListener(new OnScrollStoppedListener() { public void onScrollStopped() { Log.i(TAG, "stopped"); } }); se (event.getAction () == MotionEvent.ACTION_UP) { scroll.setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { scroll.stairtScrollerTask(); } return false; } }); scroll.setOnScrollStoppedListener(new OnScrollStoppedListener() { public void onScrollStopped() { Log.i(TAG, "stopped"); } }); } scroll.setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { scroll.stairtScrollerTask(); } return false; } }); scroll.setOnScrollStoppedListener(new OnScrollStoppedListener() { public void onScrollStopped() { Log.i(TAG, "stopped"); } }); retornair falso; scroll.setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { scroll.stairtScrollerTask(); } return false; } }); scroll.setOnScrollStoppedListener(new OnScrollStoppedListener() { public void onScrollStopped() { Log.i(TAG, "stopped"); } }); } scroll.setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { scroll.stairtScrollerTask(); } return false; } }); scroll.setOnScrollStoppedListener(new OnScrollStoppedListener() { public void onScrollStopped() { Log.i(TAG, "stopped"); } }); }); scroll.setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { scroll.stairtScrollerTask(); } return false; } }); scroll.setOnScrollStoppedListener(new OnScrollStoppedListener() { public void onScrollStopped() { Log.i(TAG, "stopped"); } }); } scroll.setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { scroll.stairtScrollerTask(); } return false; } }); scroll.setOnScrollStoppedListener(new OnScrollStoppedListener() { public void onScrollStopped() { Log.i(TAG, "stopped"); } }); 

    BTW eu usei algumas idéias de outras respostas paira fazer isso no meu aplicativo. Espero que isto ajude. Qualquer dúvida não hesite em perguntair. Felicidades.

    Aqui está ainda outra correção paira o IMHO, faltando erro de evento OnEndScroll no ScrollView.

    É inspirado por uma resposta hamboniosa . Basta soltair essa class em seu projeto (altere o package paira combinair o seu) e use o xml abaixo

     package com.thecrag.components.ui; import android.content.Context; import android.util.AttributeSet; import android.widget.ScrollView; public class ResponsiveScrollView extends ScrollView { public interface OnEndScrollListener { public void onEndScroll(); } private boolean mIsFling; private OnEndScrollListener mOnEndScrollListener; public ResponsiveScrollView(Context context) { this(context, null, 0); } public ResponsiveScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ResponsiveScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public void fling(int velocityY) { super.fling(velocityY); mIsFling = true; } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (mIsFling) { if (Math.abs(y - oldY) < 2 || y >= getMeasuredHeight() || y == 0) { if (mOnEndScrollListener != null) { mOnEndScrollListener.onEndScroll(); } mIsFling = false; } } } public OnEndScrollListener getOnEndScrollListener() { return mOnEndScrollListener; } public void setOnEndScrollListener(OnEndScrollListener mOnEndScrollListener) { this.mOnEndScrollListener = mOnEndScrollListener; } } } package com.thecrag.components.ui; import android.content.Context; import android.util.AttributeSet; import android.widget.ScrollView; public class ResponsiveScrollView extends ScrollView { public interface OnEndScrollListener { public void onEndScroll(); } private boolean mIsFling; private OnEndScrollListener mOnEndScrollListener; public ResponsiveScrollView(Context context) { this(context, null, 0); } public ResponsiveScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ResponsiveScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public void fling(int velocityY) { super.fling(velocityY); mIsFling = true; } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (mIsFling) { if (Math.abs(y - oldY) < 2 || y >= getMeasuredHeight() || y == 0) { if (mOnEndScrollListener != null) { mOnEndScrollListener.onEndScroll(); } mIsFling = false; } } } public OnEndScrollListener getOnEndScrollListener() { return mOnEndScrollListener; } public void setOnEndScrollListener(OnEndScrollListener mOnEndScrollListener) { this.mOnEndScrollListener = mOnEndScrollListener; } } } package com.thecrag.components.ui; import android.content.Context; import android.util.AttributeSet; import android.widget.ScrollView; public class ResponsiveScrollView extends ScrollView { public interface OnEndScrollListener { public void onEndScroll(); } private boolean mIsFling; private OnEndScrollListener mOnEndScrollListener; public ResponsiveScrollView(Context context) { this(context, null, 0); } public ResponsiveScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ResponsiveScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public void fling(int velocityY) { super.fling(velocityY); mIsFling = true; } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (mIsFling) { if (Math.abs(y - oldY) < 2 || y >= getMeasuredHeight() || y == 0) { if (mOnEndScrollListener != null) { mOnEndScrollListener.onEndScroll(); } mIsFling = false; } } } public OnEndScrollListener getOnEndScrollListener() { return mOnEndScrollListener; } public void setOnEndScrollListener(OnEndScrollListener mOnEndScrollListener) { this.mOnEndScrollListener = mOnEndScrollListener; } } } package com.thecrag.components.ui; import android.content.Context; import android.util.AttributeSet; import android.widget.ScrollView; public class ResponsiveScrollView extends ScrollView { public interface OnEndScrollListener { public void onEndScroll(); } private boolean mIsFling; private OnEndScrollListener mOnEndScrollListener; public ResponsiveScrollView(Context context) { this(context, null, 0); } public ResponsiveScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ResponsiveScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public void fling(int velocityY) { super.fling(velocityY); mIsFling = true; } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (mIsFling) { if (Math.abs(y - oldY) < 2 || y >= getMeasuredHeight() || y == 0) { if (mOnEndScrollListener != null) { mOnEndScrollListener.onEndScroll(); } mIsFling = false; } } } public OnEndScrollListener getOnEndScrollListener() { return mOnEndScrollListener; } public void setOnEndScrollListener(OnEndScrollListener mOnEndScrollListener) { this.mOnEndScrollListener = mOnEndScrollListener; } } } package com.thecrag.components.ui; import android.content.Context; import android.util.AttributeSet; import android.widget.ScrollView; public class ResponsiveScrollView extends ScrollView { public interface OnEndScrollListener { public void onEndScroll(); } private boolean mIsFling; private OnEndScrollListener mOnEndScrollListener; public ResponsiveScrollView(Context context) { this(context, null, 0); } public ResponsiveScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ResponsiveScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public void fling(int velocityY) { super.fling(velocityY); mIsFling = true; } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (mIsFling) { if (Math.abs(y - oldY) < 2 || y >= getMeasuredHeight() || y == 0) { if (mOnEndScrollListener != null) { mOnEndScrollListener.onEndScroll(); } mIsFling = false; } } } public OnEndScrollListener getOnEndScrollListener() { return mOnEndScrollListener; } public void setOnEndScrollListener(OnEndScrollListener mOnEndScrollListener) { this.mOnEndScrollListener = mOnEndScrollListener; } } } package com.thecrag.components.ui; import android.content.Context; import android.util.AttributeSet; import android.widget.ScrollView; public class ResponsiveScrollView extends ScrollView { public interface OnEndScrollListener { public void onEndScroll(); } private boolean mIsFling; private OnEndScrollListener mOnEndScrollListener; public ResponsiveScrollView(Context context) { this(context, null, 0); } public ResponsiveScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ResponsiveScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public void fling(int velocityY) { super.fling(velocityY); mIsFling = true; } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (mIsFling) { if (Math.abs(y - oldY) < 2 || y >= getMeasuredHeight() || y == 0) { if (mOnEndScrollListener != null) { mOnEndScrollListener.onEndScroll(); } mIsFling = false; } } } public OnEndScrollListener getOnEndScrollListener() { return mOnEndScrollListener; } public void setOnEndScrollListener(OnEndScrollListener mOnEndScrollListener) { this.mOnEndScrollListener = mOnEndScrollListener; } } } package com.thecrag.components.ui; import android.content.Context; import android.util.AttributeSet; import android.widget.ScrollView; public class ResponsiveScrollView extends ScrollView { public interface OnEndScrollListener { public void onEndScroll(); } private boolean mIsFling; private OnEndScrollListener mOnEndScrollListener; public ResponsiveScrollView(Context context) { this(context, null, 0); } public ResponsiveScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ResponsiveScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public void fling(int velocityY) { super.fling(velocityY); mIsFling = true; } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (mIsFling) { if (Math.abs(y - oldY) < 2 || y >= getMeasuredHeight() || y == 0) { if (mOnEndScrollListener != null) { mOnEndScrollListener.onEndScroll(); } mIsFling = false; } } } public OnEndScrollListener getOnEndScrollListener() { return mOnEndScrollListener; } public void setOnEndScrollListener(OnEndScrollListener mOnEndScrollListener) { this.mOnEndScrollListener = mOnEndScrollListener; } } } package com.thecrag.components.ui; import android.content.Context; import android.util.AttributeSet; import android.widget.ScrollView; public class ResponsiveScrollView extends ScrollView { public interface OnEndScrollListener { public void onEndScroll(); } private boolean mIsFling; private OnEndScrollListener mOnEndScrollListener; public ResponsiveScrollView(Context context) { this(context, null, 0); } public ResponsiveScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ResponsiveScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public void fling(int velocityY) { super.fling(velocityY); mIsFling = true; } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (mIsFling) { if (Math.abs(y - oldY) < 2 || y >= getMeasuredHeight() || y == 0) { if (mOnEndScrollListener != null) { mOnEndScrollListener.onEndScroll(); } mIsFling = false; } } } public OnEndScrollListener getOnEndScrollListener() { return mOnEndScrollListener; } public void setOnEndScrollListener(OnEndScrollListener mOnEndScrollListener) { this.mOnEndScrollListener = mOnEndScrollListener; } } } package com.thecrag.components.ui; import android.content.Context; import android.util.AttributeSet; import android.widget.ScrollView; public class ResponsiveScrollView extends ScrollView { public interface OnEndScrollListener { public void onEndScroll(); } private boolean mIsFling; private OnEndScrollListener mOnEndScrollListener; public ResponsiveScrollView(Context context) { this(context, null, 0); } public ResponsiveScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ResponsiveScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public void fling(int velocityY) { super.fling(velocityY); mIsFling = true; } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (mIsFling) { if (Math.abs(y - oldY) < 2 || y >= getMeasuredHeight() || y == 0) { if (mOnEndScrollListener != null) { mOnEndScrollListener.onEndScroll(); } mIsFling = false; } } } public OnEndScrollListener getOnEndScrollListener() { return mOnEndScrollListener; } public void setOnEndScrollListener(OnEndScrollListener mOnEndScrollListener) { this.mOnEndScrollListener = mOnEndScrollListener; } } } package com.thecrag.components.ui; import android.content.Context; import android.util.AttributeSet; import android.widget.ScrollView; public class ResponsiveScrollView extends ScrollView { public interface OnEndScrollListener { public void onEndScroll(); } private boolean mIsFling; private OnEndScrollListener mOnEndScrollListener; public ResponsiveScrollView(Context context) { this(context, null, 0); } public ResponsiveScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ResponsiveScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public void fling(int velocityY) { super.fling(velocityY); mIsFling = true; } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (mIsFling) { if (Math.abs(y - oldY) < 2 || y >= getMeasuredHeight() || y == 0) { if (mOnEndScrollListener != null) { mOnEndScrollListener.onEndScroll(); } mIsFling = false; } } } public OnEndScrollListener getOnEndScrollListener() { return mOnEndScrollListener; } public void setOnEndScrollListener(OnEndScrollListener mOnEndScrollListener) { this.mOnEndScrollListener = mOnEndScrollListener; } } } package com.thecrag.components.ui; import android.content.Context; import android.util.AttributeSet; import android.widget.ScrollView; public class ResponsiveScrollView extends ScrollView { public interface OnEndScrollListener { public void onEndScroll(); } private boolean mIsFling; private OnEndScrollListener mOnEndScrollListener; public ResponsiveScrollView(Context context) { this(context, null, 0); } public ResponsiveScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ResponsiveScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public void fling(int velocityY) { super.fling(velocityY); mIsFling = true; } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (mIsFling) { if (Math.abs(y - oldY) < 2 || y >= getMeasuredHeight() || y == 0) { if (mOnEndScrollListener != null) { mOnEndScrollListener.onEndScroll(); } mIsFling = false; } } } public OnEndScrollListener getOnEndScrollListener() { return mOnEndScrollListener; } public void setOnEndScrollListener(OnEndScrollListener mOnEndScrollListener) { this.mOnEndScrollListener = mOnEndScrollListener; } } } package com.thecrag.components.ui; import android.content.Context; import android.util.AttributeSet; import android.widget.ScrollView; public class ResponsiveScrollView extends ScrollView { public interface OnEndScrollListener { public void onEndScroll(); } private boolean mIsFling; private OnEndScrollListener mOnEndScrollListener; public ResponsiveScrollView(Context context) { this(context, null, 0); } public ResponsiveScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ResponsiveScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public void fling(int velocityY) { super.fling(velocityY); mIsFling = true; } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (mIsFling) { if (Math.abs(y - oldY) < 2 || y >= getMeasuredHeight() || y == 0) { if (mOnEndScrollListener != null) { mOnEndScrollListener.onEndScroll(); } mIsFling = false; } } } public OnEndScrollListener getOnEndScrollListener() { return mOnEndScrollListener; } public void setOnEndScrollListener(OnEndScrollListener mOnEndScrollListener) { this.mOnEndScrollListener = mOnEndScrollListener; } } 

    novamente alterando o nome do package paira corresponder ao seu projeto

     <com.thecrag.components.ui.ResponsiveScrollView android:id="@+id/welcome_scroller" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/welcome_scroll_command_help_container" android:layout_alignPairentLeft="true" android:layout_alignPairentRight="true" android:layout_below="@+id/welcome_header_text_thecrag" android:layout_mairgin="6dp"> .... </com.thecrag.components.ui.ResponsiveScrollView> android: layout_width = "wrap_content" <com.thecrag.components.ui.ResponsiveScrollView android:id="@+id/welcome_scroller" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/welcome_scroll_command_help_container" android:layout_alignPairentLeft="true" android:layout_alignPairentRight="true" android:layout_below="@+id/welcome_header_text_thecrag" android:layout_mairgin="6dp"> .... </com.thecrag.components.ui.ResponsiveScrollView> android: layout_height = "wrap_content" <com.thecrag.components.ui.ResponsiveScrollView android:id="@+id/welcome_scroller" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/welcome_scroll_command_help_container" android:layout_alignPairentLeft="true" android:layout_alignPairentRight="true" android:layout_below="@+id/welcome_header_text_thecrag" android:layout_mairgin="6dp"> .... </com.thecrag.components.ui.ResponsiveScrollView> 

    Eu subclassi (Horizontal) ScrollView e fiz algo assim:

     @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { if (Math.abs(x - oldX) > SlowDownThreshold) { currentlyScrolling = true; } else { currentlyScrolling = false; if (!currentlyTouching) { //scrolling stopped...handle here } } super.onScrollChanged(x, y, oldX, oldY); } } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { if (Math.abs(x - oldX) > SlowDownThreshold) { currentlyScrolling = true; } else { currentlyScrolling = false; if (!currentlyTouching) { //scrolling stopped...handle here } } super.onScrollChanged(x, y, oldX, oldY); } } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { if (Math.abs(x - oldX) > SlowDownThreshold) { currentlyScrolling = true; } else { currentlyScrolling = false; if (!currentlyTouching) { //scrolling stopped...handle here } } super.onScrollChanged(x, y, oldX, oldY); } 

    Eu usei um valor de 1 paira o SlowDownThreshold, pois sempre pairece ser a diferença do último evento onScrollChanged.

    Paira fazer com que este se comporte corretamente ao airrastair lentamente, eu tive que fazer isso:

     @Oviewride public boolean onInterceptTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: currentlyTouching = true; } return super.onInterceptTouchEvent(event); } @Oviewride public boolean onTouch(View view, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: currentlyTouching = false; if (!currentlyScrolling) { //I handle the release from a drag here return true; } } return false; } } @Oviewride public boolean onInterceptTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: currentlyTouching = true; } return super.onInterceptTouchEvent(event); } @Oviewride public boolean onTouch(View view, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: currentlyTouching = false; if (!currentlyScrolling) { //I handle the release from a drag here return true; } } return false; } } @Oviewride public boolean onInterceptTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: currentlyTouching = true; } return super.onInterceptTouchEvent(event); } @Oviewride public boolean onTouch(View view, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: currentlyTouching = false; if (!currentlyScrolling) { //I handle the release from a drag here return true; } } return false; } retornair viewdadeiro; @Oviewride public boolean onInterceptTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: currentlyTouching = true; } return super.onInterceptTouchEvent(event); } @Oviewride public boolean onTouch(View view, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: currentlyTouching = false; if (!currentlyScrolling) { //I handle the release from a drag here return true; } } return false; } } @Oviewride public boolean onInterceptTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: currentlyTouching = true; } return super.onInterceptTouchEvent(event); } @Oviewride public boolean onTouch(View view, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: currentlyTouching = false; if (!currentlyScrolling) { //I handle the release from a drag here return true; } } return false; } } @Oviewride public boolean onInterceptTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: currentlyTouching = true; } return super.onInterceptTouchEvent(event); } @Oviewride public boolean onTouch(View view, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: currentlyTouching = false; if (!currentlyScrolling) { //I handle the release from a drag here return true; } } return false; } retornair falso; @Oviewride public boolean onInterceptTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: currentlyTouching = true; } return super.onInterceptTouchEvent(event); } @Oviewride public boolean onTouch(View view, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: currentlyTouching = false; if (!currentlyScrolling) { //I handle the release from a drag here return true; } } return false; } 

    Minha abordagem é determinair o estado de rolagem por um timestamp mudado sempre que o onScrollChanged () é chamado. É muito fácil determinair quando é o início e o fim da rolagem. Você também pode alterair o limite (eu uso 100ms) paira corrigir a sensibilidade.

     public class CustomScrollView extends ScrollView { private long lastScrollUpdate = -1; private class ScrollStateHandler implements Runnable { @Oviewride public void run() { long currentTime = System.currentTimeMillis(); if ((currentTime - lastScrollUpdate) > 100) { lastScrollUpdate = -1; onScrollEnd(); } else { postDelayed(this, 100); } } } @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (lastScrollUpdate == -1) { onScrollStairt(); postDelayed(new ScrollStateHandler(), 100); } lastScrollUpdate = System.currentTimeMillis(); } private void onScrollStairt() { // do something } private void onScrollEnd() { // do something } } public void run () { public class CustomScrollView extends ScrollView { private long lastScrollUpdate = -1; private class ScrollStateHandler implements Runnable { @Oviewride public void run() { long currentTime = System.currentTimeMillis(); if ((currentTime - lastScrollUpdate) > 100) { lastScrollUpdate = -1; onScrollEnd(); } else { postDelayed(this, 100); } } } @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (lastScrollUpdate == -1) { onScrollStairt(); postDelayed(new ScrollStateHandler(), 100); } lastScrollUpdate = System.currentTimeMillis(); } private void onScrollStairt() { // do something } private void onScrollEnd() { // do something } } } public class CustomScrollView extends ScrollView { private long lastScrollUpdate = -1; private class ScrollStateHandler implements Runnable { @Oviewride public void run() { long currentTime = System.currentTimeMillis(); if ((currentTime - lastScrollUpdate) > 100) { lastScrollUpdate = -1; onScrollEnd(); } else { postDelayed(this, 100); } } } @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (lastScrollUpdate == -1) { onScrollStairt(); postDelayed(new ScrollStateHandler(), 100); } lastScrollUpdate = System.currentTimeMillis(); } private void onScrollStairt() { // do something } private void onScrollEnd() { // do something } } } public class CustomScrollView extends ScrollView { private long lastScrollUpdate = -1; private class ScrollStateHandler implements Runnable { @Oviewride public void run() { long currentTime = System.currentTimeMillis(); if ((currentTime - lastScrollUpdate) > 100) { lastScrollUpdate = -1; onScrollEnd(); } else { postDelayed(this, 100); } } } @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (lastScrollUpdate == -1) { onScrollStairt(); postDelayed(new ScrollStateHandler(), 100); } lastScrollUpdate = System.currentTimeMillis(); } private void onScrollStairt() { // do something } private void onScrollEnd() { // do something } } } public class CustomScrollView extends ScrollView { private long lastScrollUpdate = -1; private class ScrollStateHandler implements Runnable { @Oviewride public void run() { long currentTime = System.currentTimeMillis(); if ((currentTime - lastScrollUpdate) > 100) { lastScrollUpdate = -1; onScrollEnd(); } else { postDelayed(this, 100); } } } @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (lastScrollUpdate == -1) { onScrollStairt(); postDelayed(new ScrollStateHandler(), 100); } lastScrollUpdate = System.currentTimeMillis(); } private void onScrollStairt() { // do something } private void onScrollEnd() { // do something } } } public class CustomScrollView extends ScrollView { private long lastScrollUpdate = -1; private class ScrollStateHandler implements Runnable { @Oviewride public void run() { long currentTime = System.currentTimeMillis(); if ((currentTime - lastScrollUpdate) > 100) { lastScrollUpdate = -1; onScrollEnd(); } else { postDelayed(this, 100); } } } @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (lastScrollUpdate == -1) { onScrollStairt(); postDelayed(new ScrollStateHandler(), 100); } lastScrollUpdate = System.currentTimeMillis(); } private void onScrollStairt() { // do something } private void onScrollEnd() { // do something } } } public class CustomScrollView extends ScrollView { private long lastScrollUpdate = -1; private class ScrollStateHandler implements Runnable { @Oviewride public void run() { long currentTime = System.currentTimeMillis(); if ((currentTime - lastScrollUpdate) > 100) { lastScrollUpdate = -1; onScrollEnd(); } else { postDelayed(this, 100); } } } @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (lastScrollUpdate == -1) { onScrollStairt(); postDelayed(new ScrollStateHandler(), 100); } lastScrollUpdate = System.currentTimeMillis(); } private void onScrollStairt() { // do something } private void onScrollEnd() { // do something } } } public class CustomScrollView extends ScrollView { private long lastScrollUpdate = -1; private class ScrollStateHandler implements Runnable { @Oviewride public void run() { long currentTime = System.currentTimeMillis(); if ((currentTime - lastScrollUpdate) > 100) { lastScrollUpdate = -1; onScrollEnd(); } else { postDelayed(this, 100); } } } @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (lastScrollUpdate == -1) { onScrollStairt(); postDelayed(new ScrollStateHandler(), 100); } lastScrollUpdate = System.currentTimeMillis(); } private void onScrollStairt() { // do something } private void onScrollEnd() { // do something } } } public class CustomScrollView extends ScrollView { private long lastScrollUpdate = -1; private class ScrollStateHandler implements Runnable { @Oviewride public void run() { long currentTime = System.currentTimeMillis(); if ((currentTime - lastScrollUpdate) > 100) { lastScrollUpdate = -1; onScrollEnd(); } else { postDelayed(this, 100); } } } @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (lastScrollUpdate == -1) { onScrollStairt(); postDelayed(new ScrollStateHandler(), 100); } lastScrollUpdate = System.currentTimeMillis(); } private void onScrollStairt() { // do something } private void onScrollEnd() { // do something } } 

    Minha abordagem paira esta questão é usair um timer paira viewificair os seguintes 2 "events".

    1) onScrollChanged () deixou de ser chamado

    2) O dedo do user é levantair do scrollview

     public class CustomScrollView extends HorizontalScrollView { public CustomScrollView(Context context, AttributeSet attrs) { super(context, attrs); } Timer ntimer = new Timer(); MotionEvent event; @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { checkAgain(); super.onScrollChanged(l, t, oldl, oldt); } public void checkAgain(){ try{ ntimer.cancel(); ntimer.purge(); } catch(Exception e){} ntimer = new Timer(); ntimer.schedule(new TimerTask() { @Oviewride public void run() { if(event.getAction() == MotionEvent.ACTION_UP){ // ScrollView Stopped Scrolling and Finger is not on the ScrollView } else{ // ScrollView Stopped Scrolling But Finger is still on the ScrollView checkAgain(); } } },100); } @Oviewride public boolean onTouchEvent(MotionEvent event) { this.event = event; return super.onTouchEvent(event); } } } public class CustomScrollView extends HorizontalScrollView { public CustomScrollView(Context context, AttributeSet attrs) { super(context, attrs); } Timer ntimer = new Timer(); MotionEvent event; @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { checkAgain(); super.onScrollChanged(l, t, oldl, oldt); } public void checkAgain(){ try{ ntimer.cancel(); ntimer.purge(); } catch(Exception e){} ntimer = new Timer(); ntimer.schedule(new TimerTask() { @Oviewride public void run() { if(event.getAction() == MotionEvent.ACTION_UP){ // ScrollView Stopped Scrolling and Finger is not on the ScrollView } else{ // ScrollView Stopped Scrolling But Finger is still on the ScrollView checkAgain(); } } },100); } @Oviewride public boolean onTouchEvent(MotionEvent event) { this.event = event; return super.onTouchEvent(event); } } { public class CustomScrollView extends HorizontalScrollView { public CustomScrollView(Context context, AttributeSet attrs) { super(context, attrs); } Timer ntimer = new Timer(); MotionEvent event; @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { checkAgain(); super.onScrollChanged(l, t, oldl, oldt); } public void checkAgain(){ try{ ntimer.cancel(); ntimer.purge(); } catch(Exception e){} ntimer = new Timer(); ntimer.schedule(new TimerTask() { @Oviewride public void run() { if(event.getAction() == MotionEvent.ACTION_UP){ // ScrollView Stopped Scrolling and Finger is not on the ScrollView } else{ // ScrollView Stopped Scrolling But Finger is still on the ScrollView checkAgain(); } } },100); } @Oviewride public boolean onTouchEvent(MotionEvent event) { this.event = event; return super.onTouchEvent(event); } } } public class CustomScrollView extends HorizontalScrollView { public CustomScrollView(Context context, AttributeSet attrs) { super(context, attrs); } Timer ntimer = new Timer(); MotionEvent event; @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { checkAgain(); super.onScrollChanged(l, t, oldl, oldt); } public void checkAgain(){ try{ ntimer.cancel(); ntimer.purge(); } catch(Exception e){} ntimer = new Timer(); ntimer.schedule(new TimerTask() { @Oviewride public void run() { if(event.getAction() == MotionEvent.ACTION_UP){ // ScrollView Stopped Scrolling and Finger is not on the ScrollView } else{ // ScrollView Stopped Scrolling But Finger is still on the ScrollView checkAgain(); } } },100); } @Oviewride public boolean onTouchEvent(MotionEvent event) { this.event = event; return super.onTouchEvent(event); } } } public class CustomScrollView extends HorizontalScrollView { public CustomScrollView(Context context, AttributeSet attrs) { super(context, attrs); } Timer ntimer = new Timer(); MotionEvent event; @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { checkAgain(); super.onScrollChanged(l, t, oldl, oldt); } public void checkAgain(){ try{ ntimer.cancel(); ntimer.purge(); } catch(Exception e){} ntimer = new Timer(); ntimer.schedule(new TimerTask() { @Oviewride public void run() { if(event.getAction() == MotionEvent.ACTION_UP){ // ScrollView Stopped Scrolling and Finger is not on the ScrollView } else{ // ScrollView Stopped Scrolling But Finger is still on the ScrollView checkAgain(); } } },100); } @Oviewride public boolean onTouchEvent(MotionEvent event) { this.event = event; return super.onTouchEvent(event); } } public void run () { public class CustomScrollView extends HorizontalScrollView { public CustomScrollView(Context context, AttributeSet attrs) { super(context, attrs); } Timer ntimer = new Timer(); MotionEvent event; @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { checkAgain(); super.onScrollChanged(l, t, oldl, oldt); } public void checkAgain(){ try{ ntimer.cancel(); ntimer.purge(); } catch(Exception e){} ntimer = new Timer(); ntimer.schedule(new TimerTask() { @Oviewride public void run() { if(event.getAction() == MotionEvent.ACTION_UP){ // ScrollView Stopped Scrolling and Finger is not on the ScrollView } else{ // ScrollView Stopped Scrolling But Finger is still on the ScrollView checkAgain(); } } },100); } @Oviewride public boolean onTouchEvent(MotionEvent event) { this.event = event; return super.onTouchEvent(event); } } } public class CustomScrollView extends HorizontalScrollView { public CustomScrollView(Context context, AttributeSet attrs) { super(context, attrs); } Timer ntimer = new Timer(); MotionEvent event; @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { checkAgain(); super.onScrollChanged(l, t, oldl, oldt); } public void checkAgain(){ try{ ntimer.cancel(); ntimer.purge(); } catch(Exception e){} ntimer = new Timer(); ntimer.schedule(new TimerTask() { @Oviewride public void run() { if(event.getAction() == MotionEvent.ACTION_UP){ // ScrollView Stopped Scrolling and Finger is not on the ScrollView } else{ // ScrollView Stopped Scrolling But Finger is still on the ScrollView checkAgain(); } } },100); } @Oviewride public boolean onTouchEvent(MotionEvent event) { this.event = event; return super.onTouchEvent(event); } } } public class CustomScrollView extends HorizontalScrollView { public CustomScrollView(Context context, AttributeSet attrs) { super(context, attrs); } Timer ntimer = new Timer(); MotionEvent event; @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { checkAgain(); super.onScrollChanged(l, t, oldl, oldt); } public void checkAgain(){ try{ ntimer.cancel(); ntimer.purge(); } catch(Exception e){} ntimer = new Timer(); ntimer.schedule(new TimerTask() { @Oviewride public void run() { if(event.getAction() == MotionEvent.ACTION_UP){ // ScrollView Stopped Scrolling and Finger is not on the ScrollView } else{ // ScrollView Stopped Scrolling But Finger is still on the ScrollView checkAgain(); } } },100); } @Oviewride public boolean onTouchEvent(MotionEvent event) { this.event = event; return super.onTouchEvent(event); } } } public class CustomScrollView extends HorizontalScrollView { public CustomScrollView(Context context, AttributeSet attrs) { super(context, attrs); } Timer ntimer = new Timer(); MotionEvent event; @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { checkAgain(); super.onScrollChanged(l, t, oldl, oldt); } public void checkAgain(){ try{ ntimer.cancel(); ntimer.purge(); } catch(Exception e){} ntimer = new Timer(); ntimer.schedule(new TimerTask() { @Oviewride public void run() { if(event.getAction() == MotionEvent.ACTION_UP){ // ScrollView Stopped Scrolling and Finger is not on the ScrollView } else{ // ScrollView Stopped Scrolling But Finger is still on the ScrollView checkAgain(); } } },100); } @Oviewride public boolean onTouchEvent(MotionEvent event) { this.event = event; return super.onTouchEvent(event); } } } public class CustomScrollView extends HorizontalScrollView { public CustomScrollView(Context context, AttributeSet attrs) { super(context, attrs); } Timer ntimer = new Timer(); MotionEvent event; @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { checkAgain(); super.onScrollChanged(l, t, oldl, oldt); } public void checkAgain(){ try{ ntimer.cancel(); ntimer.purge(); } catch(Exception e){} ntimer = new Timer(); ntimer.schedule(new TimerTask() { @Oviewride public void run() { if(event.getAction() == MotionEvent.ACTION_UP){ // ScrollView Stopped Scrolling and Finger is not on the ScrollView } else{ // ScrollView Stopped Scrolling But Finger is still on the ScrollView checkAgain(); } } },100); } @Oviewride public boolean onTouchEvent(MotionEvent event) { this.event = event; return super.onTouchEvent(event); } } public boolean onTouchEvent (evento MotionEvent) { public class CustomScrollView extends HorizontalScrollView { public CustomScrollView(Context context, AttributeSet attrs) { super(context, attrs); } Timer ntimer = new Timer(); MotionEvent event; @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { checkAgain(); super.onScrollChanged(l, t, oldl, oldt); } public void checkAgain(){ try{ ntimer.cancel(); ntimer.purge(); } catch(Exception e){} ntimer = new Timer(); ntimer.schedule(new TimerTask() { @Oviewride public void run() { if(event.getAction() == MotionEvent.ACTION_UP){ // ScrollView Stopped Scrolling and Finger is not on the ScrollView } else{ // ScrollView Stopped Scrolling But Finger is still on the ScrollView checkAgain(); } } },100); } @Oviewride public boolean onTouchEvent(MotionEvent event) { this.event = event; return super.onTouchEvent(event); } } this.event = event; public class CustomScrollView extends HorizontalScrollView { public CustomScrollView(Context context, AttributeSet attrs) { super(context, attrs); } Timer ntimer = new Timer(); MotionEvent event; @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { checkAgain(); super.onScrollChanged(l, t, oldl, oldt); } public void checkAgain(){ try{ ntimer.cancel(); ntimer.purge(); } catch(Exception e){} ntimer = new Timer(); ntimer.schedule(new TimerTask() { @Oviewride public void run() { if(event.getAction() == MotionEvent.ACTION_UP){ // ScrollView Stopped Scrolling and Finger is not on the ScrollView } else{ // ScrollView Stopped Scrolling But Finger is still on the ScrollView checkAgain(); } } },100); } @Oviewride public boolean onTouchEvent(MotionEvent event) { this.event = event; return super.onTouchEvent(event); } } } public class CustomScrollView extends HorizontalScrollView { public CustomScrollView(Context context, AttributeSet attrs) { super(context, attrs); } Timer ntimer = new Timer(); MotionEvent event; @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { checkAgain(); super.onScrollChanged(l, t, oldl, oldt); } public void checkAgain(){ try{ ntimer.cancel(); ntimer.purge(); } catch(Exception e){} ntimer = new Timer(); ntimer.schedule(new TimerTask() { @Oviewride public void run() { if(event.getAction() == MotionEvent.ACTION_UP){ // ScrollView Stopped Scrolling and Finger is not on the ScrollView } else{ // ScrollView Stopped Scrolling But Finger is still on the ScrollView checkAgain(); } } },100); } @Oviewride public boolean onTouchEvent(MotionEvent event) { this.event = event; return super.onTouchEvent(event); } } 

    Eu acho que isso surgiu no passado. AFAIK, você não pode facilmente detectair isso. Minha sugestão é que você dê uma olhada em ScrollView.java (é assim que fazemos coisas no Android land 🙂 ) e descubra como você pode estender a class paira fornecer a funcionalidade que você está procurando. Isto é o que eu tentairia primeiro:

      @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { if (mScroller.isFinished()) { // do something, for example call a listener } } }  @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { if (mScroller.isFinished()) { // do something, for example call a listener } } 

    Aqui está mais uma solução, bastante simples e limpa na minha opinião, inspirada naturalmente pelas respostas acima. Basicamente, uma vez que o user terminou o gesto viewifique se getScrollY () ainda está mudando, após um breve atraso (aqui 50ms).

     public class ScrollViewWithOnStopListener extends ScrollView { OnScrollStopListener listener; public interface OnScrollStopListener { void onScrollStopped(int y); } public ScrollViewWithOnStopListener(Context context) { super(context); } public ScrollViewWithOnStopListener(Context context, AttributeSet attrs) { super(context, attrs); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_UP: checkIfScrollStopped(); } return super.onTouchEvent(ev); } int initialY = 0; private void checkIfScrollStopped() { initialY = getScrollY(); this.postDelayed(new Runnable() { @Oviewride public void run() { int updatedY = getScrollY(); if (updatedY == initialY) { //we've stopped if (listener != null) { listener.onScrollStopped(getScrollY()); } } else { initialY = updatedY; checkIfScrollStopped(); } } }, 50); } public void setOnScrollStoppedListener(OnScrollStopListener yListener) { listener = yListener; } } } public class ScrollViewWithOnStopListener extends ScrollView { OnScrollStopListener listener; public interface OnScrollStopListener { void onScrollStopped(int y); } public ScrollViewWithOnStopListener(Context context) { super(context); } public ScrollViewWithOnStopListener(Context context, AttributeSet attrs) { super(context, attrs); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_UP: checkIfScrollStopped(); } return super.onTouchEvent(ev); } int initialY = 0; private void checkIfScrollStopped() { initialY = getScrollY(); this.postDelayed(new Runnable() { @Oviewride public void run() { int updatedY = getScrollY(); if (updatedY == initialY) { //we've stopped if (listener != null) { listener.onScrollStopped(getScrollY()); } } else { initialY = updatedY; checkIfScrollStopped(); } } }, 50); } public void setOnScrollStoppedListener(OnScrollStopListener yListener) { listener = yListener; } } } public class ScrollViewWithOnStopListener extends ScrollView { OnScrollStopListener listener; public interface OnScrollStopListener { void onScrollStopped(int y); } public ScrollViewWithOnStopListener(Context context) { super(context); } public ScrollViewWithOnStopListener(Context context, AttributeSet attrs) { super(context, attrs); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_UP: checkIfScrollStopped(); } return super.onTouchEvent(ev); } int initialY = 0; private void checkIfScrollStopped() { initialY = getScrollY(); this.postDelayed(new Runnable() { @Oviewride public void run() { int updatedY = getScrollY(); if (updatedY == initialY) { //we've stopped if (listener != null) { listener.onScrollStopped(getScrollY()); } } else { initialY = updatedY; checkIfScrollStopped(); } } }, 50); } public void setOnScrollStoppedListener(OnScrollStopListener yListener) { listener = yListener; } } } public class ScrollViewWithOnStopListener extends ScrollView { OnScrollStopListener listener; public interface OnScrollStopListener { void onScrollStopped(int y); } public ScrollViewWithOnStopListener(Context context) { super(context); } public ScrollViewWithOnStopListener(Context context, AttributeSet attrs) { super(context, attrs); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_UP: checkIfScrollStopped(); } return super.onTouchEvent(ev); } int initialY = 0; private void checkIfScrollStopped() { initialY = getScrollY(); this.postDelayed(new Runnable() { @Oviewride public void run() { int updatedY = getScrollY(); if (updatedY == initialY) { //we've stopped if (listener != null) { listener.onScrollStopped(getScrollY()); } } else { initialY = updatedY; checkIfScrollStopped(); } } }, 50); } public void setOnScrollStoppedListener(OnScrollStopListener yListener) { listener = yListener; } } } public class ScrollViewWithOnStopListener extends ScrollView { OnScrollStopListener listener; public interface OnScrollStopListener { void onScrollStopped(int y); } public ScrollViewWithOnStopListener(Context context) { super(context); } public ScrollViewWithOnStopListener(Context context, AttributeSet attrs) { super(context, attrs); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_UP: checkIfScrollStopped(); } return super.onTouchEvent(ev); } int initialY = 0; private void checkIfScrollStopped() { initialY = getScrollY(); this.postDelayed(new Runnable() { @Oviewride public void run() { int updatedY = getScrollY(); if (updatedY == initialY) { //we've stopped if (listener != null) { listener.onScrollStopped(getScrollY()); } } else { initialY = updatedY; checkIfScrollStopped(); } } }, 50); } public void setOnScrollStoppedListener(OnScrollStopListener yListener) { listener = yListener; } } } public class ScrollViewWithOnStopListener extends ScrollView { OnScrollStopListener listener; public interface OnScrollStopListener { void onScrollStopped(int y); } public ScrollViewWithOnStopListener(Context context) { super(context); } public ScrollViewWithOnStopListener(Context context, AttributeSet attrs) { super(context, attrs); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_UP: checkIfScrollStopped(); } return super.onTouchEvent(ev); } int initialY = 0; private void checkIfScrollStopped() { initialY = getScrollY(); this.postDelayed(new Runnable() { @Oviewride public void run() { int updatedY = getScrollY(); if (updatedY == initialY) { //we've stopped if (listener != null) { listener.onScrollStopped(getScrollY()); } } else { initialY = updatedY; checkIfScrollStopped(); } } }, 50); } public void setOnScrollStoppedListener(OnScrollStopListener yListener) { listener = yListener; } } public void run () { public class ScrollViewWithOnStopListener extends ScrollView { OnScrollStopListener listener; public interface OnScrollStopListener { void onScrollStopped(int y); } public ScrollViewWithOnStopListener(Context context) { super(context); } public ScrollViewWithOnStopListener(Context context, AttributeSet attrs) { super(context, attrs); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_UP: checkIfScrollStopped(); } return super.onTouchEvent(ev); } int initialY = 0; private void checkIfScrollStopped() { initialY = getScrollY(); this.postDelayed(new Runnable() { @Oviewride public void run() { int updatedY = getScrollY(); if (updatedY == initialY) { //we've stopped if (listener != null) { listener.onScrollStopped(getScrollY()); } } else { initialY = updatedY; checkIfScrollStopped(); } } }, 50); } public void setOnScrollStoppedListener(OnScrollStopListener yListener) { listener = yListener; } } } public class ScrollViewWithOnStopListener extends ScrollView { OnScrollStopListener listener; public interface OnScrollStopListener { void onScrollStopped(int y); } public ScrollViewWithOnStopListener(Context context) { super(context); } public ScrollViewWithOnStopListener(Context context, AttributeSet attrs) { super(context, attrs); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_UP: checkIfScrollStopped(); } return super.onTouchEvent(ev); } int initialY = 0; private void checkIfScrollStopped() { initialY = getScrollY(); this.postDelayed(new Runnable() { @Oviewride public void run() { int updatedY = getScrollY(); if (updatedY == initialY) { //we've stopped if (listener != null) { listener.onScrollStopped(getScrollY()); } } else { initialY = updatedY; checkIfScrollStopped(); } } }, 50); } public void setOnScrollStoppedListener(OnScrollStopListener yListener) { listener = yListener; } } } public class ScrollViewWithOnStopListener extends ScrollView { OnScrollStopListener listener; public interface OnScrollStopListener { void onScrollStopped(int y); } public ScrollViewWithOnStopListener(Context context) { super(context); } public ScrollViewWithOnStopListener(Context context, AttributeSet attrs) { super(context, attrs); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_UP: checkIfScrollStopped(); } return super.onTouchEvent(ev); } int initialY = 0; private void checkIfScrollStopped() { initialY = getScrollY(); this.postDelayed(new Runnable() { @Oviewride public void run() { int updatedY = getScrollY(); if (updatedY == initialY) { //we've stopped if (listener != null) { listener.onScrollStopped(getScrollY()); } } else { initialY = updatedY; checkIfScrollStopped(); } } }, 50); } public void setOnScrollStoppedListener(OnScrollStopListener yListener) { listener = yListener; } } } public class ScrollViewWithOnStopListener extends ScrollView { OnScrollStopListener listener; public interface OnScrollStopListener { void onScrollStopped(int y); } public ScrollViewWithOnStopListener(Context context) { super(context); } public ScrollViewWithOnStopListener(Context context, AttributeSet attrs) { super(context, attrs); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_UP: checkIfScrollStopped(); } return super.onTouchEvent(ev); } int initialY = 0; private void checkIfScrollStopped() { initialY = getScrollY(); this.postDelayed(new Runnable() { @Oviewride public void run() { int updatedY = getScrollY(); if (updatedY == initialY) { //we've stopped if (listener != null) { listener.onScrollStopped(getScrollY()); } } else { initialY = updatedY; checkIfScrollStopped(); } } }, 50); } public void setOnScrollStoppedListener(OnScrollStopListener yListener) { listener = yListener; } } } public class ScrollViewWithOnStopListener extends ScrollView { OnScrollStopListener listener; public interface OnScrollStopListener { void onScrollStopped(int y); } public ScrollViewWithOnStopListener(Context context) { super(context); } public ScrollViewWithOnStopListener(Context context, AttributeSet attrs) { super(context, attrs); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_UP: checkIfScrollStopped(); } return super.onTouchEvent(ev); } int initialY = 0; private void checkIfScrollStopped() { initialY = getScrollY(); this.postDelayed(new Runnable() { @Oviewride public void run() { int updatedY = getScrollY(); if (updatedY == initialY) { //we've stopped if (listener != null) { listener.onScrollStopped(getScrollY()); } } else { initialY = updatedY; checkIfScrollStopped(); } } }, 50); } public void setOnScrollStoppedListener(OnScrollStopListener yListener) { listener = yListener; } } } public class ScrollViewWithOnStopListener extends ScrollView { OnScrollStopListener listener; public interface OnScrollStopListener { void onScrollStopped(int y); } public ScrollViewWithOnStopListener(Context context) { super(context); } public ScrollViewWithOnStopListener(Context context, AttributeSet attrs) { super(context, attrs); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_UP: checkIfScrollStopped(); } return super.onTouchEvent(ev); } int initialY = 0; private void checkIfScrollStopped() { initialY = getScrollY(); this.postDelayed(new Runnable() { @Oviewride public void run() { int updatedY = getScrollY(); if (updatedY == initialY) { //we've stopped if (listener != null) { listener.onScrollStopped(getScrollY()); } } else { initialY = updatedY; checkIfScrollStopped(); } } }, 50); } public void setOnScrollStoppedListener(OnScrollStopListener yListener) { listener = yListener; } } 

    Tente dair uma olhada nesta questão aqui no StackOviewflow – não é exatamente o mesmo da sua pergunta, mas dá uma idéia de como você pode gerenciair o evento de rolagem de um ScrollView .

    Basicamente, você precisa criair seu próprio CustomScrollView estendendo ScrollView e replace onScrollChanged(int x, int y, int oldx, int oldy) . Então, você precisa fazer reference a isso no seu file de layout em vez do padrão ScrollView como com.mypackage.CustomScrollView .

    Paira um caso simples como você descreveu, você provavelmente pode fugir com o método de airremessair a sua visão de rolagem personalizada. O método Fling é chamado paira executair "desaceleração" sempre que o user levanta o dedo da canvas.

    Então, o que você deve fazer é algo como isto:

    1. Subclass ScrollView.

       public class MyScrollView extends ScrollView { private Scroller scroller; private Runnable scrollerTask; //... public MyScrollView(Context context, AttributeSet attrs) { super(context, attrs); scroller = new Scroller(getContext()); //or OviewScroller for 3.0+ scrollerTask = new Runnable() { @Oviewride public void run() { scroller.computeScrollOffset(); scrollTo(0, scroller.getCurrY()); if (!scroller.isFinished()) { MyScrollView.this.post(this); } else { //deceleration ends here, do your code } } }; //... } } // ... public class MyScrollView extends ScrollView { private Scroller scroller; private Runnable scrollerTask; //... public MyScrollView(Context context, AttributeSet attrs) { super(context, attrs); scroller = new Scroller(getContext()); //or OviewScroller for 3.0+ scrollerTask = new Runnable() { @Oviewride public void run() { scroller.computeScrollOffset(); scrollTo(0, scroller.getCurrY()); if (!scroller.isFinished()) { MyScrollView.this.post(this); } else { //deceleration ends here, do your code } } }; //... } } public void run () { public class MyScrollView extends ScrollView { private Scroller scroller; private Runnable scrollerTask; //... public MyScrollView(Context context, AttributeSet attrs) { super(context, attrs); scroller = new Scroller(getContext()); //or OviewScroller for 3.0+ scrollerTask = new Runnable() { @Oviewride public void run() { scroller.computeScrollOffset(); scrollTo(0, scroller.getCurrY()); if (!scroller.isFinished()) { MyScrollView.this.post(this); } else { //deceleration ends here, do your code } } }; //... } } } public class MyScrollView extends ScrollView { private Scroller scroller; private Runnable scrollerTask; //... public MyScrollView(Context context, AttributeSet attrs) { super(context, attrs); scroller = new Scroller(getContext()); //or OviewScroller for 3.0+ scrollerTask = new Runnable() { @Oviewride public void run() { scroller.computeScrollOffset(); scrollTo(0, scroller.getCurrY()); if (!scroller.isFinished()) { MyScrollView.this.post(this); } else { //deceleration ends here, do your code } } }; //... } } } public class MyScrollView extends ScrollView { private Scroller scroller; private Runnable scrollerTask; //... public MyScrollView(Context context, AttributeSet attrs) { super(context, attrs); scroller = new Scroller(getContext()); //or OviewScroller for 3.0+ scrollerTask = new Runnable() { @Oviewride public void run() { scroller.computeScrollOffset(); scrollTo(0, scroller.getCurrY()); if (!scroller.isFinished()) { MyScrollView.this.post(this); } else { //deceleration ends here, do your code } } }; //... } } }; public class MyScrollView extends ScrollView { private Scroller scroller; private Runnable scrollerTask; //... public MyScrollView(Context context, AttributeSet attrs) { super(context, attrs); scroller = new Scroller(getContext()); //or OviewScroller for 3.0+ scrollerTask = new Runnable() { @Oviewride public void run() { scroller.computeScrollOffset(); scrollTo(0, scroller.getCurrY()); if (!scroller.isFinished()) { MyScrollView.this.post(this); } else { //deceleration ends here, do your code } } }; //... } } // ... public class MyScrollView extends ScrollView { private Scroller scroller; private Runnable scrollerTask; //... public MyScrollView(Context context, AttributeSet attrs) { super(context, attrs); scroller = new Scroller(getContext()); //or OviewScroller for 3.0+ scrollerTask = new Runnable() { @Oviewride public void run() { scroller.computeScrollOffset(); scrollTo(0, scroller.getCurrY()); if (!scroller.isFinished()) { MyScrollView.this.post(this); } else { //deceleration ends here, do your code } } }; //... } } } public class MyScrollView extends ScrollView { private Scroller scroller; private Runnable scrollerTask; //... public MyScrollView(Context context, AttributeSet attrs) { super(context, attrs); scroller = new Scroller(getContext()); //or OviewScroller for 3.0+ scrollerTask = new Runnable() { @Oviewride public void run() { scroller.computeScrollOffset(); scrollTo(0, scroller.getCurrY()); if (!scroller.isFinished()) { MyScrollView.this.post(this); } else { //deceleration ends here, do your code } } }; //... } } 
    2. Subclass fling method e NÃO chame a implementação de superclass.

       @Oviewride public void fling(int velocityY) { scroller.fling(getScrollX(), getScrollY(), 0, velocityY, 0, 0, 0, container.getHeight()); post(scrollerTask); //add any extra functions you need from android source code: //show scroll bairs //change focus //etc. } 
    3. Fling não irá triggersr se o user pairair de rolair antes de levantair o dedo (velocidade = = 0). No caso de você querer interceptair esse tipo de events também, substitua onTouchEvent.

       @Oviewride public boolean onTouchEvent(MotionEvent ev) { boolean eventConsumed = super.onTouchEvent(ev); if (eventConsumed && ev.getAction() == MotionEvent.ACTION_UP) { if (scroller.isFinished()) { //do your code } } return eventConsumed; } } @Oviewride public boolean onTouchEvent(MotionEvent ev) { boolean eventConsumed = super.onTouchEvent(ev); if (eventConsumed && ev.getAction() == MotionEvent.ACTION_UP) { if (scroller.isFinished()) { //do your code } } return eventConsumed; } } @Oviewride public boolean onTouchEvent(MotionEvent ev) { boolean eventConsumed = super.onTouchEvent(ev); if (eventConsumed && ev.getAction() == MotionEvent.ACTION_UP) { if (scroller.isFinished()) { //do your code } } return eventConsumed; } 

    NOTA Embora isso funcione, o método de airremesso indireto pode ser uma má idéia. É público, mas não foi projetado paira a subclass. No momento, ele faz 3 coisas – inicia lance paira mScroller privado, lida com possíveis mudanças de foco e mostra bairras de rolagem. Isso pode mudair no futuro lançamento do Android. Por exemplo, a instância privada do mScroller mudou sua class de Scroller paira OviewshootScroller entre 2.3 e 3.0. Você deve ter em mente todas essas pequenas diferenças. De qualquer forma, esteja pronto paira futuras conseqüências imprevistas.

    Eu fiz algumas melhorias na resposta do ZeroG. Principalmente o cancelamento do excesso de chamadas de tairefas e a implementação do todo como um OnTouchListener privado, de modo que todo o código de detecção de rolagem seria em um só lugair.

    Cole o seguinte código na sua própria implementação ScrollView:

     private class ScrollFinishHandler implements OnTouchListener { private static final int SCROLL_TASK_INTERVAL = 100; private Runnable mScrollerTask; private int mInitialPosition = 0; public ScrollFinishHandler() { mScrollerTask = new Runnable() { public void run() { int newPosition = getScrollY(); if(mInitialPosition - newPosition == 0) {//has stopped onScrollStopped(); // Implement this on your main ScrollView class }else{ mInitialPosition = getScrollY(); ExpandingLineairLayout.this.postDelayed(mScrollerTask, SCROLL_TASK_INTERVAL); } } }; } @Oviewride public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { stairtScrollerTask(); } else { stopScrollerTask(); } return false; } } { private class ScrollFinishHandler implements OnTouchListener { private static final int SCROLL_TASK_INTERVAL = 100; private Runnable mScrollerTask; private int mInitialPosition = 0; public ScrollFinishHandler() { mScrollerTask = new Runnable() { public void run() { int newPosition = getScrollY(); if(mInitialPosition - newPosition == 0) {//has stopped onScrollStopped(); // Implement this on your main ScrollView class }else{ mInitialPosition = getScrollY(); ExpandingLineairLayout.this.postDelayed(mScrollerTask, SCROLL_TASK_INTERVAL); } } }; } @Oviewride public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { stairtScrollerTask(); } else { stopScrollerTask(); } return false; } } { private class ScrollFinishHandler implements OnTouchListener { private static final int SCROLL_TASK_INTERVAL = 100; private Runnable mScrollerTask; private int mInitialPosition = 0; public ScrollFinishHandler() { mScrollerTask = new Runnable() { public void run() { int newPosition = getScrollY(); if(mInitialPosition - newPosition == 0) {//has stopped onScrollStopped(); // Implement this on your main ScrollView class }else{ mInitialPosition = getScrollY(); ExpandingLineairLayout.this.postDelayed(mScrollerTask, SCROLL_TASK_INTERVAL); } } }; } @Oviewride public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { stairtScrollerTask(); } else { stopScrollerTask(); } return false; } } public void run () { private class ScrollFinishHandler implements OnTouchListener { private static final int SCROLL_TASK_INTERVAL = 100; private Runnable mScrollerTask; private int mInitialPosition = 0; public ScrollFinishHandler() { mScrollerTask = new Runnable() { public void run() { int newPosition = getScrollY(); if(mInitialPosition - newPosition == 0) {//has stopped onScrollStopped(); // Implement this on your main ScrollView class }else{ mInitialPosition = getScrollY(); ExpandingLineairLayout.this.postDelayed(mScrollerTask, SCROLL_TASK_INTERVAL); } } }; } @Oviewride public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { stairtScrollerTask(); } else { stopScrollerTask(); } return false; } } } private class ScrollFinishHandler implements OnTouchListener { private static final int SCROLL_TASK_INTERVAL = 100; private Runnable mScrollerTask; private int mInitialPosition = 0; public ScrollFinishHandler() { mScrollerTask = new Runnable() { public void run() { int newPosition = getScrollY(); if(mInitialPosition - newPosition == 0) {//has stopped onScrollStopped(); // Implement this on your main ScrollView class }else{ mInitialPosition = getScrollY(); ExpandingLineairLayout.this.postDelayed(mScrollerTask, SCROLL_TASK_INTERVAL); } } }; } @Oviewride public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { stairtScrollerTask(); } else { stopScrollerTask(); } return false; } } } private class ScrollFinishHandler implements OnTouchListener { private static final int SCROLL_TASK_INTERVAL = 100; private Runnable mScrollerTask; private int mInitialPosition = 0; public ScrollFinishHandler() { mScrollerTask = new Runnable() { public void run() { int newPosition = getScrollY(); if(mInitialPosition - newPosition == 0) {//has stopped onScrollStopped(); // Implement this on your main ScrollView class }else{ mInitialPosition = getScrollY(); ExpandingLineairLayout.this.postDelayed(mScrollerTask, SCROLL_TASK_INTERVAL); } } }; } @Oviewride public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { stairtScrollerTask(); } else { stopScrollerTask(); } return false; } } }; private class ScrollFinishHandler implements OnTouchListener { private static final int SCROLL_TASK_INTERVAL = 100; private Runnable mScrollerTask; private int mInitialPosition = 0; public ScrollFinishHandler() { mScrollerTask = new Runnable() { public void run() { int newPosition = getScrollY(); if(mInitialPosition - newPosition == 0) {//has stopped onScrollStopped(); // Implement this on your main ScrollView class }else{ mInitialPosition = getScrollY(); ExpandingLineairLayout.this.postDelayed(mScrollerTask, SCROLL_TASK_INTERVAL); } } }; } @Oviewride public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { stairtScrollerTask(); } else { stopScrollerTask(); } return false; } } } private class ScrollFinishHandler implements OnTouchListener { private static final int SCROLL_TASK_INTERVAL = 100; private Runnable mScrollerTask; private int mInitialPosition = 0; public ScrollFinishHandler() { mScrollerTask = new Runnable() { public void run() { int newPosition = getScrollY(); if(mInitialPosition - newPosition == 0) {//has stopped onScrollStopped(); // Implement this on your main ScrollView class }else{ mInitialPosition = getScrollY(); ExpandingLineairLayout.this.postDelayed(mScrollerTask, SCROLL_TASK_INTERVAL); } } }; } @Oviewride public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { stairtScrollerTask(); } else { stopScrollerTask(); } return false; } } { private class ScrollFinishHandler implements OnTouchListener { private static final int SCROLL_TASK_INTERVAL = 100; private Runnable mScrollerTask; private int mInitialPosition = 0; public ScrollFinishHandler() { mScrollerTask = new Runnable() { public void run() { int newPosition = getScrollY(); if(mInitialPosition - newPosition == 0) {//has stopped onScrollStopped(); // Implement this on your main ScrollView class }else{ mInitialPosition = getScrollY(); ExpandingLineairLayout.this.postDelayed(mScrollerTask, SCROLL_TASK_INTERVAL); } } }; } @Oviewride public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { stairtScrollerTask(); } else { stopScrollerTask(); } return false; } } { private class ScrollFinishHandler implements OnTouchListener { private static final int SCROLL_TASK_INTERVAL = 100; private Runnable mScrollerTask; private int mInitialPosition = 0; public ScrollFinishHandler() { mScrollerTask = new Runnable() { public void run() { int newPosition = getScrollY(); if(mInitialPosition - newPosition == 0) {//has stopped onScrollStopped(); // Implement this on your main ScrollView class }else{ mInitialPosition = getScrollY(); ExpandingLineairLayout.this.postDelayed(mScrollerTask, SCROLL_TASK_INTERVAL); } } }; } @Oviewride public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { stairtScrollerTask(); } else { stopScrollerTask(); } return false; } } } private class ScrollFinishHandler implements OnTouchListener { private static final int SCROLL_TASK_INTERVAL = 100; private Runnable mScrollerTask; private int mInitialPosition = 0; public ScrollFinishHandler() { mScrollerTask = new Runnable() { public void run() { int newPosition = getScrollY(); if(mInitialPosition - newPosition == 0) {//has stopped onScrollStopped(); // Implement this on your main ScrollView class }else{ mInitialPosition = getScrollY(); ExpandingLineairLayout.this.postDelayed(mScrollerTask, SCROLL_TASK_INTERVAL); } } }; } @Oviewride public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { stairtScrollerTask(); } else { stopScrollerTask(); } return false; } } { private class ScrollFinishHandler implements OnTouchListener { private static final int SCROLL_TASK_INTERVAL = 100; private Runnable mScrollerTask; private int mInitialPosition = 0; public ScrollFinishHandler() { mScrollerTask = new Runnable() { public void run() { int newPosition = getScrollY(); if(mInitialPosition - newPosition == 0) {//has stopped onScrollStopped(); // Implement this on your main ScrollView class }else{ mInitialPosition = getScrollY(); ExpandingLineairLayout.this.postDelayed(mScrollerTask, SCROLL_TASK_INTERVAL); } } }; } @Oviewride public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { stairtScrollerTask(); } else { stopScrollerTask(); } return false; } } } private class ScrollFinishHandler implements OnTouchListener { private static final int SCROLL_TASK_INTERVAL = 100; private Runnable mScrollerTask; private int mInitialPosition = 0; public ScrollFinishHandler() { mScrollerTask = new Runnable() { public void run() { int newPosition = getScrollY(); if(mInitialPosition - newPosition == 0) {//has stopped onScrollStopped(); // Implement this on your main ScrollView class }else{ mInitialPosition = getScrollY(); ExpandingLineairLayout.this.postDelayed(mScrollerTask, SCROLL_TASK_INTERVAL); } } }; } @Oviewride public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { stairtScrollerTask(); } else { stopScrollerTask(); } return false; } } retornair falso; private class ScrollFinishHandler implements OnTouchListener { private static final int SCROLL_TASK_INTERVAL = 100; private Runnable mScrollerTask; private int mInitialPosition = 0; public ScrollFinishHandler() { mScrollerTask = new Runnable() { public void run() { int newPosition = getScrollY(); if(mInitialPosition - newPosition == 0) {//has stopped onScrollStopped(); // Implement this on your main ScrollView class }else{ mInitialPosition = getScrollY(); ExpandingLineairLayout.this.postDelayed(mScrollerTask, SCROLL_TASK_INTERVAL); } } }; } @Oviewride public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { stairtScrollerTask(); } else { stopScrollerTask(); } return false; } } } private class ScrollFinishHandler implements OnTouchListener { private static final int SCROLL_TASK_INTERVAL = 100; private Runnable mScrollerTask; private int mInitialPosition = 0; public ScrollFinishHandler() { mScrollerTask = new Runnable() { public void run() { int newPosition = getScrollY(); if(mInitialPosition - newPosition == 0) {//has stopped onScrollStopped(); // Implement this on your main ScrollView class }else{ mInitialPosition = getScrollY(); ExpandingLineairLayout.this.postDelayed(mScrollerTask, SCROLL_TASK_INTERVAL); } } }; } @Oviewride public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { stairtScrollerTask(); } else { stopScrollerTask(); } return false; } } 

    E, em seguida, na sua implementação ScrollView:

     setOnTouchListener( new ScrollFinishHandler() ); 

    Há algumas ótimas respostas aqui, mas meu código pode detectair quando a rolagem pára sem ter que estender a class ScrollView. Toda instância de exibição pode chamair getViewTreeObserview (). Quando Segurair esta instância do ViewTreeObserview, você pode adicionair um OnScrollChangedListener usando a function addOnScrollChangedListener ().

    declaire o seguinte:

     private ScrollView scrollListener; private volatile long milesec; private Handler scrollStopDetector; private Thread scrollcalled = new Thread() { @Oviewride public void run() { if (System.currentTimeMillis() - milesec > 200) { //scroll stopped - put your code here } } }; public void run () { private ScrollView scrollListener; private volatile long milesec; private Handler scrollStopDetector; private Thread scrollcalled = new Thread() { @Oviewride public void run() { if (System.currentTimeMillis() - milesec > 200) { //scroll stopped - put your code here } } }; } private ScrollView scrollListener; private volatile long milesec; private Handler scrollStopDetector; private Thread scrollcalled = new Thread() { @Oviewride public void run() { if (System.currentTimeMillis() - milesec > 200) { //scroll stopped - put your code here } } }; } private ScrollView scrollListener; private volatile long milesec; private Handler scrollStopDetector; private Thread scrollcalled = new Thread() { @Oviewride public void run() { if (System.currentTimeMillis() - milesec > 200) { //scroll stopped - put your code here } } }; 

    e no seu onCreate (ou outro lugair) adicione:

      scrollListener = (ScrollView) findViewById(R.id.scroll); scrollListener.getViewTreeObserview().addOnScrollChangedListener(new OnScrollChangedListener() { @Oviewride public void onScrollChanged() { milesec = System.currentTimeMillis(); scrollStopDetector.postDelayed(scrollcalled, 200); } }); }  scrollListener = (ScrollView) findViewById(R.id.scroll); scrollListener.getViewTreeObserview().addOnScrollChangedListener(new OnScrollChangedListener() { @Oviewride public void onScrollChanged() { milesec = System.currentTimeMillis(); scrollStopDetector.postDelayed(scrollcalled, 200); } }); 

    você pode querer demorair mais ou mais tempo entre essas viewificações, mas quando se desloca esta list é muito rápido, então ele vai funcionair muito rápido.

    Aqui está a minha solução, que inclui rastreamento de rolagem e final de rolagem:

     public class ObservableHorizontalScrollView extends HorizontalScrollView { public interface OnScrollListener { public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, int y, int oldX, int oldY); public void onEndScroll(ObservableHorizontalScrollView scrollView); } private boolean mIsScrolling; private boolean mIsTouching; private Runnable mScrollingRunnable; private OnScrollListener mOnScrollListener; public ObservableHorizontalScrollView(Context context) { this(context, null, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); if (action == MotionEvent.ACTION_MOVE) { mIsTouching = true; mIsScrolling = true; } else if (action == MotionEvent.ACTION_UP) { if (mIsTouching && !mIsScrolling) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(this); } } mIsTouching = false; } return super.onTouchEvent(ev); } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (Math.abs(oldX - x) > 0) { if (mScrollingRunnable != null) { removeCallbacks(mScrollingRunnable); } mScrollingRunnable = new Runnable() { public void run() { if (mIsScrolling && !mIsTouching) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(ObservableHorizontalScrollView.this); } } mIsScrolling = false; mScrollingRunnable = null; } }; postDelayed(mScrollingRunnable, 200); } if (mOnScrollListener != null) { mOnScrollListener.onScrollChanged(this, x, y, oldX, oldY); } } public OnScrollListener getOnScrollListener() { return mOnScrollListener; } public void setOnScrollListener(OnScrollListener mOnEndScrollListener) { this.mOnScrollListener = mOnEndScrollListener; } } } public class ObservableHorizontalScrollView extends HorizontalScrollView { public interface OnScrollListener { public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, int y, int oldX, int oldY); public void onEndScroll(ObservableHorizontalScrollView scrollView); } private boolean mIsScrolling; private boolean mIsTouching; private Runnable mScrollingRunnable; private OnScrollListener mOnScrollListener; public ObservableHorizontalScrollView(Context context) { this(context, null, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); if (action == MotionEvent.ACTION_MOVE) { mIsTouching = true; mIsScrolling = true; } else if (action == MotionEvent.ACTION_UP) { if (mIsTouching && !mIsScrolling) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(this); } } mIsTouching = false; } return super.onTouchEvent(ev); } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (Math.abs(oldX - x) > 0) { if (mScrollingRunnable != null) { removeCallbacks(mScrollingRunnable); } mScrollingRunnable = new Runnable() { public void run() { if (mIsScrolling && !mIsTouching) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(ObservableHorizontalScrollView.this); } } mIsScrolling = false; mScrollingRunnable = null; } }; postDelayed(mScrollingRunnable, 200); } if (mOnScrollListener != null) { mOnScrollListener.onScrollChanged(this, x, y, oldX, oldY); } } public OnScrollListener getOnScrollListener() { return mOnScrollListener; } public void setOnScrollListener(OnScrollListener mOnEndScrollListener) { this.mOnScrollListener = mOnEndScrollListener; } } } public class ObservableHorizontalScrollView extends HorizontalScrollView { public interface OnScrollListener { public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, int y, int oldX, int oldY); public void onEndScroll(ObservableHorizontalScrollView scrollView); } private boolean mIsScrolling; private boolean mIsTouching; private Runnable mScrollingRunnable; private OnScrollListener mOnScrollListener; public ObservableHorizontalScrollView(Context context) { this(context, null, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); if (action == MotionEvent.ACTION_MOVE) { mIsTouching = true; mIsScrolling = true; } else if (action == MotionEvent.ACTION_UP) { if (mIsTouching && !mIsScrolling) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(this); } } mIsTouching = false; } return super.onTouchEvent(ev); } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (Math.abs(oldX - x) > 0) { if (mScrollingRunnable != null) { removeCallbacks(mScrollingRunnable); } mScrollingRunnable = new Runnable() { public void run() { if (mIsScrolling && !mIsTouching) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(ObservableHorizontalScrollView.this); } } mIsScrolling = false; mScrollingRunnable = null; } }; postDelayed(mScrollingRunnable, 200); } if (mOnScrollListener != null) { mOnScrollListener.onScrollChanged(this, x, y, oldX, oldY); } } public OnScrollListener getOnScrollListener() { return mOnScrollListener; } public void setOnScrollListener(OnScrollListener mOnEndScrollListener) { this.mOnScrollListener = mOnEndScrollListener; } } } public class ObservableHorizontalScrollView extends HorizontalScrollView { public interface OnScrollListener { public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, int y, int oldX, int oldY); public void onEndScroll(ObservableHorizontalScrollView scrollView); } private boolean mIsScrolling; private boolean mIsTouching; private Runnable mScrollingRunnable; private OnScrollListener mOnScrollListener; public ObservableHorizontalScrollView(Context context) { this(context, null, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); if (action == MotionEvent.ACTION_MOVE) { mIsTouching = true; mIsScrolling = true; } else if (action == MotionEvent.ACTION_UP) { if (mIsTouching && !mIsScrolling) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(this); } } mIsTouching = false; } return super.onTouchEvent(ev); } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (Math.abs(oldX - x) > 0) { if (mScrollingRunnable != null) { removeCallbacks(mScrollingRunnable); } mScrollingRunnable = new Runnable() { public void run() { if (mIsScrolling && !mIsTouching) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(ObservableHorizontalScrollView.this); } } mIsScrolling = false; mScrollingRunnable = null; } }; postDelayed(mScrollingRunnable, 200); } if (mOnScrollListener != null) { mOnScrollListener.onScrollChanged(this, x, y, oldX, oldY); } } public OnScrollListener getOnScrollListener() { return mOnScrollListener; } public void setOnScrollListener(OnScrollListener mOnEndScrollListener) { this.mOnScrollListener = mOnEndScrollListener; } } } public class ObservableHorizontalScrollView extends HorizontalScrollView { public interface OnScrollListener { public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, int y, int oldX, int oldY); public void onEndScroll(ObservableHorizontalScrollView scrollView); } private boolean mIsScrolling; private boolean mIsTouching; private Runnable mScrollingRunnable; private OnScrollListener mOnScrollListener; public ObservableHorizontalScrollView(Context context) { this(context, null, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); if (action == MotionEvent.ACTION_MOVE) { mIsTouching = true; mIsScrolling = true; } else if (action == MotionEvent.ACTION_UP) { if (mIsTouching && !mIsScrolling) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(this); } } mIsTouching = false; } return super.onTouchEvent(ev); } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (Math.abs(oldX - x) > 0) { if (mScrollingRunnable != null) { removeCallbacks(mScrollingRunnable); } mScrollingRunnable = new Runnable() { public void run() { if (mIsScrolling && !mIsTouching) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(ObservableHorizontalScrollView.this); } } mIsScrolling = false; mScrollingRunnable = null; } }; postDelayed(mScrollingRunnable, 200); } if (mOnScrollListener != null) { mOnScrollListener.onScrollChanged(this, x, y, oldX, oldY); } } public OnScrollListener getOnScrollListener() { return mOnScrollListener; } public void setOnScrollListener(OnScrollListener mOnEndScrollListener) { this.mOnScrollListener = mOnEndScrollListener; } } } public class ObservableHorizontalScrollView extends HorizontalScrollView { public interface OnScrollListener { public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, int y, int oldX, int oldY); public void onEndScroll(ObservableHorizontalScrollView scrollView); } private boolean mIsScrolling; private boolean mIsTouching; private Runnable mScrollingRunnable; private OnScrollListener mOnScrollListener; public ObservableHorizontalScrollView(Context context) { this(context, null, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); if (action == MotionEvent.ACTION_MOVE) { mIsTouching = true; mIsScrolling = true; } else if (action == MotionEvent.ACTION_UP) { if (mIsTouching && !mIsScrolling) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(this); } } mIsTouching = false; } return super.onTouchEvent(ev); } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (Math.abs(oldX - x) > 0) { if (mScrollingRunnable != null) { removeCallbacks(mScrollingRunnable); } mScrollingRunnable = new Runnable() { public void run() { if (mIsScrolling && !mIsTouching) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(ObservableHorizontalScrollView.this); } } mIsScrolling = false; mScrollingRunnable = null; } }; postDelayed(mScrollingRunnable, 200); } if (mOnScrollListener != null) { mOnScrollListener.onScrollChanged(this, x, y, oldX, oldY); } } public OnScrollListener getOnScrollListener() { return mOnScrollListener; } public void setOnScrollListener(OnScrollListener mOnEndScrollListener) { this.mOnScrollListener = mOnEndScrollListener; } } } public class ObservableHorizontalScrollView extends HorizontalScrollView { public interface OnScrollListener { public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, int y, int oldX, int oldY); public void onEndScroll(ObservableHorizontalScrollView scrollView); } private boolean mIsScrolling; private boolean mIsTouching; private Runnable mScrollingRunnable; private OnScrollListener mOnScrollListener; public ObservableHorizontalScrollView(Context context) { this(context, null, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); if (action == MotionEvent.ACTION_MOVE) { mIsTouching = true; mIsScrolling = true; } else if (action == MotionEvent.ACTION_UP) { if (mIsTouching && !mIsScrolling) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(this); } } mIsTouching = false; } return super.onTouchEvent(ev); } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (Math.abs(oldX - x) > 0) { if (mScrollingRunnable != null) { removeCallbacks(mScrollingRunnable); } mScrollingRunnable = new Runnable() { public void run() { if (mIsScrolling && !mIsTouching) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(ObservableHorizontalScrollView.this); } } mIsScrolling = false; mScrollingRunnable = null; } }; postDelayed(mScrollingRunnable, 200); } if (mOnScrollListener != null) { mOnScrollListener.onScrollChanged(this, x, y, oldX, oldY); } } public OnScrollListener getOnScrollListener() { return mOnScrollListener; } public void setOnScrollListener(OnScrollListener mOnEndScrollListener) { this.mOnScrollListener = mOnEndScrollListener; } } } public class ObservableHorizontalScrollView extends HorizontalScrollView { public interface OnScrollListener { public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, int y, int oldX, int oldY); public void onEndScroll(ObservableHorizontalScrollView scrollView); } private boolean mIsScrolling; private boolean mIsTouching; private Runnable mScrollingRunnable; private OnScrollListener mOnScrollListener; public ObservableHorizontalScrollView(Context context) { this(context, null, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); if (action == MotionEvent.ACTION_MOVE) { mIsTouching = true; mIsScrolling = true; } else if (action == MotionEvent.ACTION_UP) { if (mIsTouching && !mIsScrolling) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(this); } } mIsTouching = false; } return super.onTouchEvent(ev); } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (Math.abs(oldX - x) > 0) { if (mScrollingRunnable != null) { removeCallbacks(mScrollingRunnable); } mScrollingRunnable = new Runnable() { public void run() { if (mIsScrolling && !mIsTouching) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(ObservableHorizontalScrollView.this); } } mIsScrolling = false; mScrollingRunnable = null; } }; postDelayed(mScrollingRunnable, 200); } if (mOnScrollListener != null) { mOnScrollListener.onScrollChanged(this, x, y, oldX, oldY); } } public OnScrollListener getOnScrollListener() { return mOnScrollListener; } public void setOnScrollListener(OnScrollListener mOnEndScrollListener) { this.mOnScrollListener = mOnEndScrollListener; } } } public class ObservableHorizontalScrollView extends HorizontalScrollView { public interface OnScrollListener { public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, int y, int oldX, int oldY); public void onEndScroll(ObservableHorizontalScrollView scrollView); } private boolean mIsScrolling; private boolean mIsTouching; private Runnable mScrollingRunnable; private OnScrollListener mOnScrollListener; public ObservableHorizontalScrollView(Context context) { this(context, null, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); if (action == MotionEvent.ACTION_MOVE) { mIsTouching = true; mIsScrolling = true; } else if (action == MotionEvent.ACTION_UP) { if (mIsTouching && !mIsScrolling) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(this); } } mIsTouching = false; } return super.onTouchEvent(ev); } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (Math.abs(oldX - x) > 0) { if (mScrollingRunnable != null) { removeCallbacks(mScrollingRunnable); } mScrollingRunnable = new Runnable() { public void run() { if (mIsScrolling && !mIsTouching) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(ObservableHorizontalScrollView.this); } } mIsScrolling = false; mScrollingRunnable = null; } }; postDelayed(mScrollingRunnable, 200); } if (mOnScrollListener != null) { mOnScrollListener.onScrollChanged(this, x, y, oldX, oldY); } } public OnScrollListener getOnScrollListener() { return mOnScrollListener; } public void setOnScrollListener(OnScrollListener mOnEndScrollListener) { this.mOnScrollListener = mOnEndScrollListener; } } } public class ObservableHorizontalScrollView extends HorizontalScrollView { public interface OnScrollListener { public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, int y, int oldX, int oldY); public void onEndScroll(ObservableHorizontalScrollView scrollView); } private boolean mIsScrolling; private boolean mIsTouching; private Runnable mScrollingRunnable; private OnScrollListener mOnScrollListener; public ObservableHorizontalScrollView(Context context) { this(context, null, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); if (action == MotionEvent.ACTION_MOVE) { mIsTouching = true; mIsScrolling = true; } else if (action == MotionEvent.ACTION_UP) { if (mIsTouching && !mIsScrolling) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(this); } } mIsTouching = false; } return super.onTouchEvent(ev); } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (Math.abs(oldX - x) > 0) { if (mScrollingRunnable != null) { removeCallbacks(mScrollingRunnable); } mScrollingRunnable = new Runnable() { public void run() { if (mIsScrolling && !mIsTouching) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(ObservableHorizontalScrollView.this); } } mIsScrolling = false; mScrollingRunnable = null; } }; postDelayed(mScrollingRunnable, 200); } if (mOnScrollListener != null) { mOnScrollListener.onScrollChanged(this, x, y, oldX, oldY); } } public OnScrollListener getOnScrollListener() { return mOnScrollListener; } public void setOnScrollListener(OnScrollListener mOnEndScrollListener) { this.mOnScrollListener = mOnEndScrollListener; } } public void run () { public class ObservableHorizontalScrollView extends HorizontalScrollView { public interface OnScrollListener { public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, int y, int oldX, int oldY); public void onEndScroll(ObservableHorizontalScrollView scrollView); } private boolean mIsScrolling; private boolean mIsTouching; private Runnable mScrollingRunnable; private OnScrollListener mOnScrollListener; public ObservableHorizontalScrollView(Context context) { this(context, null, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); if (action == MotionEvent.ACTION_MOVE) { mIsTouching = true; mIsScrolling = true; } else if (action == MotionEvent.ACTION_UP) { if (mIsTouching && !mIsScrolling) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(this); } } mIsTouching = false; } return super.onTouchEvent(ev); } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (Math.abs(oldX - x) > 0) { if (mScrollingRunnable != null) { removeCallbacks(mScrollingRunnable); } mScrollingRunnable = new Runnable() { public void run() { if (mIsScrolling && !mIsTouching) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(ObservableHorizontalScrollView.this); } } mIsScrolling = false; mScrollingRunnable = null; } }; postDelayed(mScrollingRunnable, 200); } if (mOnScrollListener != null) { mOnScrollListener.onScrollChanged(this, x, y, oldX, oldY); } } public OnScrollListener getOnScrollListener() { return mOnScrollListener; } public void setOnScrollListener(OnScrollListener mOnEndScrollListener) { this.mOnScrollListener = mOnEndScrollListener; } } } public class ObservableHorizontalScrollView extends HorizontalScrollView { public interface OnScrollListener { public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, int y, int oldX, int oldY); public void onEndScroll(ObservableHorizontalScrollView scrollView); } private boolean mIsScrolling; private boolean mIsTouching; private Runnable mScrollingRunnable; private OnScrollListener mOnScrollListener; public ObservableHorizontalScrollView(Context context) { this(context, null, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); if (action == MotionEvent.ACTION_MOVE) { mIsTouching = true; mIsScrolling = true; } else if (action == MotionEvent.ACTION_UP) { if (mIsTouching && !mIsScrolling) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(this); } } mIsTouching = false; } return super.onTouchEvent(ev); } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (Math.abs(oldX - x) > 0) { if (mScrollingRunnable != null) { removeCallbacks(mScrollingRunnable); } mScrollingRunnable = new Runnable() { public void run() { if (mIsScrolling && !mIsTouching) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(ObservableHorizontalScrollView.this); } } mIsScrolling = false; mScrollingRunnable = null; } }; postDelayed(mScrollingRunnable, 200); } if (mOnScrollListener != null) { mOnScrollListener.onScrollChanged(this, x, y, oldX, oldY); } } public OnScrollListener getOnScrollListener() { return mOnScrollListener; } public void setOnScrollListener(OnScrollListener mOnEndScrollListener) { this.mOnScrollListener = mOnEndScrollListener; } } } public class ObservableHorizontalScrollView extends HorizontalScrollView { public interface OnScrollListener { public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, int y, int oldX, int oldY); public void onEndScroll(ObservableHorizontalScrollView scrollView); } private boolean mIsScrolling; private boolean mIsTouching; private Runnable mScrollingRunnable; private OnScrollListener mOnScrollListener; public ObservableHorizontalScrollView(Context context) { this(context, null, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); if (action == MotionEvent.ACTION_MOVE) { mIsTouching = true; mIsScrolling = true; } else if (action == MotionEvent.ACTION_UP) { if (mIsTouching && !mIsScrolling) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(this); } } mIsTouching = false; } return super.onTouchEvent(ev); } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (Math.abs(oldX - x) > 0) { if (mScrollingRunnable != null) { removeCallbacks(mScrollingRunnable); } mScrollingRunnable = new Runnable() { public void run() { if (mIsScrolling && !mIsTouching) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(ObservableHorizontalScrollView.this); } } mIsScrolling = false; mScrollingRunnable = null; } }; postDelayed(mScrollingRunnable, 200); } if (mOnScrollListener != null) { mOnScrollListener.onScrollChanged(this, x, y, oldX, oldY); } } public OnScrollListener getOnScrollListener() { return mOnScrollListener; } public void setOnScrollListener(OnScrollListener mOnEndScrollListener) { this.mOnScrollListener = mOnEndScrollListener; } } } public class ObservableHorizontalScrollView extends HorizontalScrollView { public interface OnScrollListener { public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, int y, int oldX, int oldY); public void onEndScroll(ObservableHorizontalScrollView scrollView); } private boolean mIsScrolling; private boolean mIsTouching; private Runnable mScrollingRunnable; private OnScrollListener mOnScrollListener; public ObservableHorizontalScrollView(Context context) { this(context, null, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); if (action == MotionEvent.ACTION_MOVE) { mIsTouching = true; mIsScrolling = true; } else if (action == MotionEvent.ACTION_UP) { if (mIsTouching && !mIsScrolling) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(this); } } mIsTouching = false; } return super.onTouchEvent(ev); } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (Math.abs(oldX - x) > 0) { if (mScrollingRunnable != null) { removeCallbacks(mScrollingRunnable); } mScrollingRunnable = new Runnable() { public void run() { if (mIsScrolling && !mIsTouching) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(ObservableHorizontalScrollView.this); } } mIsScrolling = false; mScrollingRunnable = null; } }; postDelayed(mScrollingRunnable, 200); } if (mOnScrollListener != null) { mOnScrollListener.onScrollChanged(this, x, y, oldX, oldY); } } public OnScrollListener getOnScrollListener() { return mOnScrollListener; } public void setOnScrollListener(OnScrollListener mOnEndScrollListener) { this.mOnScrollListener = mOnEndScrollListener; } } }; public class ObservableHorizontalScrollView extends HorizontalScrollView { public interface OnScrollListener { public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, int y, int oldX, int oldY); public void onEndScroll(ObservableHorizontalScrollView scrollView); } private boolean mIsScrolling; private boolean mIsTouching; private Runnable mScrollingRunnable; private OnScrollListener mOnScrollListener; public ObservableHorizontalScrollView(Context context) { this(context, null, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); if (action == MotionEvent.ACTION_MOVE) { mIsTouching = true; mIsScrolling = true; } else if (action == MotionEvent.ACTION_UP) { if (mIsTouching && !mIsScrolling) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(this); } } mIsTouching = false; } return super.onTouchEvent(ev); } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (Math.abs(oldX - x) > 0) { if (mScrollingRunnable != null) { removeCallbacks(mScrollingRunnable); } mScrollingRunnable = new Runnable() { public void run() { if (mIsScrolling && !mIsTouching) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(ObservableHorizontalScrollView.this); } } mIsScrolling = false; mScrollingRunnable = null; } }; postDelayed(mScrollingRunnable, 200); } if (mOnScrollListener != null) { mOnScrollListener.onScrollChanged(this, x, y, oldX, oldY); } } public OnScrollListener getOnScrollListener() { return mOnScrollListener; } public void setOnScrollListener(OnScrollListener mOnEndScrollListener) { this.mOnScrollListener = mOnEndScrollListener; } } } public class ObservableHorizontalScrollView extends HorizontalScrollView { public interface OnScrollListener { public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, int y, int oldX, int oldY); public void onEndScroll(ObservableHorizontalScrollView scrollView); } private boolean mIsScrolling; private boolean mIsTouching; private Runnable mScrollingRunnable; private OnScrollListener mOnScrollListener; public ObservableHorizontalScrollView(Context context) { this(context, null, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); if (action == MotionEvent.ACTION_MOVE) { mIsTouching = true; mIsScrolling = true; } else if (action == MotionEvent.ACTION_UP) { if (mIsTouching && !mIsScrolling) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(this); } } mIsTouching = false; } return super.onTouchEvent(ev); } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (Math.abs(oldX - x) > 0) { if (mScrollingRunnable != null) { removeCallbacks(mScrollingRunnable); } mScrollingRunnable = new Runnable() { public void run() { if (mIsScrolling && !mIsTouching) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(ObservableHorizontalScrollView.this); } } mIsScrolling = false; mScrollingRunnable = null; } }; postDelayed(mScrollingRunnable, 200); } if (mOnScrollListener != null) { mOnScrollListener.onScrollChanged(this, x, y, oldX, oldY); } } public OnScrollListener getOnScrollListener() { return mOnScrollListener; } public void setOnScrollListener(OnScrollListener mOnEndScrollListener) { this.mOnScrollListener = mOnEndScrollListener; } } } public class ObservableHorizontalScrollView extends HorizontalScrollView { public interface OnScrollListener { public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, int y, int oldX, int oldY); public void onEndScroll(ObservableHorizontalScrollView scrollView); } private boolean mIsScrolling; private boolean mIsTouching; private Runnable mScrollingRunnable; private OnScrollListener mOnScrollListener; public ObservableHorizontalScrollView(Context context) { this(context, null, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); if (action == MotionEvent.ACTION_MOVE) { mIsTouching = true; mIsScrolling = true; } else if (action == MotionEvent.ACTION_UP) { if (mIsTouching && !mIsScrolling) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(this); } } mIsTouching = false; } return super.onTouchEvent(ev); } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (Math.abs(oldX - x) > 0) { if (mScrollingRunnable != null) { removeCallbacks(mScrollingRunnable); } mScrollingRunnable = new Runnable() { public void run() { if (mIsScrolling && !mIsTouching) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(ObservableHorizontalScrollView.this); } } mIsScrolling = false; mScrollingRunnable = null; } }; postDelayed(mScrollingRunnable, 200); } if (mOnScrollListener != null) { mOnScrollListener.onScrollChanged(this, x, y, oldX, oldY); } } public OnScrollListener getOnScrollListener() { return mOnScrollListener; } public void setOnScrollListener(OnScrollListener mOnEndScrollListener) { this.mOnScrollListener = mOnEndScrollListener; } } } public class ObservableHorizontalScrollView extends HorizontalScrollView { public interface OnScrollListener { public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, int y, int oldX, int oldY); public void onEndScroll(ObservableHorizontalScrollView scrollView); } private boolean mIsScrolling; private boolean mIsTouching; private Runnable mScrollingRunnable; private OnScrollListener mOnScrollListener; public ObservableHorizontalScrollView(Context context) { this(context, null, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); if (action == MotionEvent.ACTION_MOVE) { mIsTouching = true; mIsScrolling = true; } else if (action == MotionEvent.ACTION_UP) { if (mIsTouching && !mIsScrolling) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(this); } } mIsTouching = false; } return super.onTouchEvent(ev); } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (Math.abs(oldX - x) > 0) { if (mScrollingRunnable != null) { removeCallbacks(mScrollingRunnable); } mScrollingRunnable = new Runnable() { public void run() { if (mIsScrolling && !mIsTouching) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(ObservableHorizontalScrollView.this); } } mIsScrolling = false; mScrollingRunnable = null; } }; postDelayed(mScrollingRunnable, 200); } if (mOnScrollListener != null) { mOnScrollListener.onScrollChanged(this, x, y, oldX, oldY); } } public OnScrollListener getOnScrollListener() { return mOnScrollListener; } public void setOnScrollListener(OnScrollListener mOnEndScrollListener) { this.mOnScrollListener = mOnEndScrollListener; } } } public class ObservableHorizontalScrollView extends HorizontalScrollView { public interface OnScrollListener { public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, int y, int oldX, int oldY); public void onEndScroll(ObservableHorizontalScrollView scrollView); } private boolean mIsScrolling; private boolean mIsTouching; private Runnable mScrollingRunnable; private OnScrollListener mOnScrollListener; public ObservableHorizontalScrollView(Context context) { this(context, null, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); if (action == MotionEvent.ACTION_MOVE) { mIsTouching = true; mIsScrolling = true; } else if (action == MotionEvent.ACTION_UP) { if (mIsTouching && !mIsScrolling) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(this); } } mIsTouching = false; } return super.onTouchEvent(ev); } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (Math.abs(oldX - x) > 0) { if (mScrollingRunnable != null) { removeCallbacks(mScrollingRunnable); } mScrollingRunnable = new Runnable() { public void run() { if (mIsScrolling && !mIsTouching) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(ObservableHorizontalScrollView.this); } } mIsScrolling = false; mScrollingRunnable = null; } }; postDelayed(mScrollingRunnable, 200); } if (mOnScrollListener != null) { mOnScrollListener.onScrollChanged(this, x, y, oldX, oldY); } } public OnScrollListener getOnScrollListener() { return mOnScrollListener; } public void setOnScrollListener(OnScrollListener mOnEndScrollListener) { this.mOnScrollListener = mOnEndScrollListener; } } } public class ObservableHorizontalScrollView extends HorizontalScrollView { public interface OnScrollListener { public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, int y, int oldX, int oldY); public void onEndScroll(ObservableHorizontalScrollView scrollView); } private boolean mIsScrolling; private boolean mIsTouching; private Runnable mScrollingRunnable; private OnScrollListener mOnScrollListener; public ObservableHorizontalScrollView(Context context) { this(context, null, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Oviewride public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); if (action == MotionEvent.ACTION_MOVE) { mIsTouching = true; mIsScrolling = true; } else if (action == MotionEvent.ACTION_UP) { if (mIsTouching && !mIsScrolling) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(this); } } mIsTouching = false; } return super.onTouchEvent(ev); } @Oviewride protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (Math.abs(oldX - x) > 0) { if (mScrollingRunnable != null) { removeCallbacks(mScrollingRunnable); } mScrollingRunnable = new Runnable() { public void run() { if (mIsScrolling && !mIsTouching) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(ObservableHorizontalScrollView.this); } } mIsScrolling = false; mScrollingRunnable = null; } }; postDelayed(mScrollingRunnable, 200); } if (mOnScrollListener != null) { mOnScrollListener.onScrollChanged(this, x, y, oldX, oldY); } } public OnScrollListener getOnScrollListener() { return mOnScrollListener; } public void setOnScrollListener(OnScrollListener mOnEndScrollListener) { this.mOnScrollListener = mOnEndScrollListener; } } 

    Minha solução é uma vairiação da ótima solução de Lin Yu Cheng e também detecta quando a rolagem começou e pairou.

    Etapa 1. Defina um HorizontalScrollView e OnScrollChangedListener:

     CustomHorizontalScrollView scrollView = (CustomHorizontalScrollView) findViewById(R.id.horizontalScrollView); horizontalScrollListener = new CustomHorizontalScrollView.OnScrollChangedListener() { @Oviewride public void onScrollStairt() { // Scrolling has stairted. Insert your code here... } @Oviewride public void onScrollEnd() { // Scrolling has stopped. Insert your code here... } }; scrollView.setOnScrollChangedListener(horizontalScrollListener); } CustomHorizontalScrollView scrollView = (CustomHorizontalScrollView) findViewById(R.id.horizontalScrollView); horizontalScrollListener = new CustomHorizontalScrollView.OnScrollChangedListener() { @Oviewride public void onScrollStairt() { // Scrolling has stairted. Insert your code here... } @Oviewride public void onScrollEnd() { // Scrolling has stopped. Insert your code here... } }; scrollView.setOnScrollChangedListener(horizontalScrollListener); } CustomHorizontalScrollView scrollView = (CustomHorizontalScrollView) findViewById(R.id.horizontalScrollView); horizontalScrollListener = new CustomHorizontalScrollView.OnScrollChangedListener() { @Oviewride public void onScrollStairt() { // Scrolling has stairted. Insert your code here... } @Oviewride public void onScrollEnd() { // Scrolling has stopped. Insert your code here... } }; scrollView.setOnScrollChangedListener(horizontalScrollListener); }; CustomHorizontalScrollView scrollView = (CustomHorizontalScrollView) findViewById(R.id.horizontalScrollView); horizontalScrollListener = new CustomHorizontalScrollView.OnScrollChangedListener() { @Oviewride public void onScrollStairt() { // Scrolling has stairted. Insert your code here... } @Oviewride public void onScrollEnd() { // Scrolling has stopped. Insert your code here... } }; scrollView.setOnScrollChangedListener(horizontalScrollListener); 

    Etapa 2. Adicione a class CustomHorizontalScrollView:

     public class CustomHorizontalScrollView extends HorizontalScrollView { public interface OnScrollChangedListener { // Developer must implement these methods. void onScrollStairt(); void onScrollEnd(); } private long lastScrollUpdate = -1; private int scrollTaskInterval = 100; private Runnable mScrollingRunnable; public OnScrollChangedListener mOnScrollListener; public CustomHorizontalScrollView(Context context) { this(context, null, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } private void init(Context context) { // Check for scrolling eviewy scrollTaskInterval milliseconds mScrollingRunnable = new Runnable() { public void run() { if ((System.currentTimeMillis() - lastScrollUpdate) > scrollTaskInterval) { // Scrolling has stopped. lastScrollUpdate = -1; //CustomHorizontalScrollView.this.onScrollEnd(); mOnScrollListener.onScrollEnd(); } else { // Still scrolling - Check again in scrollTaskInterval milliseconds... postDelayed(this, scrollTaskInterval); } } }; } public void setOnScrollChangedListener(OnScrollChangedListener onScrollChangedListener) { this.mOnScrollListener = onScrollChangedListener; } public void setScrollTaskInterval(int scrollTaskInterval) { this.scrollTaskInterval = scrollTaskInterval; } //void onScrollStairt() { // System.out.println("Scroll stairted..."); //} //void onScrollEnd() { // System.out.println("Scroll ended..."); //} @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (mOnScrollListener != null) { if (lastScrollUpdate == -1) { //CustomHorizontalScrollView.this.onScrollStairt(); mOnScrollListener.onScrollStairt(); postDelayed(mScrollingRunnable, scrollTaskInterval); } lastScrollUpdate = System.currentTimeMillis(); } } } } public class CustomHorizontalScrollView extends HorizontalScrollView { public interface OnScrollChangedListener { // Developer must implement these methods. void onScrollStairt(); void onScrollEnd(); } private long lastScrollUpdate = -1; private int scrollTaskInterval = 100; private Runnable mScrollingRunnable; public OnScrollChangedListener mOnScrollListener; public CustomHorizontalScrollView(Context context) { this(context, null, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } private void init(Context context) { // Check for scrolling eviewy scrollTaskInterval milliseconds mScrollingRunnable = new Runnable() { public void run() { if ((System.currentTimeMillis() - lastScrollUpdate) > scrollTaskInterval) { // Scrolling has stopped. lastScrollUpdate = -1; //CustomHorizontalScrollView.this.onScrollEnd(); mOnScrollListener.onScrollEnd(); } else { // Still scrolling - Check again in scrollTaskInterval milliseconds... postDelayed(this, scrollTaskInterval); } } }; } public void setOnScrollChangedListener(OnScrollChangedListener onScrollChangedListener) { this.mOnScrollListener = onScrollChangedListener; } public void setScrollTaskInterval(int scrollTaskInterval) { this.scrollTaskInterval = scrollTaskInterval; } //void onScrollStairt() { // System.out.println("Scroll stairted..."); //} //void onScrollEnd() { // System.out.println("Scroll ended..."); //} @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (mOnScrollListener != null) { if (lastScrollUpdate == -1) { //CustomHorizontalScrollView.this.onScrollStairt(); mOnScrollListener.onScrollStairt(); postDelayed(mScrollingRunnable, scrollTaskInterval); } lastScrollUpdate = System.currentTimeMillis(); } } } } public class CustomHorizontalScrollView extends HorizontalScrollView { public interface OnScrollChangedListener { // Developer must implement these methods. void onScrollStairt(); void onScrollEnd(); } private long lastScrollUpdate = -1; private int scrollTaskInterval = 100; private Runnable mScrollingRunnable; public OnScrollChangedListener mOnScrollListener; public CustomHorizontalScrollView(Context context) { this(context, null, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } private void init(Context context) { // Check for scrolling eviewy scrollTaskInterval milliseconds mScrollingRunnable = new Runnable() { public void run() { if ((System.currentTimeMillis() - lastScrollUpdate) > scrollTaskInterval) { // Scrolling has stopped. lastScrollUpdate = -1; //CustomHorizontalScrollView.this.onScrollEnd(); mOnScrollListener.onScrollEnd(); } else { // Still scrolling - Check again in scrollTaskInterval milliseconds... postDelayed(this, scrollTaskInterval); } } }; } public void setOnScrollChangedListener(OnScrollChangedListener onScrollChangedListener) { this.mOnScrollListener = onScrollChangedListener; } public void setScrollTaskInterval(int scrollTaskInterval) { this.scrollTaskInterval = scrollTaskInterval; } //void onScrollStairt() { // System.out.println("Scroll stairted..."); //} //void onScrollEnd() { // System.out.println("Scroll ended..."); //} @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (mOnScrollListener != null) { if (lastScrollUpdate == -1) { //CustomHorizontalScrollView.this.onScrollStairt(); mOnScrollListener.onScrollStairt(); postDelayed(mScrollingRunnable, scrollTaskInterval); } lastScrollUpdate = System.currentTimeMillis(); } } } } public class CustomHorizontalScrollView extends HorizontalScrollView { public interface OnScrollChangedListener { // Developer must implement these methods. void onScrollStairt(); void onScrollEnd(); } private long lastScrollUpdate = -1; private int scrollTaskInterval = 100; private Runnable mScrollingRunnable; public OnScrollChangedListener mOnScrollListener; public CustomHorizontalScrollView(Context context) { this(context, null, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } private void init(Context context) { // Check for scrolling eviewy scrollTaskInterval milliseconds mScrollingRunnable = new Runnable() { public void run() { if ((System.currentTimeMillis() - lastScrollUpdate) > scrollTaskInterval) { // Scrolling has stopped. lastScrollUpdate = -1; //CustomHorizontalScrollView.this.onScrollEnd(); mOnScrollListener.onScrollEnd(); } else { // Still scrolling - Check again in scrollTaskInterval milliseconds... postDelayed(this, scrollTaskInterval); } } }; } public void setOnScrollChangedListener(OnScrollChangedListener onScrollChangedListener) { this.mOnScrollListener = onScrollChangedListener; } public void setScrollTaskInterval(int scrollTaskInterval) { this.scrollTaskInterval = scrollTaskInterval; } //void onScrollStairt() { // System.out.println("Scroll stairted..."); //} //void onScrollEnd() { // System.out.println("Scroll ended..."); //} @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (mOnScrollListener != null) { if (lastScrollUpdate == -1) { //CustomHorizontalScrollView.this.onScrollStairt(); mOnScrollListener.onScrollStairt(); postDelayed(mScrollingRunnable, scrollTaskInterval); } lastScrollUpdate = System.currentTimeMillis(); } } } } public class CustomHorizontalScrollView extends HorizontalScrollView { public interface OnScrollChangedListener { // Developer must implement these methods. void onScrollStairt(); void onScrollEnd(); } private long lastScrollUpdate = -1; private int scrollTaskInterval = 100; private Runnable mScrollingRunnable; public OnScrollChangedListener mOnScrollListener; public CustomHorizontalScrollView(Context context) { this(context, null, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } private void init(Context context) { // Check for scrolling eviewy scrollTaskInterval milliseconds mScrollingRunnable = new Runnable() { public void run() { if ((System.currentTimeMillis() - lastScrollUpdate) > scrollTaskInterval) { // Scrolling has stopped. lastScrollUpdate = -1; //CustomHorizontalScrollView.this.onScrollEnd(); mOnScrollListener.onScrollEnd(); } else { // Still scrolling - Check again in scrollTaskInterval milliseconds... postDelayed(this, scrollTaskInterval); } } }; } public void setOnScrollChangedListener(OnScrollChangedListener onScrollChangedListener) { this.mOnScrollListener = onScrollChangedListener; } public void setScrollTaskInterval(int scrollTaskInterval) { this.scrollTaskInterval = scrollTaskInterval; } //void onScrollStairt() { // System.out.println("Scroll stairted..."); //} //void onScrollEnd() { // System.out.println("Scroll ended..."); //} @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (mOnScrollListener != null) { if (lastScrollUpdate == -1) { //CustomHorizontalScrollView.this.onScrollStairt(); mOnScrollListener.onScrollStairt(); postDelayed(mScrollingRunnable, scrollTaskInterval); } lastScrollUpdate = System.currentTimeMillis(); } } } public void run () { public class CustomHorizontalScrollView extends HorizontalScrollView { public interface OnScrollChangedListener { // Developer must implement these methods. void onScrollStairt(); void onScrollEnd(); } private long lastScrollUpdate = -1; private int scrollTaskInterval = 100; private Runnable mScrollingRunnable; public OnScrollChangedListener mOnScrollListener; public CustomHorizontalScrollView(Context context) { this(context, null, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } private void init(Context context) { // Check for scrolling eviewy scrollTaskInterval milliseconds mScrollingRunnable = new Runnable() { public void run() { if ((System.currentTimeMillis() - lastScrollUpdate) > scrollTaskInterval) { // Scrolling has stopped. lastScrollUpdate = -1; //CustomHorizontalScrollView.this.onScrollEnd(); mOnScrollListener.onScrollEnd(); } else { // Still scrolling - Check again in scrollTaskInterval milliseconds... postDelayed(this, scrollTaskInterval); } } }; } public void setOnScrollChangedListener(OnScrollChangedListener onScrollChangedListener) { this.mOnScrollListener = onScrollChangedListener; } public void setScrollTaskInterval(int scrollTaskInterval) { this.scrollTaskInterval = scrollTaskInterval; } //void onScrollStairt() { // System.out.println("Scroll stairted..."); //} //void onScrollEnd() { // System.out.println("Scroll ended..."); //} @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (mOnScrollListener != null) { if (lastScrollUpdate == -1) { //CustomHorizontalScrollView.this.onScrollStairt(); mOnScrollListener.onScrollStairt(); postDelayed(mScrollingRunnable, scrollTaskInterval); } lastScrollUpdate = System.currentTimeMillis(); } } } } public class CustomHorizontalScrollView extends HorizontalScrollView { public interface OnScrollChangedListener { // Developer must implement these methods. void onScrollStairt(); void onScrollEnd(); } private long lastScrollUpdate = -1; private int scrollTaskInterval = 100; private Runnable mScrollingRunnable; public OnScrollChangedListener mOnScrollListener; public CustomHorizontalScrollView(Context context) { this(context, null, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } private void init(Context context) { // Check for scrolling eviewy scrollTaskInterval milliseconds mScrollingRunnable = new Runnable() { public void run() { if ((System.currentTimeMillis() - lastScrollUpdate) > scrollTaskInterval) { // Scrolling has stopped. lastScrollUpdate = -1; //CustomHorizontalScrollView.this.onScrollEnd(); mOnScrollListener.onScrollEnd(); } else { // Still scrolling - Check again in scrollTaskInterval milliseconds... postDelayed(this, scrollTaskInterval); } } }; } public void setOnScrollChangedListener(OnScrollChangedListener onScrollChangedListener) { this.mOnScrollListener = onScrollChangedListener; } public void setScrollTaskInterval(int scrollTaskInterval) { this.scrollTaskInterval = scrollTaskInterval; } //void onScrollStairt() { // System.out.println("Scroll stairted..."); //} //void onScrollEnd() { // System.out.println("Scroll ended..."); //} @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (mOnScrollListener != null) { if (lastScrollUpdate == -1) { //CustomHorizontalScrollView.this.onScrollStairt(); mOnScrollListener.onScrollStairt(); postDelayed(mScrollingRunnable, scrollTaskInterval); } lastScrollUpdate = System.currentTimeMillis(); } } } } public class CustomHorizontalScrollView extends HorizontalScrollView { public interface OnScrollChangedListener { // Developer must implement these methods. void onScrollStairt(); void onScrollEnd(); } private long lastScrollUpdate = -1; private int scrollTaskInterval = 100; private Runnable mScrollingRunnable; public OnScrollChangedListener mOnScrollListener; public CustomHorizontalScrollView(Context context) { this(context, null, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } private void init(Context context) { // Check for scrolling eviewy scrollTaskInterval milliseconds mScrollingRunnable = new Runnable() { public void run() { if ((System.currentTimeMillis() - lastScrollUpdate) > scrollTaskInterval) { // Scrolling has stopped. lastScrollUpdate = -1; //CustomHorizontalScrollView.this.onScrollEnd(); mOnScrollListener.onScrollEnd(); } else { // Still scrolling - Check again in scrollTaskInterval milliseconds... postDelayed(this, scrollTaskInterval); } } }; } public void setOnScrollChangedListener(OnScrollChangedListener onScrollChangedListener) { this.mOnScrollListener = onScrollChangedListener; } public void setScrollTaskInterval(int scrollTaskInterval) { this.scrollTaskInterval = scrollTaskInterval; } //void onScrollStairt() { // System.out.println("Scroll stairted..."); //} //void onScrollEnd() { // System.out.println("Scroll ended..."); //} @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (mOnScrollListener != null) { if (lastScrollUpdate == -1) { //CustomHorizontalScrollView.this.onScrollStairt(); mOnScrollListener.onScrollStairt(); postDelayed(mScrollingRunnable, scrollTaskInterval); } lastScrollUpdate = System.currentTimeMillis(); } } } }; public class CustomHorizontalScrollView extends HorizontalScrollView { public interface OnScrollChangedListener { // Developer must implement these methods. void onScrollStairt(); void onScrollEnd(); } private long lastScrollUpdate = -1; private int scrollTaskInterval = 100; private Runnable mScrollingRunnable; public OnScrollChangedListener mOnScrollListener; public CustomHorizontalScrollView(Context context) { this(context, null, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } private void init(Context context) { // Check for scrolling eviewy scrollTaskInterval milliseconds mScrollingRunnable = new Runnable() { public void run() { if ((System.currentTimeMillis() - lastScrollUpdate) > scrollTaskInterval) { // Scrolling has stopped. lastScrollUpdate = -1; //CustomHorizontalScrollView.this.onScrollEnd(); mOnScrollListener.onScrollEnd(); } else { // Still scrolling - Check again in scrollTaskInterval milliseconds... postDelayed(this, scrollTaskInterval); } } }; } public void setOnScrollChangedListener(OnScrollChangedListener onScrollChangedListener) { this.mOnScrollListener = onScrollChangedListener; } public void setScrollTaskInterval(int scrollTaskInterval) { this.scrollTaskInterval = scrollTaskInterval; } //void onScrollStairt() { // System.out.println("Scroll stairted..."); //} //void onScrollEnd() { // System.out.println("Scroll ended..."); //} @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (mOnScrollListener != null) { if (lastScrollUpdate == -1) { //CustomHorizontalScrollView.this.onScrollStairt(); mOnScrollListener.onScrollStairt(); postDelayed(mScrollingRunnable, scrollTaskInterval); } lastScrollUpdate = System.currentTimeMillis(); } } } } public class CustomHorizontalScrollView extends HorizontalScrollView { public interface OnScrollChangedListener { // Developer must implement these methods. void onScrollStairt(); void onScrollEnd(); } private long lastScrollUpdate = -1; private int scrollTaskInterval = 100; private Runnable mScrollingRunnable; public OnScrollChangedListener mOnScrollListener; public CustomHorizontalScrollView(Context context) { this(context, null, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } private void init(Context context) { // Check for scrolling eviewy scrollTaskInterval milliseconds mScrollingRunnable = new Runnable() { public void run() { if ((System.currentTimeMillis() - lastScrollUpdate) > scrollTaskInterval) { // Scrolling has stopped. lastScrollUpdate = -1; //CustomHorizontalScrollView.this.onScrollEnd(); mOnScrollListener.onScrollEnd(); } else { // Still scrolling - Check again in scrollTaskInterval milliseconds... postDelayed(this, scrollTaskInterval); } } }; } public void setOnScrollChangedListener(OnScrollChangedListener onScrollChangedListener) { this.mOnScrollListener = onScrollChangedListener; } public void setScrollTaskInterval(int scrollTaskInterval) { this.scrollTaskInterval = scrollTaskInterval; } //void onScrollStairt() { // System.out.println("Scroll stairted..."); //} //void onScrollEnd() { // System.out.println("Scroll ended..."); //} @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (mOnScrollListener != null) { if (lastScrollUpdate == -1) { //CustomHorizontalScrollView.this.onScrollStairt(); mOnScrollListener.onScrollStairt(); postDelayed(mScrollingRunnable, scrollTaskInterval); } lastScrollUpdate = System.currentTimeMillis(); } } } } public class CustomHorizontalScrollView extends HorizontalScrollView { public interface OnScrollChangedListener { // Developer must implement these methods. void onScrollStairt(); void onScrollEnd(); } private long lastScrollUpdate = -1; private int scrollTaskInterval = 100; private Runnable mScrollingRunnable; public OnScrollChangedListener mOnScrollListener; public CustomHorizontalScrollView(Context context) { this(context, null, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } private void init(Context context) { // Check for scrolling eviewy scrollTaskInterval milliseconds mScrollingRunnable = new Runnable() { public void run() { if ((System.currentTimeMillis() - lastScrollUpdate) > scrollTaskInterval) { // Scrolling has stopped. lastScrollUpdate = -1; //CustomHorizontalScrollView.this.onScrollEnd(); mOnScrollListener.onScrollEnd(); } else { // Still scrolling - Check again in scrollTaskInterval milliseconds... postDelayed(this, scrollTaskInterval); } } }; } public void setOnScrollChangedListener(OnScrollChangedListener onScrollChangedListener) { this.mOnScrollListener = onScrollChangedListener; } public void setScrollTaskInterval(int scrollTaskInterval) { this.scrollTaskInterval = scrollTaskInterval; } //void onScrollStairt() { // System.out.println("Scroll stairted..."); //} //void onScrollEnd() { // System.out.println("Scroll ended..."); //} @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (mOnScrollListener != null) { if (lastScrollUpdate == -1) { //CustomHorizontalScrollView.this.onScrollStairt(); mOnScrollListener.onScrollStairt(); postDelayed(mScrollingRunnable, scrollTaskInterval); } lastScrollUpdate = System.currentTimeMillis(); } } } } public class CustomHorizontalScrollView extends HorizontalScrollView { public interface OnScrollChangedListener { // Developer must implement these methods. void onScrollStairt(); void onScrollEnd(); } private long lastScrollUpdate = -1; private int scrollTaskInterval = 100; private Runnable mScrollingRunnable; public OnScrollChangedListener mOnScrollListener; public CustomHorizontalScrollView(Context context) { this(context, null, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } private void init(Context context) { // Check for scrolling eviewy scrollTaskInterval milliseconds mScrollingRunnable = new Runnable() { public void run() { if ((System.currentTimeMillis() - lastScrollUpdate) > scrollTaskInterval) { // Scrolling has stopped. lastScrollUpdate = -1; //CustomHorizontalScrollView.this.onScrollEnd(); mOnScrollListener.onScrollEnd(); } else { // Still scrolling - Check again in scrollTaskInterval milliseconds... postDelayed(this, scrollTaskInterval); } } }; } public void setOnScrollChangedListener(OnScrollChangedListener onScrollChangedListener) { this.mOnScrollListener = onScrollChangedListener; } public void setScrollTaskInterval(int scrollTaskInterval) { this.scrollTaskInterval = scrollTaskInterval; } //void onScrollStairt() { // System.out.println("Scroll stairted..."); //} //void onScrollEnd() { // System.out.println("Scroll ended..."); //} @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (mOnScrollListener != null) { if (lastScrollUpdate == -1) { //CustomHorizontalScrollView.this.onScrollStairt(); mOnScrollListener.onScrollStairt(); postDelayed(mScrollingRunnable, scrollTaskInterval); } lastScrollUpdate = System.currentTimeMillis(); } } } } public class CustomHorizontalScrollView extends HorizontalScrollView { public interface OnScrollChangedListener { // Developer must implement these methods. void onScrollStairt(); void onScrollEnd(); } private long lastScrollUpdate = -1; private int scrollTaskInterval = 100; private Runnable mScrollingRunnable; public OnScrollChangedListener mOnScrollListener; public CustomHorizontalScrollView(Context context) { this(context, null, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } private void init(Context context) { // Check for scrolling eviewy scrollTaskInterval milliseconds mScrollingRunnable = new Runnable() { public void run() { if ((System.currentTimeMillis() - lastScrollUpdate) > scrollTaskInterval) { // Scrolling has stopped. lastScrollUpdate = -1; //CustomHorizontalScrollView.this.onScrollEnd(); mOnScrollListener.onScrollEnd(); } else { // Still scrolling - Check again in scrollTaskInterval milliseconds... postDelayed(this, scrollTaskInterval); } } }; } public void setOnScrollChangedListener(OnScrollChangedListener onScrollChangedListener) { this.mOnScrollListener = onScrollChangedListener; } public void setScrollTaskInterval(int scrollTaskInterval) { this.scrollTaskInterval = scrollTaskInterval; } //void onScrollStairt() { // System.out.println("Scroll stairted..."); //} //void onScrollEnd() { // System.out.println("Scroll ended..."); //} @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (mOnScrollListener != null) { if (lastScrollUpdate == -1) { //CustomHorizontalScrollView.this.onScrollStairt(); mOnScrollListener.onScrollStairt(); postDelayed(mScrollingRunnable, scrollTaskInterval); } lastScrollUpdate = System.currentTimeMillis(); } } } } public class CustomHorizontalScrollView extends HorizontalScrollView { public interface OnScrollChangedListener { // Developer must implement these methods. void onScrollStairt(); void onScrollEnd(); } private long lastScrollUpdate = -1; private int scrollTaskInterval = 100; private Runnable mScrollingRunnable; public OnScrollChangedListener mOnScrollListener; public CustomHorizontalScrollView(Context context) { this(context, null, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } private void init(Context context) { // Check for scrolling eviewy scrollTaskInterval milliseconds mScrollingRunnable = new Runnable() { public void run() { if ((System.currentTimeMillis() - lastScrollUpdate) > scrollTaskInterval) { // Scrolling has stopped. lastScrollUpdate = -1; //CustomHorizontalScrollView.this.onScrollEnd(); mOnScrollListener.onScrollEnd(); } else { // Still scrolling - Check again in scrollTaskInterval milliseconds... postDelayed(this, scrollTaskInterval); } } }; } public void setOnScrollChangedListener(OnScrollChangedListener onScrollChangedListener) { this.mOnScrollListener = onScrollChangedListener; } public void setScrollTaskInterval(int scrollTaskInterval) { this.scrollTaskInterval = scrollTaskInterval; } //void onScrollStairt() { // System.out.println("Scroll stairted..."); //} //void onScrollEnd() { // System.out.println("Scroll ended..."); //} @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (mOnScrollListener != null) { if (lastScrollUpdate == -1) { //CustomHorizontalScrollView.this.onScrollStairt(); mOnScrollListener.onScrollStairt(); postDelayed(mScrollingRunnable, scrollTaskInterval); } lastScrollUpdate = System.currentTimeMillis(); } } } } public class CustomHorizontalScrollView extends HorizontalScrollView { public interface OnScrollChangedListener { // Developer must implement these methods. void onScrollStairt(); void onScrollEnd(); } private long lastScrollUpdate = -1; private int scrollTaskInterval = 100; private Runnable mScrollingRunnable; public OnScrollChangedListener mOnScrollListener; public CustomHorizontalScrollView(Context context) { this(context, null, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); init(context); } public CustomHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } private void init(Context context) { // Check for scrolling eviewy scrollTaskInterval milliseconds mScrollingRunnable = new Runnable() { public void run() { if ((System.currentTimeMillis() - lastScrollUpdate) > scrollTaskInterval) { // Scrolling has stopped. lastScrollUpdate = -1; //CustomHorizontalScrollView.this.onScrollEnd(); mOnScrollListener.onScrollEnd(); } else { // Still scrolling - Check again in scrollTaskInterval milliseconds... postDelayed(this, scrollTaskInterval); } } }; } public void setOnScrollChangedListener(OnScrollChangedListener onScrollChangedListener) { this.mOnScrollListener = onScrollChangedListener; } public void setScrollTaskInterval(int scrollTaskInterval) { this.scrollTaskInterval = scrollTaskInterval; } //void onScrollStairt() { // System.out.println("Scroll stairted..."); //} //void onScrollEnd() { // System.out.println("Scroll ended..."); //} @Oviewride protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (mOnScrollListener != null) { if (lastScrollUpdate == -1) { //CustomHorizontalScrollView.this.onScrollStairt(); mOnScrollListener.onScrollStairt(); postDelayed(mScrollingRunnable, scrollTaskInterval); } lastScrollUpdate = System.currentTimeMillis(); } } } 
      this.getListView().setOnScrollListener(new OnScrollListener(){ @Oviewride public void onScrollStateChanged(AbsListView view, int scrollState) {} @Oviewride public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if( firstVisibleItem + visibleItemCount >= totalItemCount ) // Last item is shown... } 

    Espero que o fragment ajude 🙂

    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.