android - programacion - Detectando la dirección de desplazamiento en el adaptador(arriba/abajo)
programacion android pdf 2018 (9)
Asigne un OnScrollListener
a su ListView
. Cree una bandera que indique si el usuario se está desplazando hacia arriba o hacia abajo. Establezca un valor apropiado para la bandera comprobando si la posición actual del primer elemento visible es más o menos que la posición anterior del primer elemento visible. Ponga ese cheque dentro de onScrollStateChanged()
.
Código de muestra:
private int mLastFirstVisibleItem;
private boolean mIsScrollingUp;
public void onScrollStateChanged(AbsListView view, int scrollState) {
final ListView lw = getListView();
if (view.getId() == lw.getId()) {
final int currentFirstVisibleItem = lw.getFirstVisiblePosition();
if (currentFirstVisibleItem > mLastFirstVisibleItem) {
mIsScrollingUp = false;
} else if (currentFirstVisibleItem < mLastFirstVisibleItem) {
mIsScrollingUp = true;
}
mLastFirstVisibleItem = currentFirstVisibleItem;
}
}
Verifique si mIsScrollingUp
es verdadero o falso en getView()
, y asigne las animaciones en consecuencia.
Estoy intentando imitar la aplicación Google Plus en mi proyecto, ya que parece ser la referencia ahora.
El efecto de vista de lista cuando se desplaza es realmente agradable y me gustaría hacer algo similar.
Comencé con el controlador de diseño de página http://android-er.blogspot.be/2009/10/listview-and-listactivity-layout.html
LayoutAnimationController controller
= AnimationUtils.loadLayoutAnimation(
this, R.anim.list_layout_controller);
getListView().setLayoutAnimation(controller);
y eso parece malo, ya que no todos los elementos están animados:
Así que terminé usando el getView del adaptador y usando esto:
AnimationSet set = new AnimationSet(true);
Animation animation = new AlphaAnimation(0.0f, 1.0f);
animation.setDuration(800);
set.addAnimation(animation);
animation = new TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0.0f,Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 1.0f,Animation.RELATIVE_TO_SELF, 0.0f
);
animation.setDuration(600);
set.addAnimation(animation);
row.startAnimation(set);
¡El resultado es impresionante y estoy muy feliz con él!
Desafortunadamente, ¡solo funciona cuando me desplazo de arriba a abajo de la lista!
Quiero hacer que funcione cuando me desplazo por el otro lado, necesito cambiar un poco la traducción de la animación.
Entonces, mi pregunta, ¿hay una manera de detectar si me desplazo hacia arriba o hacia abajo en mi adaptador?
Este es mi enfoque: le proporciona una respuesta más inmediata sobre cuánto ha desplazado: OnScroll
, puede obtener la posición superior del primer elemento de su lista. Es bastante confiable obtener información de posición de desplazamiento real inmediatamente.
listView.getChildAt(0).getTop()
He usado esta solución mucho más simple:
public class ScrollDetectingListView extends ListView
...
setOnScrollListener( new OnScrollListener()
{
private int mInitialScroll = 0;
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount)
{
int scrolledOffset = computeVerticalScrollOffset();
boolean scrollUp = scrolledOffset > mInitialScroll;
mInitialScroll = scrolledOffset;
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
}
La respuesta aceptada realmente no "detecta" el desplazamiento hacia arriba o hacia abajo. No funcionará si el elemento visible actual es realmente enorme. Usar onTouchListener
es el camino a seguir.
Este es el fragmento de código que utilicé:
listView.setOnTouchListener(new View.OnTouchListener() {
float initialY, finalY;
boolean isScrollingUp;
@Override
public boolean onTouch(View v, MotionEvent event) {
int action = MotionEventCompat.getActionMasked(event);
switch(action) {
case (MotionEvent.ACTION_DOWN):
initialY = event.getY();
case (MotionEvent.ACTION_UP):
finalY = event.getY();
if (initialY < finalY) {
Log.d(TAG, "Scrolling up");
isScrollingUp = true;
} else if (initialY > finalY) {
Log.d(TAG, "Scrolling down");
isScrollingUp = false;
}
default:
}
if (isScrollingUp) {
// do animation for scrolling up
} else {
// do animation for scrolling down
}
return false; // has to be false, or it will freeze the listView
}
});
Prueba esto . Espero que te ayude . Lógica de @Gal Rom Answer.
lv.setOnScrollListener(new OnScrollListener() {
private int mLastFirstVisibleItem;
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if(mLastFirstVisibleItem<firstVisibleItem)
{
Log.i("SCROLLING DOWN","TRUE");
}
if(mLastFirstVisibleItem>firstVisibleItem)
{
Log.i("SCROLLING UP","TRUE");
}
mLastFirstVisibleItem=firstVisibleItem;
}
});
Solución general que no se basa en posiciones de vistas / etc. Simplemente verifique el desplazamiento de desplazamiento vertical y compárelo con el desplazamiento de desplazamiento anterior. Si el nuevo valor es mayor que el anterior, el usuario se está desplazando hacia abajo y viceversa.
// [START check vertical scroll direction]
int oldScrollOffset = 0;
listView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
@Override
public void onScrollChange(View view, int i, int i1, int i2, int i3) {
Boolean scrollDirectionDown;
int newScrollOffset = listView.computeVerticalScrollOffset();
if (newScrollOffset > oldScrollOffset) {
scrollDirectionDown = true;
} else {
scrollDirectionDown = false;
}
oldScrollOffset = newScrollOffset;
if (scrollDirectionDown) {
// Update accordingly for scrolling down
Log.d(TAG, "scrolling down");
} else {
// Update accordingly for scrolling up
Log.d(TAG, "scrolling up");
}
});
// [END check vertical scroll direction]
Solución más compleja (trabajar con elementos largos en la vista de lista)
Crear vista de lista personalizada
public class ScrollDetectingListView extends ListView { public ScrollDetectingListView(Context context) { super(context); } public ScrollDetectingListView(Context context, AttributeSet attrs) { super(context,attrs); } public ScrollDetectingListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } //we need this protected method for scroll detection public int getVerticalScrollOffset() { return computeVerticalScrollOffset(); } }
Anular OnScroll
listView.setOnScrollListener(new AbsListView.OnScrollListener() { private int mInitialScroll = 0; @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { int scrolledOffset = listView.getVerticalScrollOffset(); if (scrolledOffset!=mInitialScroll) { //if scroll position changed boolean scrollUp = (scrolledOffset - mInitialScroll) < 0; mInitialScroll = scrolledOffset; } } });
Terminé haciendo esto:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Log.i("",position+" - "+lastposition);
if (position >= lastposition)
animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF,
0.0f, Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 1.0f,
Animation.RELATIVE_TO_SELF, 0.0f);
else
animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF,
0.0f, Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, -1.0f,
Animation.RELATIVE_TO_SELF, 0.0f);
animation.setDuration(600);
set.addAnimation(animation);
row.startAnimation(set);
lastposition = position;
}
list.setOnScrollListener(new OnScrollListener() {
int last_item;
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if(last_item<firstVisibleItem+visibleItemCount-1){
System.out.println("List is scrolling upwards");
}
else if(last_item>firstVisibleItem+visibleItemCount-1){
System.out.println("List is scrolling downwards");
}
last_item = firstVisibleItem+visibleItemCount-1;
}
});
En función de la posición del último elemento visible, decido si la vista de lista está subiendo o bajando.