SwipeRefreshLayout setRefreshing () प्रारंभ में संकेतक नहीं दिखा रहा है


144

मैं एक बहुत ही सरल लेआउट है, लेकिन जब मैं फोन setRefreshing(true)में onActivityCreated()मेरी टुकड़ा की, इसे शुरू नहीं दिखाती है।

यह केवल तभी पता चलता है जब मैं रिफ्रेश करने के लिए एक पुल करता हूं। किसी भी विचार क्यों यह शुरू में नहीं दिखा रहा है?

खुशबू 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>

टुकड़ा कोड:

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

आप किस संस्करण का उपयोग करते हैं?
अहमद हेगाज़ी

संकलन "com.android.support :appcompat-v7:21.0.0"
वज्र नंइजा

मैं पुष्टि करता हूं कि जाने पर उस संस्करण से मेरे साथ यह समस्या हुई थी। पहले के संस्करणों में कोई समस्या नहीं है। अगर मुझे कोई उपाय मिलता है तो मैं समाधान पोस्ट करूँगा।
अहमद हेगाज़ी

मुझे पहले के संस्करण की कोशिश करने दें
वज्रनाजा

इसके अलावा मेरे लिए v20 पर काम नहीं कर रहा। यह आपके लिए किस संस्करण पर काम कर रहा है?
थंडरसिनजा

जवाबों:


307

उसी मुद्दे का सामना किया। मेरा समाधान -

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

1
अच्छी तरह से काम करता है, लेकिन मुझे नहीं पता कि हमें mSwipeRefreshLayout.setRefreshing (सही) के बजाय ऐसा करने की आवश्यकता क्यों है;
कोकरिको


1
यह एक अच्छा समाधान / वर्कअराउंड नहीं है। यदि उपयोगकर्ता हवाई जहाज मोड पर है, तो नेटवर्क रिक्वेस्ट शुरू करने और उसकी प्रतिक्रिया (इस मामले में विफलता) प्राप्त करने के बाद आपका रिफ्रेश लॉयल अपने आप ही ताज़ा होने लगेगा। ताज़ा करने से रोकने के लिए इसे हैंडल करने पर, यह तब तक काम नहीं करेगा क्योंकि यह अभी तक शुरू नहीं हुआ था! आपके द्वारा अपनी प्रतिक्रिया प्राप्त करने के बाद दूसरे शब्दों में रिफ्रेश लाइयआउट ताज़ा होना शुरू हो जाएगा। सौभाग्य इसे रोक रहा है
समर

1
जैसा कि मुझे याद है कि "पोस्ट" सिंक हैं और जोड़ने के क्रम में चलती हैं। तो आप इसे रोकने के लिए एक और पोस्ट जोड़ सकते हैं।
वलोडिमिर बेयल्डका

2
यह शायद कार्यान्वयन में सबसे सरल दिखता है लेकिन यह अच्छा नहीं है। नीचे दिए गए @ niks.stack समाधान बेहतर है क्योंकि इसका उपयोग करने वाले कोड में किसी भी बदलाव की आवश्यकता नहीं है, इसलिए जब अंततः यह बग समर्थन में तय हो जाता है, तो आप बस वापस करने के लिए समर्थन SwipeRefreshLayout
Marcin Orlowski

100

इसके बजाय वलोडिमिर बेयल्डका का जवाब देखें।

ये पुराने वर्कअराउंड हैं।

यह पहले के संस्करण पर काम करता था android.support.v4, लेकिन 21.0.0 के संस्करण से यह काम नहीं करता है और अभी भी 10-12 दिसंबर, 2014 को android.support.v4:21.0.3जारी किया गया है और यही कारण है।

SwipeRefreshLayout संकेतक प्रकट नहीं होता है जब से setRefreshing(true)पहले कहा जाता हैSwipeRefreshLayout.onMeasure()

युक्ति:

कॉल करने setProgressViewOffset()पर SwipeRefreshLayoutलेआउट का सर्कल व्यू अमान्य SwipeRefreshLayout.onMeasure()हो जाता है जिसके कारण तुरंत कॉल किया जाता है।

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

अद्यतन बेहतर समाधान

क्योंकि अभिविन्यास में परिवर्तन होने पर एक्शनबार पतला हो सकता है या आपने मैन्युअल रूप से एक्शनबार का आकार निर्धारित किया है। हमने इस दृश्य के ऊपर से पिक्सेल में ऑफसेट सेट किया है, जिस पर प्रगति स्पिनर को वर्तमान एक्शनबार के आकार के लिए एक सफल स्वाइप जेस्चर के बाद रीसेट करना चाहिए।

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

अद्यतन 20 नवंबर 2014

यदि व्यू शुरू होने के बाद SwipeRefreshLayout को दिखाना आपके ऐप के लिए बहुत महत्वपूर्ण नहीं है। आप भविष्य में इसे केवल हैंडलर या अपनी मनचाही चीज का उपयोग करके भविष्य में पोस्ट कर सकते हैं।

उदहारण के लिए।

handler.postDelayed(new Runnable() {

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

या वलोडिमिर बेयल्डका के उत्तर के रूप में।

यहाँ है मुद्दा एंड्रॉयड समस्या ट्रैकर में। कृपया उन्हें यह दिखाने के लिए उकसाएं कि हमें इसे ठीक करने की आवश्यकता है।


क्या आपने बहुत परीक्षण किया था delay time? मैं 500अपने पर प्रयोग कर रहा हूं Galaxy S4। यकीन नहीं होता कि यह किसी अन्य डिवाइस पर समस्या होगी।
दलबंग 20

मैंने देरी के समय के साथ ज्यादा परीक्षण नहीं किया, लेकिन मुझे लगता है 500कि मैं ठीक करूंगा। मैंने इसका परीक्षण किया है। emulatorमैं सिर्फ मिलीसेकंड के safeसाथ रहना चाहता था1000
अहमद हेगाज़ी

3
देरी से पोस्ट करने की कोई आवश्यकता नहीं है। आप बस पोस्ट कर सकते हैं। बिना देरी के पोस्ट करने का मतलब है "यह काम एक बार जब आप जो अभी कर रहे हैं उसके साथ करें"। और अब यह क्या कर रहा है और अपने यूआई को माप रहा है।
ओरेन

47

मेरा समाधान ओवरराइड करना है 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
आपके समाधान का लाभ दृश्य को अछूता रखने के लिए है! इस तरह हम यहाँ निर्दिष्ट डिज़ाइन पैटर्न के अनुरूप हैं: google.com/design/spec/patterns/… । धन्यवाद!
इगोर डी लोरेंज़ी

क्या आप बता सकते हैं कि यह कैसे काम करता है? यह काम कर रहा है लेकिन मुझे आंतरिक कामकाज नहीं मिल रहा है। क्या मुझे कुछ मामूली याद आ रहा है?
श्री

setRefreshing ऑनमार्ट कॉल के बाद ही काम करता है, इसलिए हम लोकल रिफ्रेशिंग फ्लैग को स्टोर करते हैं, और पहले ऑनमैर कॉल पर इसे लागू करते हैं
nikita.zhelonkin

5
मैं इस समाधान से प्यार करता हूं क्योंकि इसका मतलब है कि SwipeRefreshLayout को कॉल करने वाला कोड बिल्कुल वैसा ही हो सकता है जैसा हम चाहते हैं कि यह बिना किसी जटिलता के हो। यह मूल रूप से SwipeRefreshLayout में बग को ठीक करता है। SwipeRefreshLayout वास्तव में बस इस तरह से लागू किया जाना चाहिए।
डेट्राहम

यह उत्तर ऐसा प्रतीत नहीं हो सकता है कि सीधे आगे है, लेकिन यह कई समर्थन लाइब्रेरी संस्करणों के माध्यम से समस्या को ठीक करता है (मेरे मामले में यह 23.1.1 है)। टिकट के अनुसार यह मुद्दा @ 23.2 निर्धारित नहीं है। code.google.com/p/android/issues/detail?id=77712
रॉबर्ट

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

3
यह उत्तर केवल एक ही है जो हैक नहीं है इसलिए इसे स्वीकार किया जाना चाहिए
हेनरिक

1
बस एक छोटी सी बात: .removeGlobalOnLayoutListener होना चाहिए। .removeOnGlobalLayoutListener
mkuech

1
@mkeuch इस बात पर निर्भर करता है कि आपका लक्ष्य किस API पर है। यदि API16 के अंतर्गत आपका लक्ष्यीकरण है, तो आपको API संस्करण की जाँच करनी होगी, और दोनों का उपयोग करना होगा।
मार्को

मुझे यह सबसे अधिक उत्कीर्ण उत्तर की तुलना में थोड़ा अधिक पसंद है क्योंकि यह अधिक स्पष्ट है कि इसका उपयोग क्यों किया जाता है।
मार्सेल ब्रो

मुझे अपने आप को सही करना चाहिए, यह समाधान हमेशा मेरे लिए काम नहीं करता है। कुछ मामलों में setRefreshing(false)लिपटे कॉलिंग onGlobalLayoutListener()लोडिंग इंडिकेटर को खारिज नहीं करता है।
मार्सेल ब्रो


4

वलोडिमिर बेयल्डका के जवाब के आधार पर , यह सिर्फ एक छोटा विचार है जो आपको कोड को साफ रखने में मदद करेगा। यह एक ऐसा पद पाने के योग्य है जिसका मुझे विश्वास है: आप बग को ठीक करने के बाद व्यवहार को पोस्टिंग से डायरेक्ट मेथड कॉल पर आसानी से वापस ला सकेंगे।

एक उपयोगिता वर्ग लिखें जैसे:

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

आपके mSwipeContainer.setRefreshing(isRefreshing)द्वारा स्थानापन्न कोड में Utils.setRefreshing(mSwipeContainer, isRefreshing): अब बग को तय करने के बाद कोड में केवल एक बिंदु को बदलना होगा, Utilsकक्षा। विधि को फिर से (और हटा दिया गया Utils) इनलाइन भी किया जा सकता है ।

आम तौर पर ध्यान देने योग्य दृश्य अंतर नहीं होगा। हालांकि ध्यान रखें कि लंबित रिफ्रेश आपके पुराने Activityउदाहरणों को जीवित रख सकता है , SwipeRefreshLayoutउनके दृष्टिकोण पदानुक्रमों में। यदि यह एक चिंता का विषय है, तो WeakReferenceएस का उपयोग करने के लिए विधि को ट्वीक करें , लेकिन आम तौर पर आप यूआई थ्रेड को वैसे भी ब्लॉक नहीं करते हैं, और इस प्रकार केवल एक-दो मिलीसेकेंड तक देरी से जीसी।


2

इसके अलावा आप इस विधि को सेटफ्रेशिंग से पहले कॉल कर सकते हैं।

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

यह मेरे लिए काम करता है।


1

मैंने com.android.support:appcompat-v7:21.0.3आपके उसी दृष्टिकोण का उपयोग करते हुए AppCompat Library का इस्तेमाल किया और इसने काम किया। इसलिए, आप उस लाइब्रेरी के संस्करण को अपडेट करते हैं।

सलाह: RelativeLayoutअभिविन्यास का समर्थन नहीं करता है, यह एक विशेषता है 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);
}

लेआउट 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>

1

Volodymyr Baydalka के अलावा निम्नलिखित कोड का उपयोग करें:

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

स्पष्टीकरण I ने वलोडिमिर बायडाल्का (टुकड़ों का उपयोग करके) द्वारा दिए गए समाधान को लागू किया, लेकिन स्वाइपरेफ़र शुरू होने के बाद यह कॉल करने पर भी कभी दूर नहीं गया, swipeContainer.setRefreshing(false); इसलिए ऊपर दिए गए कोड को लागू करना पड़ा जिससे मेरी समस्या हल हो गई। किसी भी अधिक विचार क्यों यह होता है सबसे स्वागत है।

सादर,

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


1

@ niks.stack उनके जवाब के जवाब में, मैं प्रगति पहिया दिखाने के बाद onLayout()किया गया है। जब मैंने इसे सीधे इस्तेमाल किया onMeasure(), तो यह कुछ ऑफर्स का सम्मान नहीं करेगा, लेकिन इसके बाद इसका उपयोग 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 के बाद एक अच्छे कॉलबैक की तलाश में था! Thnx। मुझे गुस्सा आ रहा था कि आरंभिक रन ऑफ़ द ऑफ था ...
xdbas

0

मेरा समाधान (समर्थन 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);

0

Im 'com.android.support:appcompat-v7:23.1.1' का उपयोग कर रहा है

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

पहले मैं swipeRefreshLayout.setRefreshing(true);अंदर की getData()विधि का उपयोग कर रहा था , इसलिए यह काम नहीं कर रहा था। मैं नहीं जानता कि इसकी विधि के अंदर काम क्यों नहीं कर रहा है।

हालांकि मैंने swipeRefreshLayout.setRefreshing(true);अपने फ्रैगमेंट में केवल एक बार इस्तेमाल किया ।



-1

एक और समाधान है SwipeRefreshLayout से एक नया नियंत्रण और व्युत्पन्न बनाना। ताज़ा सक्रिय होने पर OnMeasure फ़ंक्शन को ओवरराइड करें और रिफ़र को फिर से चालू करें। मैं एक xamarin परियोजना में इस समाधान का उपयोग करता हूं और यह अच्छी तरह से काम करता है। यहाँ कुछ नमूना 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;
            }
        }
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.