SwipeRefreshLayout setRefreshing () göstergesi başlangıçta göstermiyor


144

Ben çok basit bir düzen var ama dediğim zaman setRefreshing(true)içinde onActivityCreated()benim parçanın, başlangıçta göstermez.

Sadece yenilemek için bir çekim yaptığımda gösterir. Başlangıçta neden görünmediğine dair bir fikrin var mı?

Parça 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>

Parça kodu:

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
    }
}

Hangi sürümü kullanıyorsunuz?
Ahmed Hegazy

derlemek "com.android.support:appcompat-v7:21.0.0"
thunderousNinja

Bu sorunun bende o versiyondan devam ettiğini teyit ediyorum. Önceki sürümlerde bununla ilgili herhangi bir sorun yoktur. Eğer alırsam çözüm yollayacağım.
Ahmed Hegazy

Let me den eski bir sürüm
thunderousNinja

Ayrıca benim için v20 üzerinde çalışmıyor. Sizin için hangi sürümde çalışıyor?
thunderousNinja

Yanıtlar:


307

Aynı sorunla karşı karşıya. Çözümüm -

mSwipeRefreshLayout.post(new Runnable() {
    @Override
    public void run() {
        mSwipeRefreshLayout.setRefreshing(true);
    }
});

1
İyi çalışıyor ama neden mSwipeRefreshLayout.setRefreshing (true) yerine bunu yapmak gerektiğini bilmiyorum;
Cocorico


1
Bu iyi bir çözüm / geçici çözüm değildir. Kullanıcı uçak modundaysa, refreshLayout'unuz ağ isteğini zaten başlattıktan ve yanıtını aldıktan sonra kendi iş parçacığında yenilenmeye başlar (bu durumda hata). RefreshLayout'u durdurmak için kullanılırken, henüz başlamadığı için işe yaramaz! Başka bir deyişle, yanıtınızı aldıktan sonra refreshLayout yenilemeye başlar. İyi şanslar onu durduruyor
Samer

1
Hatırladığım gibi "gönderiler" eşitlenir ve ekleme sırasına göre çalışır. Böylece durdurmak için başka bir yayın ekleyebilirsiniz.
Volodymyr Baydalka

2
Belki de uygulamada en basit görünüyor ama hoş değil. Aşağıdaki @ niks.stack çözümü , kod kullanarak herhangi bir değişiklik gerektirmediği için daha iyidir, bu nedenle sonunda bu hata destek lib'de düzeltildiğinde, sadece lib'i desteklemeye geri dönersiniz SwipeRefreshLayout
Marcin Orlowski

100

Bunun yerine Volodymyr Baydalka'nın cevabına bakın.

Bunlar eski çözümler.

Bu daha önceki sürümünde çalışıyordu android.support.v4, ancak 21.0.0 sürümünden itibaren çalışmıyor ve 10-12 Aralık 2014'teandroid.support.v4:21.0.3 piyasaya sürülüyor. .

SwipeRefreshLayout göstergesi, setRefreshing(true)önceSwipeRefreshLayout.onMeasure()

Çözüm:

çağırmadan setProgressViewOffset()üzerinde SwipeRefreshLayoutneden düzen çemberi görünümünü invalidtes o SwipeRefreshLayout.onMeasure()hemen çağrılacak.

mSwipeRefreshLayout.setProgressViewOffset(false, 0,
                (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24, getResources().getDisplayMetrics()));
mSwipeRefreshLayout.setRefreshing(true);

GÜNCELLEME Daha İyi Geçici Çözüm

Çünkü yön değiştiğinde eylem çubuğu incelebilir veya eylem çubuğu boyutunu manuel olarak ayarlamış olabilirsiniz. Dengeyi, başarılı bir kaydırma hareketi sonrasında geçerli işlem çubuğu boyutuna geçtikten sonra ilerleme döndürücünün sıfırlanması gereken bu görünümün üstünden piksel cinsinden ayarladık.

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));

GÜNCELLEŞTİRME 20 Kasım 2014

Görünüm başlatıldıktan sonra uygulamanız için SwipeRefreshLayout'u göstermeniz çok önemli değilse. İşleyicileri veya istediğiniz herhangi bir şeyi kullanarak gelecekte bir zamana gönderebilirsiniz.

Örnek olarak.

handler.postDelayed(new Runnable() {

    @Override
    public void run() {
        mSwipeRefreshLayout.setRefreshing(true);
    }
}, 1000);

veya Volodymyr Baydalka'nın cevabından bahsedildiği gibi.

İşte mesele android sorun izleyicide. Lütfen düzeltilmemiz gerektiğini göstermek için oy verin.


İle çok fazla test yaptınız mı delay time? Ben kullanıyorum 500on my Galaxy S4. Bunun başka bir cihazda sorun olup olmayacağından emin değilim.
theblang

Ben gecikme süresi ile çok test yapmadım, ama sanırım 500bunu test ettik fine.I yapacağını emulatorsadece olmak istedim .I safeile 1000milisaniye
Ahmed Hegazy

3
Gecikmeli yayınlamaya gerek yoktur. sadece yayınlayabilirsiniz. gecikmeden yayınlamak, "şu anda yaptığınız işi bitirdiğinizde bu şeyi yapın" anlamına gelir. ve şimdi yaptığı şey kullanıcı arayüzünüzü ölçmek ve düzenlemek.
Ören

47

Benim çözümüm geçersiz kılmak 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;
        }
    }
}

3
Çözümünüzün avantajı, görüntüye dokunulmamasını sağlamaktır! Bu şekilde, burada belirtilen tasarım modeline uygun olarak devam ediyoruz: google.com/design/spec/patterns/… . Teşekkürler!
Igor de Lorenzi

Bunun nasıl çalıştığını açıklayabilir misiniz? Çalışıyor ama iç işleri tam olarak anlamıyorum. Sadece önemsiz bir şey mi kaçırıyorum?
Sree

setRefreshing sadece onMeasure çağrısından sonra çalışır, bu yüzden yerel ferahlatıcı bayrağı saklarız ve ilk onMeasure çağrısı uygular
nikita.zhelonkin

5
Bu çözümü seviyorum çünkü SwipeRefreshLayout çağıran kod herhangi bir komplikasyon olmadan, olmasını istediğimiz gibi olabilir anlamına gelir. Temelde SwipeRefreshLayout'ta hatayı düzelttim. SwipeRefreshLayout gerçekten bu şekilde uygulanmalıdır.
DataGraham

Bu yanıt o kadar da ileriye doğru görünmeyebilir, ancak birçok destek kütüphanesi sürümünde sorunu güzelce giderir (benim durumumda 23.1.1). Bilete göre bu sorun @ 23.2'de düzeltilmedi. code.google.com/p/android/issues/detail?id=77712
Robert

20
mRefreshLayout.getViewTreeObserver()
                .addOnGlobalLayoutListener(
                        new ViewTreeObserver.OnGlobalLayoutListener() {
                            @Override
                            public void onGlobalLayout() {
                                mRefreshLayout
                                        .getViewTreeObserver()
                                        .removeGlobalOnLayoutListener(this);
                                mRefreshLayout.setRefreshing(true);
                            }
                        });

3
Bu cevap bir hack olmayan tek cevaptır, bu yüzden kabul edilmelidir
Heinrich

1
Sadece küçük bir şey: .removeGlobalOnLayoutListener .removeOnGlobalLayoutListener
mkuech

1
@mkeuch, hedeflemenizin hangi API'ya bağlı olduğuna bağlıdır. API16 altında hedeflemeniz varsa, API sürüm kontrolü yapmanız ve her ikisini birden kullanmanız gerekir.
Marko

Bunu en çok cevaplanan cevaptan biraz daha beğendim, çünkü neden kullanıldığını daha açık.
Marcel Bro

Kendimi düzeltmeliyim, bu çözüm her zaman benim için işe yaramaz. Bazı durumlarda, setRefreshing(false)sarılmış çağrı onGlobalLayoutListener()yükleme göstergesini kapatmaz.
Marcel Bro


4

Volodymyr Baydalka'nın cevabına dayanarak , bu sadece kodu temiz tutmanıza yardımcı olacak küçük bir fikirdir. İnanıyorum bir gönderiyi hak ediyor: Hata düzeltildikten sonra, davranışı kolayca gönderme yönteminden doğrudan yöntem çağrısına geri alabileceksiniz.

Şunun gibi bir yardımcı program sınıfı yazın:

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);
            }
        });
    }
}

Kod yerine mSwipeContainer.setRefreshing(isRefreshing) tarafından Utils.setRefreshing(mSwipeContainer, isRefreshing): Hata düzeltildikten sonra artık kod ihtiyaçları tek nokta, değiştirilmesi Utilssınıfı. Yöntem ayrıca satır içine alınabilir (ve buradan çıkarılabilir Utils).

Genellikle belirgin bir görsel fark olmayacaktır. Bekleyen yenilemenin , görünüm hiyerarşilerini koruyarak eski Activityörneklerinizi canlı tutabileceğini unutmayın SwipeRefreshLayout. Bu bir endişe ise, WeakReferences kullanma yöntemini değiştirin , ancak normalde UI iş parçacığını yine de engellemezsiniz ve böylece gc'yi yalnızca birkaç milisaniye geciktirirsiniz.


2

Ayrıca setRefreshing önce bu yöntemi çağırabilirsiniz ..

    swipeRefreshLayout.measure(View.MEASURED_SIZE_MASK,View.MEASURED_HEIGHT_STATE_SHIFT);
swipeRefreshLayout.setRefreshing(true);

Benim için işe yarıyor.


1

AppCompat Kütüphanesini kullandım com.android.support:appcompat-v7:21.0.3Aynı yaklaşımı kullanarak kullandım ve işe yaradı. Böylece, bu kütüphanenin sürümünü güncellersiniz.

Tavsiye: RelativeLayoutyönlendirmeyi desteklemez, bu bir özelliktir 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);
}

Düzen XML'si:

<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>

1

Volodymyr Baydalka'ya ek olarak aşağıdaki kodu da kullanın:

swipeContainer.post(new Runnable() {
        @Override
        public void run() {
            swipeContainer.setRefreshing(false);
        }
    });

Açıklama Volodymyr Baydalka tarafından verilen çözümü (parçaları kullanarak) uyguladım ama swipeReferesh başladıktan sonra bile çağrıda hiç gitmedi swipeContainer.setRefreshing(false); bu yüzden sorunumu çözen yukarıda verilen kodu uygulamak zorunda kaldı. bunun neden daha fazla fikir olduğunu kabul ediyoruz.

Saygılarımızla,

'Com.android.support:appcompat-v7:22.2.1'


1

@ niks.stack Cevabına yanıt olarak, ilerledikten sonra ilerleme çarkını gösterirdim onLayout(). Doğrudan kullandıktan sonra onMeasure(), bazı ofsetleri onurlandırmazdı, ama sonra kullandım 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;
    }
}

OnMeasure'dan sonra iyi bir geri arama arıyordum! Thnx. İlk koşuda ofsetin kapalı olduğu boktan sinir bozucu oldu ...
xdbas

0

Çözümüm (destek v7 olmadan) -

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);

0

'Com.android.support:appcompat-v7:23.1.1' kullanıyorum

swipeRefreshLayout.post(new Runnable() {
        @Override
        public void run() {
            swipeRefreshLayout.setRefreshing(true);
            getData();
        }
    });

Daha önce swipeRefreshLayout.setRefreshing(true);içerideki getData()yöntemi kullanıyordum , bu yüzden işe yaramıyordu. Neden yöntem içinde çalışmadığını bilmiyorum.

Parçamda swipeRefreshLayout.setRefreshing(true);sadece bir kez kullandım .


0

Bunu dene

(Doğru) mSwipeRefreshLayout.setNestedScrollingEnabled;


-1

Başka bir geçici çözüm, yeni bir denetim oluşturmak ve SwipeRefreshLayout'tan türetmektir. OnMeasure işlevini geçersiz kılın ve yenileme etkinleştirilmişse yenilemeyi tekrar değiştirin. Bu çözümü bir xamarin projesinde kullanıyorum ve iyi çalışıyor. İşte bazı örnek C # -Kod:

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;
            }
        }
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.