সোয়াইপ রিফ্রেশলয়আউট সেট রিফ্রেশিং () প্রাথমিকভাবে সূচক দেখানো হচ্ছে না


144

আমি একটি খুব সহজ লেআউট আছে কিন্তু যখন আমি কল setRefreshing(true)মধ্যে onActivityCreated()আমার টুকরা, এটি প্রাথমিকভাবে দেখায় না।

এটি কেবল তখনই প্রদর্শিত হয় যখন আমি রিফ্রেশ করার জন্য টান করি। কোনও ধারণা কেন এটি প্রাথমিকভাবে প্রদর্শিত হচ্ছে না?

খণ্ড এক্সএমএল:

<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"
বজ্রগ্রস্ত

আমি নিশ্চিত হয়েছি যে সমস্যাটি আমার সাথে সেই সংস্করণটি থেকে চলছে। আগের সংস্করণগুলির সাথে কোনও সমস্যা নেই। আমি যদি কিছু পাই তবে সমাধান পোস্ট করব।
আহমেদ হেগাজি

আমাকে আগের সংস্করণটি চেষ্টা করতে দাও
বজ্রসংক্রান্ত

এছাড়াও আমার জন্য ভি 20 তে কাজ করছেন না। এটি আপনার জন্য কোন সংস্করণে কাজ করছে?
বজ্রহীন

উত্তর:


307

একই ইস্যুতে মুখোমুখি। আমার সমাধান -

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

1
ভাল কাজ করে তবে আমি জানি না কেন আমাদের এমসুইপআরফ্রেশলাইআউট.সেটর রিফ্রেশিং (সত্য) এর পরিবর্তে এটি করা দরকার;
কোকরিকো


1
এটি কোনও ভাল সমাধান / কর্মক্ষেত্র নয়। ব্যবহারকারী যদি বিমান মোডে থাকে তবে আপনার রিফ্রেশআলআউট ইতিমধ্যে নেটওয়ার্কের অনুরোধ শুরু করার পরে এবং তার প্রতিক্রিয়া পাওয়ার (তার ক্ষেত্রে ব্যর্থতা) পাওয়ার পরে নিজের থ্রেডে রিফ্রেশ শুরু করবে। রিফ্রেশআলআউট বন্ধ করার জন্য এটি পরিচালনা করার পরে, এটি এখনও শুরু না হওয়ায় এটি কাজ করবে না! অন্য কথায় রিফ্রেশআলআউট আপনার প্রতিক্রিয়া পাওয়ার পরে সতেজ করা শুরু করবে। শুভকামনা এটি বন্ধ করে
সমর

1
যেমনটি আমার মনে আছে "পোস্টগুলি" সিঙ্ক হয় এবং যুক্ত করার ক্রমে চলে। সুতরাং এটি বন্ধ করতে আপনি অন্য পোস্ট যুক্ত করতে পারেন।
ভোলোডাইমার বেদালকা

2
এটি বাস্তবায়নে সম্ভবত সবচেয়ে সহজ দেখাচ্ছে তবে এটি ভাল নয়। নীচে @ নাইস.স্ট্যাকের সমাধানটি আরও ভাল কারণ এটি ব্যবহার করে কোডে কোনও পরিবর্তন প্রয়োজন হয় না, সুতরাং অবশেষে যখন এই বাগটি সমর্থন লাইব স্থির করা হয়, আপনি কেবল লাইব সমর্থন করার জন্য ফিরে যান সুইপ রেফ্রেশলয়আউট
মার্সিন

100

পরিবর্তে ভলডোমির বায়ডালকার উত্তর দেখুন।

এগুলি হ'ল পুরানো কাজের ক্ষেত্র।

এটি পূর্ববর্তী সংস্করণে কাজ করত android.support.v4, তবে চলমান সংস্করণ থেকে 21.0.0 এটি কাজ করে না এবং এখনও 10-12 ডিসেম্বর, 2014android.support.v4:21.0.3 এ প্রকাশিত রয়েছে এবং এটিই কারণ।

যখন setRefreshing(true)আগে ডাকা হবে তখন সোয়াইপ রিফ্রেশলয়আউট সূচকটি উপস্থিত হয় নাSwipeRefreshLayout.onMeasure()

কার্যসংক্রান্ত:

কলিং setProgressViewOffset()উপর SwipeRefreshLayoutবিন্যাস ঘটাচ্ছে বৃত্তের দৃশ্য invalidtes যে SwipeRefreshLayout.onMeasure()অবিলম্বে বলা হবে।

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

উন্নত workaround

কারণ অরিয়েন্টেশন পরিবর্তনের সময় অ্যাকশনবারটি আরও পাতলা হতে পারে বা আপনি নিজে অ্যাকশনবারের আকারটি সেট করেছেন। আমরা এই ভিউটির শীর্ষ থেকে পিক্সেলগুলিতে অফসেট সেট করেছি যেখানে বর্তমান অ্যাকশনবারের আকারে সফল সোয়াইপ অঙ্গভঙ্গির পরে অগ্রগতি স্পিনারটি পুনরায় সেট করতে হবে।

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

যদি ভিউ শুরু হয়ে যায় তবে সোয়াইপ রিফ্রেশলয়আউটটি দেখাতে যদি এটি আপনার অ্যাপের পক্ষে খুব গুরুত্বপূর্ণ না হয়। আপনি হ্যান্ডলার বা আপনার পছন্দসই কোনও জিনিস ব্যবহার করে ভবিষ্যতে কোনও সময়ে পোস্ট করতে পারেন।

উদাহরণ হিসাবে।

handler.postDelayed(new Runnable() {

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

বা ভলডোমায়ার বেয়াদালকার উত্তর হিসাবে উল্লেখ করা হয়েছে।

এখানে ইস্যু অ্যান্ড্রয়েড ইস্যু যে ব্যক্তি অনুসরণ করে না। আমাদের এটি সংশোধন করা দরকার তা দেখানোর জন্য দয়া করে এটি upvote করুন।


আপনি কি সাথে অনেক পরীক্ষা করেছিলেন delay time? আমি 500আমার ব্যবহার করছি Galaxy S4। এটি অন্য ডিভাইসে সমস্যা হবে কিনা তা নিশ্চিত নয়।
theblang

আমি বিলম্বের সময়ের সাথে সাথে অনেক পরীক্ষামূলক করিনি, কিন্তু আমার মনে 500fine.I করবেন তে এটি পরীক্ষা আছে emulator.আমি শুধু হতে চেয়েছিলেন safeসঙ্গে 1000মিলিসেকেন্ড
আহমেদ Hegazy

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/… । ধন্যবাদ!
ইগোর ডি লোরেঞ্জি

আপনি কিভাবে দয়া করে ব্যাখ্যা করতে পারেন? এটি কাজ করছে তবে আমি অভ্যন্তরীণ কাজগুলি বেশিরভাগ ক্ষেত্রে পাই না। আমি কি তুচ্ছ কিছু মিস করছি?
শ্রী

সেট-রিফ্রেশিং কেবলমাত্র onMeasure কল করার পরে কাজ করে, তাই আমরা স্থানীয় রিফ্রেশিং পতাকা সংরক্ষণ করি এবং প্রথমেম্যাসার কলটিতে এটি প্রয়োগ করুন
নিকিতা.জেলোনকিন

5
আমি এই সমাধানটি পছন্দ করি কারণ এর অর্থ সোয়াইপরিফ্রেশলাইআউটকে কল করা কোডটি কোনও রকম জটিলতা ছাড়াই ঠিক যেমন হতে পারে আমরা তা হতে চাই can এটি মূলত সোয়াইপরিফ্রেশলায়আগে বাগটি স্থির করেছে। সোয়াইপ রিফ্রেশলয়আউটটি সত্যই এইভাবে প্রয়োগ করা উচিত।
ডেটাগ্রাহাম

এই উত্তরটি সরাসরি সামনের দিকে না দেখায়, তবে এটি অনেকগুলি সমর্থন লাইব্রেরি সংস্করণ (আমার ক্ষেত্রে এটি ২৩.১.১) এর মাধ্যমে সমস্যাটি সুন্দরভাবে সমাধান করে। টিকিট অনুযায়ী এই ইস্যুটি 23.2 ঠিক করা হয়নি। কোড.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
কেবল একটি ছোট্ট জিনিস: .আরমিভগ্লোবালঅনলআউটলাইজনার হওয়া উচিত .রেমোভনগ্লোবাল লেআউটলিস্টনার
এমকিউইচ

1
@mkeuch আপনার টার্গেটিংটি কোন এপিআইয়ের উপর নির্ভর করে। যদি আপনার এপিআই 16 এর অধীনে লক্ষ্যবস্তু করা হয়, আপনাকে এপিআই সংস্করণ চেক করতে হবে এবং উভয়ই ব্যবহার করতে হবে।
মার্কো

আমি এটি সবচেয়ে উর্ধ্বমুখী উত্তরের চেয়ে কিছুটা বেশি পছন্দ করি কারণ এটি কেন ব্যবহৃত হয় তা আরও স্পষ্ট।
মার্সেল ব্রো

আমাকে অবশ্যই নিজেকে সংশোধন করতে হবে, এই সমাধানটি সর্বদা আমার পক্ষে কার্যকর হয় না। কিছু ক্ষেত্রে setRefreshing(false)মোড়ানো কলিং onGlobalLayoutListener()লোডিং সূচকটি খারিজ করে না।
মার্সেল ব্রো

14

অ্যানড্রয়েড সমর্থন লাইব্রেরি 24.2.0 সঙ্গে সমস্যা সমাধান করা উচিত ছিল! https://developer.android.com/topic/libraries/support-library/revisions.html#24-2-0-bugfixes


অ্যান্ড্রয়েডএক্স লাইবারারিগুলি অনুসন্ধান করা, সমস্যা এখনও অব্যাহত রয়েছে
ফরিদ

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 আপনার একই পদ্ধতির ব্যবহার করে ব্যবহার করেছি এবং এটি কার্যকর হয়েছে। সুতরাং, আপনি সেই লাইব্রেরির সংস্করণ আপডেট করুন।

পরামর্শ: 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);
}

লেআউট এক্সএমএল:

<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

ভোলডিমায়ার বায়ডালকা পাশাপাশি নিম্নলিখিত কোডগুলি ব্যবহার করুন:

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

ব্যাখ্যা আমি ভোলডিমিয়ার বেদালকা প্রদত্ত সমাধানটি (টুকরোগুলি ব্যবহার করে) বাস্তবায়ন করেছি তবে সোয়াইপ রেফারেশ শুরু হওয়ার পরে এটি কল করার পরেও কখনই দূরে যায় নি 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

আমি 'com.android.support:appcompat-v7:23.1.1' ব্যবহার করছি

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

আগে আমি ব্যবহার করছিলাম swipeRefreshLayout.setRefreshing(true); ভিতরে getData()পদ্ধতি , সুতরাং এটি কাজ করে না n't আমি জানি না কেন এটি অভ্যন্তরীণ পদ্ধতিতে কাজ করছে না।

যদিও আমি swipeRefreshLayout.setRefreshing(true);আমার খণ্ডে একবার ব্যবহার করেছি।



-1

আর একটি কার্যনির্বাহী হ'ল সোয়াইপরিফ্রেশলাইআউট থেকে নতুন নিয়ন্ত্রণ এবং ডেরাইভার তৈরি করা। রিফ্রেশ সক্রিয় করা থাকলে অন-মেজার ফাংশন ওভাররাইড করুন এবং রিফ্রেশটি আবার টগল করুন। আমি এই xamarin প্রকল্পে এই সমাধানটি ব্যবহার করি এবং এটি ভাল কাজ করে। এখানে কিছু নমুনা সি #-কোড:

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;
            }
        }
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.