with studio recyclerview down activity android android-layout android-fragments uiswipegesturerecognizer swiperefreshlayout

android - studio - swiperefreshlayout kotlin



SwiperefreshLayout en Android (7)

Estoy usando SwipeRefreshLayout en mi diseño a continuación:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@color/homePageBackground" android:orientation="vertical" > <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/swipeRefreshLayout_listView" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <fragment android:id="@+id/announcementHomefragment" android:name="in.test.app.AnnouncementFragment" android:layout_width="match_parent" android:layout_height="wrap_content" /> <ScrollView android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/homePageBackground" > <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="15dp" android:background="@color/homePageBackground" > <TextView android:id="@+id/newsTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginLeft="15dp" android:layout_marginTop="5dp" android:gravity="center" android:text="@string/new_list" android:textAppearance="?android:attr/textAppearanceSmall" android:textColor="@color/white" android:textStyle="bold" /> <fragment android:id="@+id/newshomefragment" android:name="in.test.app.NewsFragment" android:layout_width="wrap_content" android:layout_height="190dp" android:layout_below="@id/newsTitle" android:layout_marginTop="-15dp" /> <TextView android:id="@+id/productTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/newshomefragment" android:layout_gravity="center" android:layout_marginLeft="15dp" android:layout_marginTop="5dp" android:gravity="center" android:text="@string/product_in_home" android:textAppearance="?android:attr/textAppearanceSmall" android:textColor="@color/white" android:textStyle="bold" /> <fragment android:id="@+id/proCategoryhomefragment" android:name="in.test.app.CategoryFragment" android:layout_width="wrap_content" android:layout_height="170dp" android:layout_below="@id/productTitle" android:layout_marginTop="-15dp" /> <TextView android:id="@+id/trainingTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/proCategoryhomefragment" android:layout_gravity="center" android:layout_marginLeft="15dp" android:layout_marginTop="2dp" android:gravity="center" android:text="@string/trainings_in_home" android:textAppearance="?android:attr/textAppearanceSmall" android:textColor="@color/white" android:textStyle="bold" /> <fragment android:id="@+id/trainingfragment" android:name="in.test.app.TrainingFragment" android:layout_width="match_parent" android:layout_height="180dp" android:layout_below="@id/trainingTitle" android:layout_marginBottom="10dp" android:layout_marginTop="-15dp" /> </RelativeLayout> </ScrollView> </LinearLayout> </android.support.v4.widget.SwipeRefreshLayout>

Cuando SwipeRefreshLayout mi SwipeRefreshLayout está funcionando, pero como puede ver en el código anterior, tengo una vista de desplazamiento dentro de eso. Entonces, cuando estoy bajando mi vista de desplazamiento, se reduce y la mitad de las imágenes no se muestran porque se redujo. Cuando estoy intentando volver a subir, mi vista de desplazamiento no está subiendo. En cambio, SwipeRefreshLayout está recibiendo la llamada. ¿Qué tengo que hacer?

Por favor, ayúdame.


Como ya han dicho otros, si no tiene su vista desplazable (es decir, vista de lista) como hijo directo de SwipeRefreshLayout, el stock canChildScrollUp no funcionará.

Tiene que ver con la lógica simple que SwipeRefreshLayout usa para verificar la capacidad de la vista secundaria para desplazarse.

Estaba usando un ListView dentro de una ActionbarActivity, y quería incluir una vista vacía cada vez que mi vista de lista estaba vacía. Esto causó problemas, ya que la clase SwipeRefreshLayout solo puede tener un único hijo. Tenga en cuenta que también comprueba la capacidad de este niño para desplazarse hacia arriba para determinar si un menú desplegable hace que el niño se desplace hacia arriba, o si hace que el contenido del niño se actualice.

Entonces, si desea usar la misma lógica que SwipeRefreshLayout, simplemente extienda la clase y cree un método que le permita pasar el identificador a su vista desplazable. Tenga en cuenta que la implementación de stock utiliza canScrollVertically () que hace exactamente lo que queremos, pero solo aparece en SDK> = 14.

Además, no olvide incluir el constructor que contiene el parámetro "AttributeSet", cuando extienda la clase, de lo contrario tendrá problemas para usar la clase en sus archivos de diseño.

Por lo tanto, en el método onCreate de su Actividad (en mi caso, fue una ActionBarActivity) que incluye la vista de lista, simplemente llame a setMyScrollableView pasando su ListView o la vista que use que se desplaza.

/*Constructor*/ public MySwipeRefreshLayout(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } View mMyScrollableView = null; //The content that get''s pulled down. /*Method used to pass in my scrollable view*/ public void setMyScrollableView(View view){ mMyScrollableView = view; } /** * @return Whether it is possible for the child view of this layout to * scroll up. This was taken for the most part directly from SwipeRefreshLayout */ public boolean canChildScrollUp() { if(mMyScrollableView == null) return false; if (android.os.Build.VERSION.SDK_INT < 14) { if (mMyScrollableView instanceof AbsListView) { final AbsListView absListView = (AbsListView) mMyScrollableView; return absListView.getChildCount() > 0 && (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0) .getTop() < absListView.getPaddingTop()); } else { return mMyScrollableView.getScrollY() > 0; } } else { return ViewCompat.canScrollVertically(mMyScrollableView, -1); } }


Diría que es mejor tener un SwipeRefreshLayout extendido con oyente para poder agregar varias condiciones de las clases que muestran este diseño.

Algo como lo siguiente: GeneralSwipeRefreshLayout.java

public class GeneralSwipeRefreshLayout extends SwipeRefreshLayout { private OnChildScrollUpListener mScrollListenerNeeded; public interface OnChildScrollUpListener { boolean canChildScrollUp(); } public GeneralSwipeRefreshLayout(Context context) { super(context); } public GeneralSwipeRefreshLayout(Context context, AttributeSet attrs) { super(context, attrs); } /** * Listener that controls if scrolling up is allowed to child views or not */ public void setOnChildScrollUpListener(OnChildScrollUpListener listener) { mScrollListenerNeeded = listener; } @Override public boolean canChildScrollUp() { if (mScrollListenerNeeded == null) { Log.e(GeneralSwipeRefreshLayout.class.getSimpleName(), "listener is not defined!"); } return mScrollListenerNeeded != null && mScrollListenerNeeded.canChildScrollUp(); } }

Y luego dentro de tu clase que muestra SwipeRefreshLayout que contiene el diseño de ListView o GridView, puedes hacer algo como esto:

mSwipeLayout.setOnChildScrollUpListener(new OnChildScrollUpListener() { @Override public boolean canChildScrollUp() { return mListView.getFirstVisiblePosition() > 0 || mListView.getChildAt(0) == null || mListView.getChildAt(0).getTop() < 0; } });


La solución de @ User22791 funciona perfectamente y, en base a eso, creé una biblioteca disponible en github que puede usar (y modificar) para facilitar el uso de swipeRefreshLayout para los desarrolladores. Está aquí: https://github.com/dagova/referencedSwipeRefreshLayout

Básicamente, solo tiene que hacer referencia en su diseño a la vista que debe verificarse en el método canChildScrollUp. Espero que sea de utilidad.


Ok lo tengo funcionando Si SwipeRefreshLayout es la raíz del diseño y ScrollView reside en lo más profundo de la jerarquía (había colocado ScrollView dentro de RelativeLayout ) y no es el elemento directo de SwipeRefreshLayout , no detectará un golpe en ScrollView correctamente.

Debe crear una clase personalizada que extienda SwipeRefreshLayout y anule el método canChildScrollUp() en SwipRefreshLayout

Aquí hay un ejemplo:

public class CustomSwipeRefreshLayout extends SwipeRefreshLayout { private ScrollView scrollview; public CustomSwipeRefreshLayout(Context context) { super(context); } public CustomSwipeRefreshLayout(Context context, AttributeSet attrs) { super(context, attrs); } public void setView(ScrollView view) { this.scrollview = view; } @Override public boolean canChildScrollUp() { return scrollview.getScrollY() != 0; } }


Simplemente cree una clase que extienda SwipeRefreshLayout y anule el método canChildScrollUp() . Devuelve verdadero cuando quieras desplazarte hacia abajo para tu control.

Por ejemplo, para scrollview puedes probar esto,

@override. boolean canChildScrollUp() { //your condition to check scrollview reached at top while scrolling if(scrollview.getScrollY() == 0.0) return true; else return false; }


También encontré que las otras respuestas no funcionaron del todo.

Tardé un rato en getScrollY() cabeza para descubrir que están usando el método getScrollY() que, como se explica en esta respuesta , es un método de View que describe qué tan lejos ha estado el desplazamiento dentro de un contenedor, no un método para describir cuánto tiene su contenedor Scroll. ha sido desplazado.

Si usa la misma técnica que en las otras respuestas (anulando el método canChildScrollUp() ), puede verificar fácilmente si el Control de desplazamiento está en su punto más alto:

@Override public boolean canChildScrollUp() { return !isListAtTop(); } private boolean isListAtTop() { if(mGridView.getChildCount() == 0) return true; return mGridView.getChildAt(0).getTop() == 0; }

(Como puede ver, estoy usando un GridView , pero también puede usar un ListView )


Una solución más sencilla es usar onScrollListener y verificar si el usuario puede ver firstElement.

someView.setOnScrollListener(new AbsListView.OnScrollListener() { @Override public void onScrollStateChanged(AbsListView absListView, int scrollState) { if (scrollState == SCROLL_STATE_IDLE) { if (isViewAtTop()) { swipeLayout.setEnabled(true); } else { swipeLayout.setEnabled(false); } } } @Override public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (firstVisibleItem == 0) { swipeLayout.setEnabled(true); } else { swipeLayout.setEnabled(false); } } });

Donde el método isViewAtTop () es otro método, el control de esta Vista se desplaza hacia arriba