android - recyclerview - swiperefreshlayout kotlin
SwipeRefreshLayout setRefreshing() no muestra el indicador inicialmente (14)
Ver la respuesta de Volodymyr Baydalka en su lugar.
Estas son las viejas soluciones alternativas.
Eso solía funcionar en una versión anterior de
android.support.v4
, pero a partir de la versión 21.0.0 en curso no funciona y todavía existe con
android.support.v4:21.0.3
lanzado del
10
al
12 de diciembre de 2014
y esto es la razón.
El indicador SwipeRefreshLayout no aparece cuando se
setRefreshing(true)
antes de
SwipeRefreshLayout.onMeasure()
Solución alternativa:
llamando a
setProgressViewOffset()
en
SwipeRefreshLayout
que invalida la vista circular del diseño, lo que
SwipeRefreshLayout.onMeasure()
que se llame inmediatamente a
SwipeRefreshLayout.onMeasure()
.
mSwipeRefreshLayout.setProgressViewOffset(false, 0,
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24, getResources().getDisplayMetrics()));
mSwipeRefreshLayout.setRefreshing(true);
ACTUALIZAR Mejor solución
Debido a que la barra de acción podría adelgazarse cuando cambia la orientación o si ha establecido el tamaño de la barra de acción manualmente. Establecemos el desplazamiento en píxeles desde la parte superior de esta vista en la que la flecha de progreso debe restablecerse después de un gesto de deslizamiento exitoso al tamaño actual de la barra de acción.
TypedValue typed_value = new TypedValue();
getActivity().getTheme().resolveAttribute(android.support.v7.appcompat.R.attr.actionBarSize, typed_value, true);
mSwipeRefreshLayout.setProgressViewOffset(false, 0, getResources().getDimensionPixelSize(typed_value.resourceId));
ACTUALIZACIÓN Nov 20 2014
Si no es muy importante para su aplicación mostrar SwipeRefreshLayout una vez que se inicia la vista. Puede publicarlo en un momento en el futuro mediante el uso de controladores o cualquier cosa que desee.
como ejemplo.
handler.postDelayed(new Runnable() {
@Override
public void run() {
mSwipeRefreshLayout.setRefreshing(true);
}
}, 1000);
o como mencionó la respuesta de Volodymyr Baydalka.
Aquí está el issue en el rastreador de problemas de Android. Vota a favor para mostrarles que necesitamos que se solucione.
Tengo un diseño muy simple, pero cuando llamo a
setRefreshing(true)
en
onActivityCreated()
de mi fragmento, no se muestra inicialmente.
Solo se muestra cuando hago un pull para actualizar. ¿Alguna idea de por qué no aparece inicialmente?
Fragmento xml:
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipe_container"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</RelativeLayout>
</ScrollView>
</android.support.v4.widget.SwipeRefreshLayout>
Código de fragmento:
public static class LinkDetailsFragment extends BaseFragment implements SwipeRefreshLayout.OnRefreshListener {
@InjectView(R.id.swipe_container)
SwipeRefreshLayout mSwipeContainer;
public static LinkDetailsFragment newInstance(String subreddit, String linkId) {
Bundle args = new Bundle();
args.putString(EXTRA_SUBREDDIT, subreddit);
args.putString(EXTRA_LINK_ID, linkId);
LinkDetailsFragment fragment = new LinkDetailsFragment();
fragment.setArguments(args);
return fragment;
}
public LinkDetailsFragment() {
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mSwipeContainer.setOnRefreshListener(this);
mSwipeContainer.setColorScheme(android.R.color.holo_blue_bright,
android.R.color.holo_green_light,
android.R.color.holo_orange_light,
android.R.color.holo_red_light);
mSwipeContainer.setRefreshing(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_link_details, container, false);
ButterKnife.inject(this, rootView);
return rootView;
}
@Override
public void onRefresh() {
// refresh
}
}
@ niks.stack En respuesta a su respuesta, mostraría la rueda de progreso después de que se haya completado
onLayout()
.
Cuando lo usé directamente después de
onMeasure()
, no
onMeasure()
algunos de los desplazamientos, pero lo
onLayout()
después de
onLayout()
.
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (!mLaidOut) {
mLaidOut = true;
setRefreshing(mPreLayoutRefreshing);
}
}
@Override
public void setRefreshing(boolean refreshing) {
if (mLaidOut) {
super.setRefreshing(refreshing);
} else {
mPreLayoutRefreshing = refreshing;
}
}
Además de Volodymyr Baydalka, use también el siguiente código:
swipeContainer.post(new Runnable() {
@Override
public void run() {
swipeContainer.setRefreshing(false);
}
});
Explicación
Implementé la solución dada por Volodymyr Baydalka (usando fragmentos) pero después de que comenzó swipeReferesh nunca desapareció incluso al llamar a
swipeContainer.setRefreshing(false);
así que tuve que implementar el código dado anteriormente que resolvió mi problema.
cualquier otra idea de por qué sucede esto es muy bienvenida.
Saludos,
''com.android.support:appcompat-v7:22.2.1''
Ante el mismo problema. Mi solución -
mSwipeRefreshLayout.post(new Runnable() {
@Override
public void run() {
mSwipeRefreshLayout.setRefreshing(true);
}
});
Con la biblioteca de soporte de Android 24.2.0, ¡el problema debería haberse resuelto! https://developer.android.com/topic/libraries/support-library/revisions.html#24-2-0-bugfixes
Estoy usando ''com.android.support:appcompat-v7:23.1.1''
swipeRefreshLayout.post(new Runnable() {
@Override
public void run() {
swipeRefreshLayout.setRefreshing(true);
getData();
}
});
anteriormente estaba usando
swipeRefreshLayout.setRefreshing(true);
dentro del método
getData()
, por lo que no estaba funcionando.
No sé por qué no funciona dentro del método.
Aunque usé
swipeRefreshLayout.setRefreshing(true);
solo una vez en mi Fragmento.
Mi solución (sin soporte v7) -
TypedValue typed_value = new TypedValue();
getTheme().resolveAttribute(android.R.attr.actionBarSize, typed_value, true);
swipeLayout.setProgressViewOffset(false, 0, getResources().getDimensionPixelSize(typed_value.resourceId));
if(!swipeLayout.isEnabled())
swipeLayout.setEnabled(true);
swipeLayout.setRefreshing(true);
Mi solución es anular
SwipeRefreshLayout
:
public class MySwipeRefreshLayout extends SwipeRefreshLayout {
private boolean mMeasured = false;
private boolean mPreMeasureRefreshing = false;
public MySwipeRefreshLayout(final Context context) {
super(context);
}
public MySwipeRefreshLayout(final Context context, final AttributeSet attrs) {
super(context, attrs);
}
@Override
public void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (!mMeasured) {
mMeasured = true;
setRefreshing(mPreMeasureRefreshing);
}
}
@Override
public void setRefreshing(final boolean refreshing) {
if (mMeasured) {
super.setRefreshing(refreshing);
} else {
mPreMeasureRefreshing = refreshing;
}
}
}
Otra solución es crear un nuevo control y derivador de SwipeRefreshLayout. Anule la función OnMeasure y vuelva a alternar la actualización, si la actualización está activada. Utilizo esta solución en un proyecto xamarin y funciona bien. Aquí algunos ejemplos de código C #:
class MySwipeRefreshLayout : SwipeRefreshLayout
{
/// <summary>
/// used to indentify, if measure was called for the first time
/// </summary>
private bool m_MeasureCalled;
public MvxSwipeRefreshLayout(Context context, IAttributeSet attrs)
: base(context, attrs)
{
}
public MvxSwipeRefreshLayout(Context context)
: base(context)
{
}
public override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
base.OnMeasure(widthMeasureSpec, heightMeasureSpec);
if (!m_MeasureCalled)
{
//change refreshing only one time
m_MeasureCalled = true;
if (Refreshing)
{
Refreshing = false;
Refreshing = true;
}
}
}
}
Prueba esto
mSwipeRefreshLayout.setNestedScrollingEnabled (true);
Según la respuesta de Volodymyr Baydalka , esta es solo una pequeña idea que lo ayudará a mantener limpio el código. Merece una publicación, creo: podrá revertir fácilmente el comportamiento de la publicación a la llamada al método directo, una vez que se solucione el error.
Escribe una clase de utilidad como:
public class Utils
{
private Utils()
{
}
public static void setRefreshing(final SwipeRefreshLayout swipeRefreshLayout, final boolean isRefreshing)
{
// From Guava, or write your own checking code
checkNonNullArg(swipeRefreshLayout);
swipeRefreshLayout.post(new Runnable()
{
@Override
public void run()
{
swipeRefreshLayout.setRefreshing(isRefreshing);
}
});
}
}
En su código, sustituya
mSwipeContainer.setRefreshing(isRefreshing)
por
Utils.setRefreshing(mSwipeContainer, isRefreshing)
: ahora solo es necesario cambiar un punto en el código una vez que se corrige el error, la clase
Utils
.
El método también se puede insertar en línea (y eliminar de
Utils
).
Por lo general, no habrá una diferencia visual notable.
Sin embargo, tenga en cuenta que la actualización pendiente podría mantener vivas sus instancias de
Activity
, manteniendo
SwipeRefreshLayout
en sus jerarquías de vista.
Si eso es una preocupación, modifique el método para usar
WeakReference
s, pero normalmente no bloquea el hilo de la interfaz de usuario de todos modos, y por lo tanto demora gc solo por un par de milisegundos.
También puede llamar a este método antes de setRefreshing ..
swipeRefreshLayout.measure(View.MEASURED_SIZE_MASK,View.MEASURED_HEIGHT_STATE_SHIFT);
swipeRefreshLayout.setRefreshing(true);
Me funcionó.
Utilicé AppCompat Library
com.android.support:appcompat-v7:21.0.3
, usando su mismo enfoque y funcionó.
Entonces, actualizas la versión de esa biblioteca.
Consejo:
RelativeLayout
no admite orientación, es un atributo para
LinearLayout
.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ViewGroup view = (ViewGroup) inflater.inflate(R.layout.license_fragment,
container, false);ButterKnife.inject(this, view);
// Setting up Pull to Refresh
swipeToRefreshLayout.setOnRefreshListener(this);
// Indicator colors for refresh
swipeToRefreshLayout.setColorSchemeResources(R.color.green,
R.color.light_green);
}
Diseño XML:
<android.support.v4.widget.SwipeRefreshLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_margin_vertical"
android:paddingTop="@dimen/activity_margin_vertical">
<!-- Content -->
</ScrollView>
</android.support.v4.widget.SwipeRefreshLayout>
mRefreshLayout.getViewTreeObserver()
.addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
mRefreshLayout
.getViewTreeObserver()
.removeGlobalOnLayoutListener(this);
mRefreshLayout.setRefreshing(true);
}
});