একটি ভিউপ্যাজার থেকে একটি টুকরো পুনরুদ্ধার করুন


248

আমি তিনটি পৃথক টুকরো হোস্ট করার জন্য ViewPagerএকটি সাথে একসাথে ব্যবহার করছি FragmentStatePagerAdapter:

  • [Fragment1]
  • [Fragment2]
  • [Fragment3]

আমি পেতে চান, তখন Fragment1থেকে ViewPagerFragmentActivity

সমস্যা কী এবং আমি কীভাবে এটি ঠিক করব?

উত্তর:


504

মূল উত্তরটি ফ্রেমওয়ার্কের দ্বারা উত্পাদিত একটি নামের উপর নির্ভর করে। যদি তা কখনও পরিবর্তিত হয়, তবে এটি আর কাজ করবে না।

এই সমাধান সম্পর্কে কী, ওভাররাইডিং instantiateItem()এবং destroyItem()আপনার Fragment(State)PagerAdapter:

public class MyPagerAdapter extends FragmentStatePagerAdapter {
    SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();

    public MyPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public int getCount() {
        return ...;
    }

    @Override
    public Fragment getItem(int position) {
        return MyFragment.newInstance(...); 
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Fragment fragment = (Fragment) super.instantiateItem(container, position);
        registeredFragments.put(position, fragment);
        return fragment;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        registeredFragments.remove(position);
        super.destroyItem(container, position, object);
    }

    public Fragment getRegisteredFragment(int position) {
        return registeredFragments.get(position);
    }
}

উপলব্ধ খণ্ডগুলি নিয়ে কাজ করার সময় এটি আমার পক্ষে কাজ করে বলে মনে হচ্ছে। যে খণ্ডগুলি এখনও ইনস্ট্যান্ট করা হয়নি, কল করার সময় তা বাতিল হয়ে যাবে getRegisteredFragment। তবে আমি প্রায়শই বর্তমানটি Fragmentবের করার জন্য এটি ব্যবহার করছি ViewPager: adapater.getRegisteredFragment(viewPager.getCurrentItem())এবং এটি আর ফিরে আসবে না null

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


41
এটি আমিও ভাবতে পারি সেরা সমাধান। শুধু পরামর্শ হয়তো মোড়ানো হবে Fragmentএকটি WeakReferenceগ্যারান্টি আপনি হচ্ছে আবর্জনা সংগ্রহ থেকে একটি ধ্বংস টুকরা প্রতিরোধ না? ঠিক মতো করার মতো জিনিসটি দেখে মনে হচ্ছে ...
অ্যালেক্স লকউড

7
MyPagerAdapterলাইফাইসাইকেলের কারণে ধ্বংস হয়ে গেলে (অর্থাত্‍ ঘোরানো) কী হবে registerdFragments? হবে Activity/ Fragmentব্যবহার MyPagerAdapterএটা সংরক্ষণ করতে হবে onSaveInstanceState, এবং তারপর নতুন সঙ্গে এটি আপডেট করতে হবে FragmentManager; ref?
স্টিভেন বাইলে

10
যদি আমি ভুল না হয়ে থাকি (এবং আপনার এটি পরীক্ষা করা উচিত) তবে জেনেটিম পদ্ধতিটি কল করা হয় না - যেমন আপনি জানেন - তবে ইনস্ট্যান্টিয়েট আইটেম পদ্ধতিটি প্রতিটি খণ্ডের জন্য বলা হয় যা ঘূর্ণনের পরে ফ্রেমওয়ার্কের মাধ্যমে পুনরুদ্ধার করা হয়।
বোস্টনের স্ট্রিটস

6
হ্যাঁ, আমি যাচাই করেছি যা getItemপেজারে রক্ষা করা FragmentManagerরাজ্যগুলির পুনঃস্থাপনের কারণে , ঘোরানো (ইতিমধ্যে তৈরি হওয়া কোনও ফ্রেজের জন্য) আবার কল করা Fragmentsহবে না। যদি instantiateItemপ্রত্যেকে Fragmentপুনরুদ্ধার করা হয় তখন যদি ডাকা হয়, তবে এই সমাধানটি আসলে আমার বা গৃহীত উত্তরের চেয়ে নিরাপদ এবং ভবিষ্যতের প্রমাণ । আমি নিজে চেষ্টা করার বিষয়টি বিবেচনা করব।
স্টিভেন বাইলে

6
@ ডরি আমি এটি ভাঙ্গি না। আমার সমাধান 'getItem ()' কল থেকে ফলাফলটি ব্যবহার করছে না। পরিবর্তে, এটি 'ইনস্ট্যান্টিয়েট আইটেম ()' কল থেকে সঞ্চিত ফলাফল ব্যবহার করছে। এবং খণ্ডটির লাইফসাইকেলটি ভাঙা হয়নি, কারণ সঞ্চিত খণ্ডটি স্পষ্ট-অ্যারে থেকে 'ড্রেস্টআইটেম ()' কল-এ সরানো হবে।
বোস্টনের স্ট্রিটস

85

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

ব্যবহার করে FragmentPagerAdapterনিচে দেখুন। ব্যবহার যদি FragmentStatePagerAdapterতার মূল্য দিকে তাকিয়ে এই । ফ্রেগমেন্টস্টেটএডাপ্টারের বর্তমান নয় এমন সূচকগুলি গ্র্যাব করে দেওয়া প্রকৃতির দ্বারা এগুলি এতটা কার্যকর নয় যেগুলি এগুলি সম্পূর্ণরূপে ছিন্ন হয়ে যাবে স্ক্রিনলিমিট সীমানার বাইরে দেখা বা বাইরে।

অনিচ্ছুক পাঠ্য

ভুল: আপনার নিজের অভ্যন্তরের টুকরাগুলির তালিকা বজায় রাখুন, যখন FragmentPagerAdapter.getItem()তাকে ডাকা হয়

  • সাধারণত একটি SparseArrayবা ব্যবহার করেMap
  • আমি যে বহু উদাহরণ লাইফাইসাইকেলের ইভেন্ট দেখেছি তার মধ্যে একটিও নয় তাই এই সমাধানটি ভঙ্গুর। হিসাবে getItemশুধুমাত্র প্রথমবার একটি পৃষ্ঠাতে স্ক্রল বলা হয় (অথবা যদি প্রাপ্ত আপনার ViewPager.setOffscreenPageLimit(x)> 0) মধ্যে ViewPager, যদি হোস্টিং Activity/ Fragmentহত্যা অথবা পুনরায় আরম্ভ করা হয়েছে তারপর অভ্যন্তরীণ SpaseArrayসম্পুর্ন বিলুপ্ত করা হবে কাস্টম FragmentPagerActivity recreated হয়, কিন্তু লোকচক্ষুর অন্তরালে ভিউপ্যাজারগুলির অভ্যন্তরীণ খণ্ডগুলি পুনরায় তৈরি করা হবে, এবং কোনও সূচকের জন্য বলা getItemহবে না , সুতরাং সূচী থেকে কোনও খণ্ড পাওয়ার ক্ষমতা চিরতরে নষ্ট হয়ে যাবে। আপনি এর মাধ্যমে এই খণ্ডগুলির রেফারেন্সগুলি সংরক্ষণ এবং পুনরুদ্ধার করে এর জন্য অ্যাকাউন্ট করতে পারেন FragmentManager.getFragment()এবং এটি putFragmentঅগোছালো আইএমএইচও পেতে শুরু করে।

ভুল: হুডের নীচে যা ব্যবহৃত হয় তার সাথে মিলিয়ে নিজের ট্যাগ আইডিটি তৈরি করুনFragmentPagerAdapter এবং পৃষ্ঠা থেকে টুকরো পুনরুদ্ধার করতে এটি ব্যবহার করুনFragmentManager

  • এটি প্রথমত অভ্যন্তরীণ-অ্যারে সমাধানে হারা-টুকরা-রেফারেন্স সমস্যার সাথে কপিরাইট করার কারণে এটি আরও ভাল, তবে উপরের উত্তরগুলিতে এবং নেটটিতে ঠিক যেমনটি উল্লেখ করা হয়েছে - এটি হ্যাকিকে তার ব্যক্তিগত পদ্ধতি হিসাবে অভ্যন্তরীণ বলে ViewPagerমনে করে যে কোনও সময় বা যে কোনও ওএস সংস্করণে পরিবর্তন করুন।

এই সমাধানটির জন্য পুনরায় তৈরি করা পদ্ধতিটি

private static String makeFragmentName(int viewId, long id) {
    return "android:switcher:" + viewId + ":" + id;
}

একটি সুখী পথ: ViewPager.instantiateItem()

getItem()উপরের মতো একইরকম পদ্ধতির সাথে নন-লাইফসাইकल-ব্রেকিং হ'ল এর instantiateItem()পরিবর্তে হুক করা উচিত getItem()যেমন প্রাক্তনকে প্রতিবার বলা হবে যে সূচি তৈরি করা / অ্যাক্সেস করা হয়। এই উত্তর দেখুন

একটি সুখী পথ: আপনার নিজের তৈরি করুন FragmentViewPager

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

/**
 * @param containerViewId the ViewPager this adapter is being supplied to
 * @param id pass in getItemId(position) as this is whats used internally in this class
 * @return the tag used for this pages fragment
 */
public static String makeFragmentName(int containerViewId, long id) {
    return "android:switcher:" + containerViewId + ":" + id;
}

তারপরে ডক যেমনটি বলেছেন, আপনি যখন সূচকের জন্য ব্যবহৃত একটি টুকরোটি ধরতে চান ঠিক তখনই এই পদ্ধতির মতো কিছু কল করুন (যা আপনি কাস্টম FragmentPagerAdapterবা একটি সাবক্লাসে রাখতে পারেন) সচেতন হওয়ার ফলে ফলাফলটি বাতিল হতে পারে যদি এখনও আইটেমটি না চাওয়া হয় has পৃষ্ঠাটি এটি এখনও তৈরি করা হয়নি।

/**
 * @return may return null if the fragment has not been instantiated yet for that position - this depends on if the fragment has been viewed
 * yet OR is a sibling covered by {@link android.support.v4.view.ViewPager#setOffscreenPageLimit(int)}. Can use this to call methods on
 * the current positions fragment.
 */
public @Nullable Fragment getFragmentForPosition(int position)
{
    String tag = makeFragmentName(mViewPager.getId(), getItemId(position));
    Fragment fragment = getSupportFragmentManager().findFragmentByTag(tag);
    return fragment;
}

এটি একটি সহজ সমাধান এবং ওয়েবে যে কোনও জায়গায় পাওয়া অন্য দুটি সমাধানের সমস্যার সমাধান করে


6
এটি কাজ করবে, তবে এর জন্য ভিউপাগার ক্লাসটি আপনার নিজস্ব উত্স কোডে অনুলিপি করা দরকার। ভিউপ্যাজারের পেজার-অ্যাডাপ্টারের 'ইনস্ট্যান্টিয়েট আইটেম ()' এবং 'ডিস্টোন আইটেম ()' এর উপর নির্ভর করে কাজ করবে এবং টুকরো'র লাইফসাইকেলগুলিকে সম্মান জানাবে (এই 2 পদ্ধতিগুলি যখন সেভ-ইনস্ট্যান্স-স্টেট থেকে খণ্ডগুলি তৈরি করা হয় তখনও বলা হয়)। আপনি সঠিক, যে 'getItem ()' কল করা হচ্ছে তার উপর নির্ভর করা ভাল ধারণা নয় এবং ব্যক্তিগত API গুলি ব্যবহার করাও নয়।
বোস্টনের স্ট্রিটস

+1 আমি সম্মত হলাম এটিও একটি সমাধান এবং উপরে সম্পাদনা করা হয়েছে। পার্থক্যটি কেবল হ'ল উপরেরটি আরও একাধিক ব্যবহারের ক্ষেত্রে কাজ করে instantiateItem()যা আপনি যখন এমন একটি খণ্ডে অ্যাক্সেস করতে চান যা একটি লাইফসাইकल ইভেন্ট সংঘটিত হওয়ার পরে এখনও দেখা হয়নি এবং জীবনচক্র ইভেন্টের আগে দেখা হয়েছিল । একটি ছোট পার্থক্য আমি জানি তবে এটিই আমার প্রোগ্রামে একটি সূক্ষ্ম বাগের দিকে পরিচালিত করেছিল তাই আমাকে এটিকে তদন্ত করে দেখছে।
ডরি

যদি সেটঅফস্ক্রিনপেজলিমিট = 1 (ডিফল্ট) হয় তবে ফ্রেমমেন্টস্টেটপেজএডাপ্টার ভিউপেজ অ্যাক্সেস হওয়ার সাথে সাথে মেমরির ভিতরে এবং টুকরো টুকরো টুকরো শুরু করতে শুরু করবে। উইট আইটেমের কল () দ্বারা পুনর্বিবেচিত পৃষ্ঠাগুলি / খণ্ডগুলির একটি নতুন উদাহরণ তৈরি করা হবে। এই জাতীয় পুনর্বিবেচনার পরে, সিস্টেমটি নতুন তৈরির পরিবর্তে পূর্ববর্তী ঘটনাগুলি পুনরায় চালু করার নির্দেশ দেওয়ার কোনও উপায় আছে?
কার্ল

পৃষ্ঠার সীমাটির বাইরে থাকলে এটি একটি নতুন তৈরি করতে হবে - তবে সংরক্ষিত অবস্থায় চলে যাচ্ছে। যদি পুরনোদের কাছাকাছি রাখতে চান তবে আপনি পৃষ্ঠার সীমাটি বাড়িয়ে দিতে পারেন
ডোরি

@ ডরি এর getItemId(pos)অভ্যন্তর নেইFragmentStatePagerAdapter
জেমশিট ইস্কেন্দরভ

70

আপনার ফ্রেগমেন্টপেজার অ্যাডাপ্টারে পরবর্তী পদ্ধতি যুক্ত করুন:

public Fragment getActiveFragment(ViewPager container, int position) {
String name = makeFragmentName(container.getId(), position);
return  mFragmentManager.findFragmentByTag(name);
}

private static String makeFragmentName(int viewId, int index) {
    return "android:switcher:" + viewId + ":" + index;
}

getActiveFragment (0) এ কাজ করতে হবে।

দেখুন ভিউপাগার https://gist.github.com/jacek-marchwicki/d6320ba9a910c514424d এ কার্যকর করা সমাধান । কিছু ব্যর্থ হলে আপনি ভাল ক্র্যাশ লগ দেখতে পাবেন।


অনেক ধন্যবাদ:) . আমি এটিকে অন্য উপায়ে sovled করেছি যা আমি খণ্ডটি পোস্ট করার জন্য একটি হ্যান্ডলার ব্যবহার করি। এটি খুব উপযুক্ত নয় তবে শেষ পর্যন্ত সমস্যাটি প্রশমিত হয়েছে। যাইহোক, আপনি দুর্দান্ত :)
কুন কিন

12
আমি এই পদ্ধতিটি ব্যবহার করছিলাম তবে আমি বিশ্বাস করি যে আমি যখন এপিআই 17 (?) এ চলে এসেছি তখন এটি কাজ করা বন্ধ করে দিয়েছে। আমি অন্য একটি পদ্ধতির প্রস্তাব করব এবং এটি পছন্দ করব যদি গুগল ভিউপ্যাজারের অবস্থানের দিক থেকে কোনও খণ্ড পুনরুদ্ধার করার জন্য একটি API প্রকাশ করে।
gcl1

দ্বিতীয় খণ্ডকে কল করতে আমার সমস্যা আছে, পদ্ধতিটি একটি নতুন তৈরি করেছে
ভাসিল ভালচেভ

2
যেহেতু কিছু এপিআই সংস্করণ মেকফ্রেগমেন্টনাম পদ্ধতিটি বেসরকারী স্ট্যাটিক স্ট্রিং মেকফ্রেগমেন্টনাম (ইন ভিউআইডি, লম্বা আইডি) এ পরিবর্তিত হয়েছিল {রিটার্ন "অ্যান্ড্রয়েড: পরিবর্তনকারী:" + ভিউআইডি + ":" + আইডি; get সুতরাং getActiveFragment পদ্ধতিটি এখন দেখতে হবে (দ্বিতীয় যুক্তির জন্য পজিশনের পরিবর্তে getItemId ব্যবহার করুন) পাবলিক টুকরা getActiveFraament (ভিউপেজার ধারক, ইনট পজিশন) name স্ট্রিং নাম = MakeFragmentName (ধারক.জেটআইডি (), getItemId (অবস্থান)); রিটার্ন এমফ্রেগমেন্টম্যানেজ.ফাইন্ডফ্রেগমেন্টবিট্যাগ (নাম); }
ইউজিন পপোভিচ

1
এটি সত্যই কাজ করে তবে এটি সত্যই বিপজ্জনক কারণ এটি ভিউ পেজারের অভ্যন্তরীণ বাস্তবায়নের উপর নির্ভর করে এবং যদি গুগল বাস্তবায়ন পরিবর্তন করে (এবং তারা করতে পারে) খারাপ জিনিস ঘটবে। আমি সত্যিই আশা করি যে গোলে এটি লাইভ টুকরোটি উপলব্ধ করতে সক্ষম করবে
শেম

38

আর একটি সহজ সমাধান:

    public class MyPagerAdapter extends FragmentPagerAdapter {
        private Fragment mCurrentFragment;

        public Fragment getCurrentFragment() {
            return mCurrentFragment;
        }
//...    
        @Override
        public void setPrimaryItem(ViewGroup container, int position, Object object) {
            if (getCurrentFragment() != object) {
                mCurrentFragment = ((Fragment) object);
            }
            super.setPrimaryItem(container, position, object);
        }
    }

1
এটি আমার বর্তমান খণ্ডের প্রয়োজনের জন্য উপযুক্ত বলে মনে হচ্ছে।
danny117

আপনার যা করা দরকার তা যদি বর্তমানে নির্বাচিত টুকরোটি পেতে হয় তবে এটি আপনার প্রয়োজন - পদ্ধতি সেটপ্রাইমারি আইটেমটি সংযুক্তিতে সেট করা হয় এবং বর্তমান আইটেম হিসাবে ফ্রেগমেন্টের অভ্যন্তরীণ সেটটিতে প্রতিটি আপডেট করা হয়।
গ্রিমে

1
এটি একটি দুর্দান্ত সমাধান বলে মনে হচ্ছে তবে এটি ব্যবহার করার পরেsetPrimaryItem() বলা হয় ViewPager.OnPageChangeListener#onPageSelected() :-(
হার্ডিসিম

21

আমি জানি এর কয়েকটি উত্তর রয়েছে তবে সম্ভবত এটি কাউকে সহায়তা করবে। আমার যখন আমার Fragmentকাছ থেকে কোনও প্রয়োজন হয় তখন আমি তুলনামূলক সহজ সমাধান ব্যবহার করেছি ViewPager। আপনার Activityবা Fragmentহোল্ডিং-এ ViewPager, আপনি এই কোডটি Fragmentধরে রাখার প্রতিটি মাধ্যমে চক্রটি ব্যবহার করতে পারেন ।

FragmentPagerAdapter fragmentPagerAdapter = (FragmentPagerAdapter) mViewPager.getAdapter();
for(int i = 0; i < fragmentPagerAdapter.getCount(); i++) {
    Fragment viewPagerFragment = fragmentPagerAdapter.getItem(i);
    if(viewPagerFragment != null) {
        // Do something with your Fragment
        // Check viewPagerFragment.isResumed() if you intend on interacting with any views.
    }
}
  • আপনি আপনার অবস্থান জানেন তাহলে Fragmentমধ্যে ViewPager, আপনি শুধু কল করতে পারেন getItem(knownPosition)

  • আপনি আপনার অবস্থান জানা না থাকলে Fragmentমধ্যে ViewPager, আপনি আপনার সন্তানদের থাকতে পারে Fragmentsমত একটি পদ্ধতি সহ একটি ইন্টারফেস বাস্তবায়ন getUniqueId(), এবং ব্যবহার যে তাদের পার্থক্য। অথবা আপনি সকলের উপর চক্র করতে পারেন Fragmentsএবং ক্লাসের ধরণ যেমন পরীক্ষা করতে পারেনif(viewPagerFragment instanceof FragmentClassYouWant)

!!! সম্পাদনা করুন !!!

আমি আবিষ্কার করেছি যে getItemকেবলমাত্র একটি দ্বারা ডেকে আসে FragmentPagerAdapterযখন প্রত্যেককে প্রথমবারFragment তৈরি করা দরকার , এর পরে, এটি প্রদর্শিত হয় যেগুলি ব্যবহার করে পুনর্ব্যবহার করা হয় । এইভাবে, অনেকগুলি বাস্তবায়ন নতুন তৈরি করে । আমার উপরের পদ্ধতিটি ব্যবহার করে, এর অর্থ হ'ল আমরা সমস্ত সময় নতুন তৈরি করব যখন আমরা সমস্ত আইটেম দিয়ে যাব । এর কারণে, আমি প্রতিটি পরিবর্তে (গ্রহণযোগ্য উত্তর ব্যবহার করে) পাওয়ার জন্য আরও ভাল পদ্ধতির সন্ধান করেছি । এটি একটি আরও সম্পূর্ণ সমাধান, এবং আমার জন্য ভাল কাজ করে চলেছে।FragmentsFragmentManagerFragmentPagerAdapter FragmentgetItemFragmentgetItemFragmentPagerAdapterFragmentManagerFragment

FragmentPagerAdapter fragmentPagerAdapter = (FragmentPagerAdapter) mViewPager.getAdapter();
for(int i = 0; i < fragmentPagerAdapter.getCount(); i++) {
    String name = makeFragmentName(mViewPager.getId(), i);
    Fragment viewPagerFragment = getChildFragmentManager().findFragmentByTag(name);
    // OR Fragment viewPagerFragment = getFragmentManager().findFragmentByTag(name);
    if(viewPagerFragment != null) {

        // Do something with your Fragment
        if (viewPagerFragment.isResumed()) {
            // Interact with any views/data that must be alive
        }
        else {
            // Flag something for update later, when this viewPagerFragment
            // returns to onResume
        }
    }
}

এবং আপনার এই পদ্ধতিটি প্রয়োজন হবে।

private static String makeFragmentName(int viewId, int position) {
    return "android:switcher:" + viewId + ":" + position;
}

1
আপনি স্রেফ ফ্রেগমেন্টবাইটাগ () সন্ধান করেছেন, তবে আমরা কোথায় টুকরা দিয়ে ট্যাগটি সেট করতে পারলাম ??
ভিন্সস্টাইলিং

@ উইংস ViewPagerনিজেই এই ট্যাগগুলি সেট করে। এই সমাধানটি ভঙ্গুর কারণ এটি "লুকানো" নামকরণের সম্মেলনটি জানার উপর নির্ভর করে ViewPager। বোস্টনের উত্তরের স্ট্রিটস একটি আরও ব্যাপক সমাধান, যা আমি এখন আমার প্রকল্পে (এই পদ্ধতির পরিবর্তে) ব্যবহার করি।
স্টিভেন বাইলে

এটি দুর্দান্ত কাজ করে! তবে আমি "if (ভিউপেজারফ্রেগমেন্ট.আইস পুনরায় চালু ())" শর্তসাপেক্ষে সরিয়ে দিয়েছি কারণ আমার স্ক্রিনের বাইরে থাকা আমার তালিকাগুলি পৃষ্ঠা আপডেট করতে হবে। তারপরে ব্যবহারকারী তালিকাফ্র্যাগমেন্ট পাতায় ফিরে গেলে, এটি সমস্ত নতুন ডেটা দিয়ে আপডেট হয়।
জেডিজে

10

আমার ক্ষেত্রে, উপরের সমাধানগুলির কোনওটিই কার্যকর হয়নি।

তবে যেহেতু আমি একটি খণ্ডে শিশু খণ্ডের ব্যবস্থাপক ব্যবহার করছি, নিম্নলিখিতটি ব্যবহৃত হয়েছিল:

Fragment f = getChildFragmentManager().getFragments().get(viewPager.getCurrentItem());

এটি কেবল তখনই কাজ করবে যদি ম্যানেজারে আপনার খণ্ডগুলি ভিউপ্যাজার আইটেমের সাথে সম্পর্কিত হয়।


ক্রিয়াকলাপ বা খণ্ডটি পুনরায় তৈরি করা হলে ভিউ পেজার থেকে পুরানো টুকরো পাওয়ার সঠিক উত্তর এটি।
সুমিত

7

অর্ডার পেতে ViewPager থেকে বর্তমান দৃশ্যমান টুকরা । আমি এই সাধারণ বিবৃতিটি ব্যবহার করছি এবং এটি ভাল কাজ করছে।

      public Fragment getFragmentFromViewpager()  
      {
         return ((Fragment) (mAdapter.instantiateItem(mViewPager, mViewPager.getCurrentItem())));
      }

3

আমি প্রথমে List<Fragment> fragments;যে সমস্ত টুকরোগুলি ( ) ব্যবহার করতে যাচ্ছিলাম তার একটি তালিকা তৈরি করে এটি বর্তমানে পরিচালনা করেছি যাতে বর্তমানে প্রদর্শিত খণ্ডটি পরিচালনা করা সহজ করে তোলে making

তাই:

@Override
onCreate(){
    //initialise the list of fragments
    fragments = new Vector<Fragment>();

    //fill up the list with out fragments
    fragments.add(Fragment.instantiate(this, MainFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, MenuFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, StoresFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, AboutFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, ContactFragment.class.getName()));


    //Set up the pager
    pager = (ViewPager)findViewById(R.id.pager);
    pager.setAdapter(new MyFragmentPagerAdapter(getSupportFragmentManager(), fragments));
    pager.setOffscreenPageLimit(4);
}

সুতরাং এই বলা যেতে পারে:

public Fragment getFragment(ViewPager pager){   
    Fragment theFragment = fragments.get(pager.getCurrentItem());
    return theFragment;
}

সুতরাং আমি এটি একটি if বিবৃতিতে চক করতে পারি যা কেবলমাত্র যদি এটি সঠিক খণ্ডে থাকে তবে চলবে

Fragment tempFragment = getFragment();
if(tempFragment == MyFragmentNo2.class){
    MyFragmentNo2 theFrag = (MyFragmentNo2) tempFragment;
    //then you can do whatever with the fragment
    theFrag.costomFunction();
}

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


1
আমার জন্য সেরা উত্তর
সোনু কুমার

3

এটি উপরের স্টিভেনের উত্তরের ভিত্তিতে তৈরি। এটি খণ্ডটির প্রকৃত উদাহরণটি ফিরে আসবে যা ইতিমধ্যে পিতামাতার ক্রিয়াকলাপের সাথে সংযুক্ত।

FragmentPagerAdapter fragmentPagerAdapter = (FragmentPagerAdapter) mViewPager.getAdapter();
    for(int i = 0; i < fragmentPagerAdapter.getCount(); i++) {

        Fragment viewPagerFragment = (Fragment) mViewPager.getAdapter().instantiateItem(mViewPager, i);
        if(viewPagerFragment != null && viewPagerFragment.isAdded()) {

            if (viewPagerFragment instanceof FragmentOne){
                FragmentOne oneFragment = (FragmentOne) viewPagerFragment;
                if (oneFragment != null){
                    oneFragment.update(); // your custom method
                }
            } else if (viewPagerFragment instanceof FragmentTwo){
                FragmentTwo twoFragment = (FragmentTwo) viewPagerFragment;

                if (twoFragment != null){
                    twoFragment.update(); // your custom method
                }
            }
        }
    }

2

এটি করার জন্য আমি একটি সহজ, পরিষ্কার উপায় খুঁজে পাইনি। তবে ভিউপেজার উইজেটটি হ'ল অন্য ভিউগ্রুপ, যা আপনার খণ্ডগুলিকে হোস্ট করে। ভিউপ্যাজারে তাত্ক্ষণিক শিশু হিসাবে এই টুকরা রয়েছে। সুতরাং আপনি কেবল তাদের উপর পুনরাবৃত্তি করতে পারেন (.getChildCount () এবং .getChildAt () ব্যবহার করে এবং দেখুন যে খণ্ড খণ্ডটি আপনি সন্ধান করছেন সেটি বর্তমানে ভিউপাগারে লোড হয়েছে এবং এর একটি রেফারেন্স পেয়েছে কিনা। যেমন আপনি টুকরো টুকরো টুকরো টুকরো বলতে কিছু স্থির অনন্য আইডি ক্ষেত্র ব্যবহার করতে পারেন।

নোট করুন যে ভিউপ্যাজারটি আপনি যে খণ্ডটি সন্ধান করছেন তাতে লোড নাও থাকতে পারে কারণ এটি তালিকাভিউয়ের মতো ভার্চুয়ালাইজিং ধারক।


1
আপনার উত্তর দেওয়ার জন্য ধন্যবাদ, আমি এটি এডিটার.জেটআইটিম () দিয়ে পুনরুদ্ধার করি; আমি অ্যান্ড্রয়েড প্রোগ্রামিংয়ের একজন নতুন ব্যক্তি। সত্যিই আপনার অনেক প্রশংসা। এখন আমি লিস্টফ্র্যাগমেন্টটি পুনরুদ্ধার করতে পারি এবং আমি এতে ফুটারভিউ যুক্ত করতে চাই, যখন আমি আমার ক্রিয়াকলাপে এটি করি তখন লগক্যাট প্রিন্ট: "java.lang.IllegalStateException: সামগ্রী দৃশ্যটি এখনও তৈরি হয়নি" তৈরি হয়েছে। আমি জানি তবে কেন আমার সমস্যা হয় এর সাথে.
কুন কিন

1
ফ্র্যাগমেন্টএকটিভিটির অনাটচ্যাগমেন্ট () পদ্ধতি আছে, ভিউপাগার হুইট টুকরা বিষয়বস্তুর জন্য এই কাজটি কী?
ভাসিল ভালচেভ

2

ফ্র্যাগমেন্টপেজারএডাপ্টার খণ্ডগুলির কারখানা। এর অবস্থানের ভিত্তিতে কোনও খণ্ড খুঁজে পেতে যদি এখনও স্মৃতিতে থাকে তবে:

public Fragment findFragmentByPosition(int position) {
    FragmentPagerAdapter fragmentPagerAdapter = getFragmentPagerAdapter();
    return getSupportFragmentManager().findFragmentByTag(
            "android:switcher:" + getViewPager().getId() + ":"
                    + fragmentPagerAdapter.getItemId(position));
}

ভি 4 সাপোর্ট এপিআই এর জন্য নমুনা কোড।


এটি অন্রেসিউম () এ বাতিল হয়ে যাচ্ছে। কোন ধারণা কেন এবং কুড়ান এটি ঠিক করতে?
সীমা

2

আপনি না কলে প্রয়োজন getItem()বা পরবর্তী পর্যায়ে কিছু অন্যান্য পদ্ধতি এর রেফারেন্স পেতে Fragmentহোস্ট ভিতরে ViewPager। আপনি যদি কিছু তথ্য ভিতরে আপডেট করতে চান Fragmentতবে এই পদ্ধতির ব্যবহার করুন: ভিউপ্যাজারকে গতিশীলভাবে আপডেট করবেন?

কীটি হ'ল নতুন ডেটা সেট করা Adaperএবং কল করা notifyDataSetChanged()যা ঘুরে ফিরে কল করবে getItemPosition(), আপনাকে একটি রেফারেন্স দিবে Fragmentএবং আপনাকে আপডেট করার সুযোগ দেবে। অন্যান্য সমস্ত উপায়ে আপনার নিজের বা অন্য কোনও হ্যাকের রেফারেন্স রাখা দরকার যা একটি ভাল সমাধান নয়।

@Override
public int getItemPosition(Object object) {
    if (object instanceof UpdateableFragment) {
        ((UpdateableFragment) object).update(xyzData);
    }
    //don't return POSITION_NONE, avoid fragment recreation. 
    return super.getItemPosition(object);
}

আমি এখানে বুঝতে পারি না, getItemPosition () ব্যবহার করার জন্য আপনার একটি খণ্ডের একটি রেফারেন্স দরকার, সুতরাং আপনি পাশাপাশি getItemPosition ব্যবহার করবেন না, তাই না?

getItemPosition()আপনার অ্যাডাপ্টারের একটি পদ্ধতি। আপনি সরাসরি এটি কল করবেন না। আপনার কাছে আপনার অ্যাডাপ্টারের একটি রেফারেন্স রয়েছে তাই আপনি যে ফোন adapter.notifyDataSetChanged()করবেন তার পরিবর্তে getItemPosition()আপনার এসের রেফারেন্স পাস করে আপনার অ্যাডাপ্টারের কল হবে Fragment। আপনি ক্রিয়াটি একটি পূর্ণ বাস্তবায়ন এখানে দেখতে পারেন stackoverflow.com/questions/19891828/...
এম-WaJeEh

আমি এটি পড়েছি এবং আমি এখনও এটি পাই না। তাদের বিরুদ্ধে কল করার জন্য আপনার এখনও সেই খণ্ডগুলির সরাসরি রেফারেন্সের দরকার আছে, তাই না? আপনি এটি হ্যাক হিসাবে উল্লেখ করেছেন তবে আমি কোনও বিকল্প দেখতে পাচ্ছি না; অ্যাডাপ্টার.জেটআইটেম (i) স্পষ্টতই কাজ করছে না।

2
ঠিক আছে আমি আরও পরিষ্কার করার জন্য আমার উত্তর আপডেট করেছি। অবশ্যই একটি আপডেট করার জন্য একটি রেফারেন্স প্রয়োজন Fragmentতবে একটি রেফারেন্স কীভাবে পাওয়া যায় তা বিতর্ক-সক্ষম। অন্যান্য সমাধানগুলি FragmentManagerঅনুরূপ স্ট্রিং ব্যবহার করে "android:switcher:"+idবা সমস্ত খণ্ডকে পুনরায় তৈরি করার কারণ POSITION_NONEথেকে ফিরে আসা থেকে রেফারেন্স getItemosition()পায়।
এম-ওয়াজেইহ

ধন্যবাদ, এটি অনেক বেশি অর্থবোধ করে এবং আমার অভিজ্ঞতার সাথে মেলে (যাতে আমি কিছু ভুল করছি না, হ্যাঁ)।

2

FragmentPagerAdapterআপনার ভিউপেজার অ্যাডাপ্টার শ্রেণিতে অবশ্যই প্রসারিত হওয়া উচিত ।
আপনি যদি এটি ব্যবহার করেন FragmentStatePagerAdapterতবে আপনি Fragmentএটির দ্বারা তার সন্ধান করতে পারবেন নাID

public static String makeFragmentName(int viewPagerId, int index) {
  return "android:switcher:" + viewPagerId + ":" + index;
}

এই পদ্ধতিটি কীভাবে ব্যবহার করবেন: -

Fragment mFragment = ((FragmentActivity) getContext()).getSupportFragmentManager().findFragmentByTag(
       AppMethodUtils.makeFragmentName(mViewPager.getId(), i)
);
InterestViewFragment newFragment = (InterestViewFragment) mFragment;

2

আরে আমি এই প্রশ্নের উত্তর এখানে দিয়েছি । মূলত, আপনার ওভাররাইড করা দরকার

সর্বজনীন অবজেক্ট ইনস্ট্যান্টিয়েট আইটেম (ভিউ গ্রুপের ধারক, অন্তর্নিহিত অবস্থান)

ফ্র্যাগমেন্টস্টেটপেজারএডাপ্টারের পদ্ধতি।


1

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


0

সবচেয়ে সহজ এবং সবচেয়ে সংক্ষিপ্ত উপায়। যদি আপনার সমস্ত খণ্ডগুলি ViewPagerবিভিন্ন শ্রেণীর হয় তবে আপনি সেগুলি নিম্নলিখিত হিসাবে পুনরুদ্ধার করতে এবং আলাদা করতে পারেন:

public class MyActivity extends Activity
{

    @Override
    public void onAttachFragment(Fragment fragment) {
        super.onAttachFragment(fragment);
        if (fragment.getClass() == MyFragment.class) {
            mMyFragment = (MyFragment) fragment;
        }
    }

}

এটিও ভুল, কারণ এখানে ভিউপ্যাজার ব্যবহার করার সময় একাধিক টুকরো সংযুক্ত হয়ে যায়। বর্তমান পৃষ্ঠার খণ্ড রয়েছে এবং তার বামে একটি এবং তার ডানদিকে রয়েছে। এটি কেবলমাত্র ব্যবহারকারী যখন তাদের কাছে পৌঁছে তখন তাদের আরম্ভ না করেই তাদের মধ্যে স্লাইড করতে দেয়।
অ্যান্ড্রয়েড বিকাশকারী

0

আমি কিছুটা ভিন্ন পদ্ধতির সাহায্যে এটিকে সহজভাবে প্রয়োগ করেছি।

আমার কাস্টম ফ্রেগমেন্টএডাপ্টার.জেট আইটেম পদ্ধতিটি নতুন মাইফ্রেগমেন্ট () নয়, মাইফ্রেগমেন্টের উদাহরণটি ফ্রেগমেন্টএডাপ্টার কনস্ট্রাক্টরে তৈরি হয়েছিল।

আমার ক্রিয়াকলাপে আমি তখন অ্যাডাপ্টারের কাছ থেকে টুকরোটি পেয়েছি, এটি যদি প্রয়োজন ফ্রেমমেন্টের প্রয়োজন হয় কিনা তা পরীক্ষা করে দেখুন, তারপর কাস্ট করুন এবং প্রয়োজনীয় পদ্ধতিগুলি ব্যবহার করুন।


0

/Values/integers.xML এ পূর্ণসংখ্যার রিসোর্স আইডি তৈরি করুন

<integer name="page1">1</integer>
<integer name="page2">2</integer>
<integer name="page3">3</integer>

তারপরে পেজারআডাপ্টারে getItem ফাংশন:

public Fragment getItem(int position) {

        Fragment fragment = null;

        if (position == 0) {
            fragment = FragmentOne.newInstance();
            mViewPager.setTag(R.integer.page1,fragment);

        }
        else if (position == 1) {

            fragment = FragmentTwo.newInstance();
            mViewPager.setTag(R.integer.page2,fragment);

        } else if (position == 2) {

            fragment = FragmentThree.newInstance();
            mViewPager.setTag(R.integer.page3,fragment);

        }

        return fragment;
        }

তারপরে ক্রিয়াকলাপে খণ্ড রেফারেন্স পেতে এই ফাংশনটি লিখুন:

private Fragment getFragmentByPosition(int position) {
    Fragment fragment = null;

    switch (position) {
        case 0:
            fragment = (Fragment) mViewPager.getTag(R.integer.page1);
            break;

        case 1:

            fragment = (Fragment) mViewPager.getTag(R.integer.page2);
            break;

        case 2:
            fragment = (Fragment) mViewPager.getTag(R.integer.page3);
            break;
            }

            return fragment;
    }

উপরের ফাংশনটি কল করে খণ্ডের রেফারেন্স পান এবং তারপরে এটি আপনার কাস্টম টুকরোতে কাস্ট করুন:

Fragment fragment = getFragmentByPosition(position);

        if (fragment != null) {
                    FragmentOne fragmentOne = (FragmentOne) fragment;
                    }

0

টুকরা পরিচালক হিসাবে টুকরা পুনরাবৃত্তি সহজ উপায়। ভিউপ্যাজারটি সন্ধান করুন, এতে বিভাগ অবস্থান যুক্তি রয়েছে, পাবলিক স্ট্যাটিক প্লেসোল্ডারফ্র্যাগমেন্ট নিউ ইনস্ট্যান্স (ইন বিভাগ বিভাগ) রাখা হয়েছে

public PlaceholderFragment getFragmentByPosition(Integer pos){
    for(Fragment f:getChildFragmentManager().getFragments()){
        if(f.getId()==R.id.viewpager && f.getArguments().getInt("SECTNUM") - 1 == pos) {
            return (PlaceholderFragment) f;
        }
    }
    return null;
}

0

খণ্ডে

public int getArgument(){
   return mPage;
{
public void update(){

}

ফ্র্যাগমেন্টএকটিভিটিতে

List<Fragment> fragments = getSupportFragmentManager().getFragments();
for(Fragment f:fragments){
    if((f instanceof PageFragment)&&(!f.isDetached())){
          PageFragment pf = (PageFragment)f;   
          if(pf.getArgument()==pager.getCurrentItem())pf.update();
    }
}

0

ট্যাবলাইআউটে খণ্ডের জন্য একাধিক ট্যাব রয়েছে। আপনি খণ্ডটির সূচি ব্যবহার করে ট্যাগ দ্বারা খণ্ডটি পেতে পারেন।

প্রাক্তন জন্য। ফ্র্যাগমেন্ট 1 এর সূচকটি 0 হয়, সুতরাং findFragmentByTag()পদ্ধতিতে, খণ্ডের ব্যবহারের পরে ভিউপেজ.আর.এর জন্য ট্যাগটি ট্রান্সজিট করুন যা আপনি যোগ করতে পারেন, খণ্ডটি প্রতিস্থাপন করতে পারেন।

String tag = "android:switcher:" + R.id.viewPager + ":" + 0; Fragment1 f = (Fragment1) getSupportFragmentManager().findFragmentByTag(tag);


-1

অ্যাডাপ্টারের জন্য ঠিক আছে FragmentStatePagerAdapterআমি একটি সমাধান তহবিল:

আপনার টুকরা ক্রিয়াকলাপ:

ActionBar mActionBar = getSupportActionBar(); 
mActionBar.addTab(mActionBar.newTab().setText("TAB1").setTabListener(this).setTag(Fragment.instantiate(this, MyFragment1.class.getName())));
mActionBar.addTab(mActionBar.newTab().setText("TAB2").setTabListener(this).setTag(Fragment.instantiate(this, MyFragment2.class.getName())));
mActionBar.addTab(mActionBar.newTab().setText("TAB3").setTabListener(this).setTag(Fragment.instantiate(this, MyFragment3.class.getName())));

viewPager = (STViewPager) super.findViewById(R.id.viewpager);
mPagerAdapter = new MyPagerAdapter(getSupportFragmentManager(), mActionBar);
viewPager.setAdapter(this.mPagerAdapter);

এবং আপনার ক্লাসে একটি মিথোড তৈরি করুন ফ্রেগমেন্টএকটিভিটি - সুতরাং সেই পদ্ধতিটি আপনাকে আপনার খণ্ডে অ্যাক্সেস দেয়, আপনার কেবল খণ্ডটির যে অবস্থানটি চান তা আপনাকে দেওয়া উচিত:

public Fragment getActiveFragment(int position) {
String name = MyPagerAdapter.makeFragmentName(position);
return getSupportFragmentManager().findFragmentByTag(name);
}

আপনার অ্যাডাপ্টারে:

public class MyPagerAdapter extends FragmentStatePagerAdapter {

private final ActionBar actionBar;
private final FragmentManager fragmentManager;

public MyPagerAdapter(FragmentManager fragmentManager, com.actionbarsherlock.app.ActionBarActionBar mActionBar) {super(fragmentManager);
this.actionBar = mActionBar;
this.fragmentManager = fragmentManager;
}

@Override
public Fragment getItem(int position) {
getSupportFragmentManager().beginTransaction().add(mTchatDetailsFragment, makeFragmentName(position)).commit();
return (Fragment)this.actionBar.getTabAt(position);
}

@Override
public int getCount() {
return this.actionBar.getTabCount();
}

@Override
public CharSequence getPageTitle(int position) {
return this.actionBar.getTabAt(position).getText();
}

private static String makeFragmentName(int viewId, int index) {
return "android:fragment:" + index;
}

}

-1
Fragment yourFragment = yourviewpageradapter.getItem(int index);

indexআপনি অ্যাডাপ্টারে খণ্ডের জায়গা যেমন আপনি fragment1প্রথমে 0 হিসাবে retreive fragment1পাস যোগ indexএবং তাই বিশ্রাম জন্য

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