2011-09-06 11 views

Respuesta

36

edición

Ver comentarios a continuación por qué, sobre todo en las diferentes versiones de la API (ESP posteriores unos), esto no es un método infalible para ver si la lista es que estás en la parte superior (relleno, etc.) Sin embargo, la máquina le dará un comienzo de una solución en dispositivos continuación API 14:

private boolean listIsAtTop() { 
    if(listView.getChildCount() == 0) return true; 
    return listView.getChildAt(0).getTop() == 0; 
} 

En lo que a mis años de aplicación hace - esto funcionó a la perfección en el momento.

+0

nice ... clean and simple – Houston

+5

Esto no siempre devuelve 0 cuando está en la parte superior de una lista para mí – JackMahoney

+0

(Puede agregar ... getTop()> 0 || ... getTop() Graeme

1

Puede notificar que la posición 0 ahora está visible OnScrollListener. Use el método onScroll.

+5

mi elemento de la lista es muy grande, así que no puedo comparar para ver si firstVisibleItem es 0, ya que el elemento cubre la mitad de la pantalla. Si el artículo es solo la mitad visible (en la parte superior). entonces también firstVisibleItem es 0, que no es la parte superior de listView. – ShineDown

+3

El asker quiere saber sobre el punto más alto no cuando se alcanza el elemento superior. Esto todavía se disparará si en el primer elemento pero no en el punto más alto – wi1

-1
lstView.setOnScrollListener(new AbsListView.OnScrollListener() { 

      @Override 
      public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { 
       //To change body of implemented methods use File | Settings | File Templates. 
       if (0 == firstVisibleItem){ 
        Toast.makeText(MyActivity.this, "Scroll to Top ", Toast.LENGTH_SHORT).show(); 
       } 
      } 
     }); 
+5

El asker quiere saber sobre el punto más alto no cuando se alcanza el elemento superior. Esto todavía se disparará si está en el primer elemento pero no en el punto más alto. – wi1

2

Usted tendrá que comprobar cuál es la primera posición visible después de aplicar la solución de Graeme para ver si el primer elemento listview es visible en la posición superior.

Algo así como lv.getFirstVisiblePosition() == 0 & & (lv.getChildCount() == 0 || lv.getChildAt (0) .getTop() == 0)

21

Sé que esta pregunta es viejo, pero aparece arriba en los resultados de búsqueda de Google. Hay un nuevo método introducido en el nivel de la API 14, que da exactamente lo que necesitábamos:

http://developer.android.com/reference/android/view/View.html#canScrollVertically%28int%29

Para las plataformas de mayor edad uno puede utilizar métodos estáticos similares de ViewCompat en la biblioteca de soporte v4. Consulte la edición a continuación.

A diferencia del método de Graeme, este método es inmune a los problemas causados ​​por la reutilización de la vista interna de ListView y/o el desplazamiento del encabezado.

Editar: solución final

he encontrado un método en el código fuente de SwipeRefreshLayout que se encarga de esto. Se puede reescribir como:

public boolean canScrollUp(View view) { 
    if (android.os.Build.VERSION.SDK_INT < 14) { 
    if (view instanceof AbsListView) { 
     final AbsListView absListView = (AbsListView) view; 
     return absListView.getChildCount() > 0 
      && (absListView.getFirstVisiblePosition() > 0 || absListView 
       .getChildAt(0).getTop() < absListView.getPaddingTop()); 
    } else { 
     return view.getScrollY() > 0; 
    } 
    } else { 
    return ViewCompat.canScrollVertically(view, -1); 
    } 
} 

Es posible que deba agregar lógica personalizada si el pasado-en vista es una vista personalizada.

+1

Tenga en cuenta que los métodos de ViewCompat para canScrollVertically y canScrollHorizontally siempre devuelven falso en los niveles de plataforma debajo de ICS. La implementación establece los métodos que devuelven falso a menos que se anule y solo la impl para ICS anula los métodos. – lillicoder

+0

@lillicoder Tienes razón. No podemos usar las implementaciones en plataformas más antiguas. He editado la respuesta para que funcione en todas las plataformas. – topduo

0

La respuesta de Graeme está cerca pero falta algo que user2036198 agregó, un cheque para getFirstVisiblePosition(). getChildAt (0) no devuelve la primera vista para el primer elemento de la lista. Las implementaciones de AbsListView no hacen una sola vista para cada posición y las mantienen todas en la memoria. En cambio, el reciclaje de vistas tiene efecto para limitar el número de vistas instanciadas en cualquier momento.

la solución es bastante simple:

public boolean canScrollVertically(AbsListView view) { 
    boolean canScroll = false; 

    if (view != null && view.getChildCount() > 0) { 
     // First item can be partially visible, top must be 0 for the item 
     canScroll = view.getFirstVisiblePosition() != 0 || view.getChildAt(0).getTop() != 0; 
    } 

    return canScroll; 
} 

Para obtener los mejores resultados en el ICS o superior, utilice siempre ViewCompat de la biblioteca de soporte v4 o View.canScrollVertically(). Utilice el método anterior en niveles de API más bajos ya que ViewCompat siempre devuelve false para canScrollVertically() y canScrollHorizontally() debajo de ICS.

0

Si puede extender ListView directamente, puede usar el método protegido llamado "computeVerticalScrollOffset()" dentro del método de sustitución "onScrollChanged()".

Con ese método protegido devuelve 0, significa que su ListView ahora se alcanza en la parte superior.

Fragmento de código

 listView = new ListView(this){ 
     @Override 
     protected void onScrollChanged(int l, int t, int oldl, int oldt) { 
      super.onScrollChanged(l, t, oldl, oldt); 

      if(computeVerticalScrollOffset() == 0){ 
       // Reach top 
      } 
     } 
1

Esta pregunta es viejo, pero tengo una solución que funciona a la perfección y es posible que funcione para alguien que busca una solución.

int limitRowsBDshow = 10; //size limit your list 
listViewMessages.setOnScrollListener(new AbsListView.OnScrollListener() { 
     int counter = 1; 
     int currentScrollState; 
     int currentFirstVisibleItem; 
     int currentVisibleItemCount; 
     int currentTotalItemCount; 


     @Override 
     public void onScrollStateChanged(AbsListView view, int scrollState) { 
      this.currentScrollState = scrollState; 
      this.isScrollCompleted(); 
     } 

     @Override 
     public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { 

      this.currentFirstVisibleItem = firstVisibleItem; 
      this.currentVisibleItemCount = visibleItemCount; 
      this.currentTotalItemCount = totalItemCount; 
     } 

     private void isScrollCompleted() { 
      if (this.currentVisibleItemCount > 0 && this.currentScrollState == SCROLL_STATE_IDLE) { 
       /*** detect if there's been a scroll which has completed ***/ 

       counter++; 
       if (currentFirstVisibleItem == 0 && currentTotalItemCount > limitRowsBDshow - 1) { 
        linearLay20msgMas.setVisibility(View.VISIBLE); 
       } 
      } 
     } 
    }); 

Este código se encuentra hace un tiempo (aquí StackOverflow). Pero no puedo encontrar este mencionar

11

Mis amigos, combinando respuesta Graeme 's con el método OnScroll ...

listView.setOnScrollListener(new AbsListView.OnScrollListener() { 
    @Override 
    public void onScrollStateChanged(AbsListView view, int scrollState) { 

    } 

    @Override 
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { 
     if(firstVisibleItem == 0 && listIsAtTop()){ 
      swipeRefreshLayout.setEnabled(true); 
     }else{ 
      swipeRefreshLayout.setEnabled(false); 
     } 
    } 
}); 


private boolean listIsAtTop() { 
    if(listView.getChildCount() == 0) return true; 
    return listView.getChildAt(0).getTop() == 0; 
} 
+0

thumbs up por mencionar swipeRefreshLayout. específicamente lo que necesitaba. – ralphgabb

Cuestiones relacionadas