android - ViewPager এ Fragment দৃশ্যমান হয়ে যায় যখন নির্ধারণ করুন




android-fragments android-viewpager (14)

ViewPager এ Fragment দৃশ্যমান হয়ে যায় যখন নির্ধারণ করুন

আপনি আপনার Fragment মধ্যে setUserVisibleHint overriding নিম্নলিখিতটি করতে পারেন:

public class MyFragment extends Fragment {
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isVisibleToUser) {
        }
        else {
        }
    }
}

সমস্যা: খণ্ডটি আসলে দৃশ্যমান হয়ে যাওয়ার আগে onResume() ফ্র্যাগমেন্ট onResume()

উদাহরণস্বরূপ, আমার কাছে ViewPager এবং FragmentPagerAdapter 2 FragmentPagerAdapter । দ্বিতীয় টুকরা শুধুমাত্র অনুমোদিত ব্যবহারকারীদের জন্য উপলব্ধ এবং আমি যখন ব্যবহারকারীর ভঙ্গি দৃশ্যমান হয়ে যায় তখন লগ ইন করতে ব্যবহারকারীকে জিজ্ঞাসা করতে হবে (সতর্কতা সংলাপ ব্যবহার করে)।

কিন্তু দ্বিতীয় অংশটি ক্যাশে করার জন্য ভিউপ্যাজার দ্বিতীয় অংশটি তৈরি করে এবং যখন ব্যবহারকারীটি সোয়াইপিং শুরু করে তখন এটি দৃশ্যমান হয়।

সুতরাং onResume() ইভেন্টটিকে দৃশ্যমান হওয়ার আগে দীর্ঘদিনের দ্বিতীয় অংশে বহিস্কার করা হয়। সেইজন্যই আমি এমন একটি ইভেন্ট খুঁজে বের করার চেষ্টা করছি যা দ্বিতীয় পর্যায়ে উপযুক্ত মুহূর্তে একটি কথোপকথন দেখানোর জন্য দৃশ্যমান হবে।

কিভাবে এই কাজ করা যেতে পারে?


আমাদের কাছে এমভিপি-এর সাথে একটি বিশেষ কেস রয়েছে যেখানে অংশটি দৃশ্যমান হয়ে উঠেছে এমন উপস্থাপককে অবহিত করা প্রয়োজন এবং উপস্থাপককে fragment.onAttach() ডাগার দ্বারা ইনজেকশনের দরকার হয়।

setUserVisibleHint() যথেষ্ট নয়, আমরা সনাক্ত করা হয়েছে এমন 3 টি ভিন্ন ক্ষেত্রে সনাক্ত করেছি ( onAttach() এ উল্লেখ করা হয়েছে যে উপস্থাপক কখন পাওয়া যায় তা আপনি জানেন):

  1. Fragment শুধু তৈরি করা হয়েছে। সিস্টেম নিম্নলিখিত কল করে তোলে:

    setUserVisibleHint() // before fragment's lifecycle calls, so presenter is null
    onAttach()
    ...
    onResume()
  2. ফ্র্যাগমেন্ট ইতিমধ্যে তৈরি এবং হোম বাটন চাপানো হয়। ফোরগ্রাউন্ডে অ্যাপ্লিকেশন পুনরুদ্ধার করার সময়, এটি বলা হয়:

    onResume()
  3. অভিযোজন পরিবর্তন:

    onAttach() // presenter available
    onResume()
    setUserVisibleHint()

আমরা কেবল উপস্থাপকের কাছে একবার দৃশ্যমানতার ইঙ্গিত চাই, তাই আমরা এটি করি:

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View root = inflater.inflate(R.layout.fragment_list, container, false);
    setHasOptionsMenu(true);

    if (savedInstanceState != null) {
        lastOrientation = savedInstanceState.getInt(STATE_LAST_ORIENTATION,
              getResources().getConfiguration().orientation);
    } else {
        lastOrientation = getResources().getConfiguration().orientation;
    }

    return root;
}

@Override
public void onResume() {
    super.onResume();
    presenter.onResume();

    int orientation = getResources().getConfiguration().orientation;
    if (orientation == lastOrientation) {
        if (getUserVisibleHint()) {
            presenter.onViewBecomesVisible();
        }
    }
    lastOrientation = orientation;
}

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (presenter != null && isResumed() && isVisibleToUser) {
        presenter.onViewBecomesVisible();
    }
}

@Override public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt(STATE_LAST_ORIENTATION, lastOrientation);
}

আমি এই ব্যবহার এবং এটা কাজ!

mContext.getWindow().getDecorView().isShown() //boolean

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

সুতরাং এই দুটি পদ্ধতিগুলি একটি সমস্যার সমাধান হিসাবে বিশেষভাবে ছোট এবং ছোট কাজগুলির জন্য ব্যবহার করা যেতে পারে।

আমি মনে করি, এটি ভাল সমাধান কিন্তু সর্বোত্তম নয়। আমি এই ব্যবহার করব কিন্তু একই সময়ে ভাল সমাধানের জন্য অপেক্ষা করব।

শুভেচ্ছা।


উল্লেখ্য যে setUserVisibleHint(false) ক্রিয়াকলাপ / setUserVisibleHint(false) বলা হয় না। আপনি এখনও শ্রোতা / ইত্যাদি সঠিকভাবে register/unregister শুরু / স্টপ চেক করতে হবে।

এছাড়াও, আপনি সেট setUserVisibleHint(false) যদি আপনার বিভাজন একটি দৃশ্যমান অবস্থায় শুরু হয়; আপনি যে ক্ষেত্রে আগে নিবন্ধন না করেছি, আপনি সেখানে unregister করতে চান না।

@Override
public void onStart() {
    super.onStart();

    if (getUserVisibleHint()) {
        // register
    }
}

@Override
public void onStop() {
    if (getUserVisibleHint()) {
        // unregister
    }

    super.onStop();
}

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);

    if (isVisibleToUser && isResumed()) {
        // register

        if (!mHasBeenVisible) {
            mHasBeenVisible = true;
        }
    } else if (mHasBeenVisible){
        // unregister
    }
}

এটি চেষ্টা করুন, এটি আমার জন্য কাজ:

@Override
public void onHiddenChanged(boolean hidden) {
        super.onHiddenChanged(hidden);

        if (hidden) {

        }else
        {}
    }

ওভাররাইড Fragment.onHiddenChanged() অনহাইড Fragment.onHiddenChanged() জন্য।

public void onHiddenChanged(boolean hidden)

যখন লুকানো অবস্থায় বলা হয় (যেমনটি isHidden() দ্বারা ফেরত দেওয়া হয় isHidden() পরিবর্তিত হয়েছে। Fragments লুকানো আউট শুরু আউট; যখনই টুকরো টুকরো টুকরো হয়ে যায় তখনই বলা হবে।

পরামিতি
hidden - boolean : যদি খণ্ডটি এখন লুকানো থাকে তবে সত্যই যদি এটি দৃশ্যমান না হয়।


পেজ onPageChangeListener ব্যবহার করে আরেকটি উপায় এখানে রয়েছে:

  ViewPager pager = (ViewPager) findByViewId(R.id.viewpager);
  FragmentPagerAdapter adapter = new FragmentPageAdapter(getFragmentManager);
  pager.setAdapter(adapter);
  pager.setOnPageChangeListener(new OnPageChangeListener() {

  public void onPageSelected(int pageNumber) {
    // Just define a callback method in your fragment and call it like this! 
    adapter.getItem(pageNumber).imVisible();

  }

  public void onPageScrolled(int arg0, float arg1, int arg2) {
    // TODO Auto-generated method stub

  }

  public void onPageScrollStateChanged(int arg0) {
    // TODO Auto-generated method stub

  }
});

ভঙ্গুর ভিতরে নিম্নলিখিত কোড যোগ করুন

@Override
public void setMenuVisibility(final boolean visible) 
 {
    super.setMenuVisibility(visible);
    if (visible && isResumed()) 
     {

     }
}

এখানে আরেকটি সমাধান এখানে পোস্ট করা হয়েছে PrrimaryItem প্যারিসডাপ্টারে ক্রিস লারসন প্রায় আমার জন্য কাজ করেছেন। কিন্তু এই পদ্ধতি প্রতিটি সেটআপ জন্য একাধিক বার বলা হয়। এছাড়াও আমি NPE থেকে ভিউ, NPE ইত্যাদি পেয়েছি কারণ এটি এই পদ্ধতির জন্য প্রস্তুত নয়, এই পদ্ধতিটি প্রথম কয়েক বার প্রস্তুত নয়। নিম্নলিখিত পরিবর্তনের সাথে এটি আমার জন্য কাজ করেছে:

private int mCurrentPosition = -1;

@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
    super.setPrimaryItem(container, position, object);

    if (position == mCurrentPosition) {
        return;
    }

    if (object instanceof MyWhizBangFragment) {
        MyWhizBangFragment fragment = (MyWhizBangFragment) object;

        if (fragment.isResumed()) {
            mCurrentPosition = position;
            fragment.doTheThingYouNeedToDoOnBecomingVisible();
        }
    }
}

FragmentStatePagerAdapters এবং 3 টি ট্যাবগুলির সাথে কাজ করার সময় আমি একই সমস্যার সম্মুখীন হয়েছি। যখনই প্রথম ট্যাবটি ক্লিক করা হয়েছিল এবং অন্য ট্যাব ক্লিক করার জন্য এটি লুকাতে হয়েছিল তখন আমাকে একটি ডিলগ দেখাতে হয়েছিল।

setUserVisibleHint() একা বর্তমান দৃশ্যমান টুকরা খুঁজে পেতে সাহায্য করে নি।

3 য় ট্যাব থেকে ক্লিক করলে -----> প্রথম ট্যাব। এটি দ্বিতীয় ফ্র্যাগমেন্টের জন্য এবং প্রথম খণ্ডের জন্য দ্বিগুণ। আমি itResumed () পদ্ধতির সাথে মিলিত।

    @Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    isVisible = isVisibleToUser;

    // Make sure that fragment is currently visible
    if (!isVisible && isResumed()) {
        // Call code when Fragment not visible
    } else if (isVisible && isResumed()) {
       // Call code when Fragment becomes visible.
    }

}

setUserVisibleHint() কখনও কখনও setUserVisibleHint() আগে বলা হয় এবং কখনও কখনও এটি সমস্যার কারণ করে।

এটিকে অতিক্রম করতে আপনাকে isResumed() পাশাপাশি setUserVisibleHint() পদ্ধতিটি চেক করতে হবে। কিন্তু এই ক্ষেত্রে আমি বুঝতে পেরেছি সেট setUserVisibleHint() ফ্র্যাগমেন্টটি পুনরায় শুরু এবং দৃশ্যমান হলেই তৈরি হবে, যখন তৈরি হবে না।

তাই ফ্র্যাগমেন্টটি visible হলে আপনি কিছু আপডেট করতে চান, তবে আপনার আপডেট ফাংশন উভয় setUserVisibleHint() এবং setUserVisibleHint() :

@Override
public View onCreateView(...){
    ...
    myUIUpdate();
    ...        
}
  ....
@Override
public void setUserVisibleHint(boolean visible){
    super.setUserVisibleHint(visible);
    if (visible && isResumed()){
        myUIUpdate();
    }
}

আপডেট: এখনও আমি বুঝতে পারলাম আমার myUIUpdate() কখনও কখনও দুবার কল করে, কারণ, যদি আপনার 3 টি ট্যাব থাকে এবং এই কোডটি দ্বিতীয় ট্যাবে থাকে তবে আপনি প্রথম ট্যাবটি খোলেন তবে দ্বিতীয় ট্যাবটি তৈরি হয় এমনকি এটি দৃশ্যমান নয় এবং myUIUpdate() বলা হয়। তারপরে যখন আপনি দ্বিতীয় ট্যাবে myUIUpdate() , তখন myUIUpdate() থেকে if (visible && isResumed()) বলা হয় এবং ফলস্বরূপ, myUIUpdate() একটি সেকেন্ডে দুইবার কল করা যেতে পারে।

অন্য সমস্যাটি হল সেট setUserVisibleHint !visible setUserVisibleHint উভয়কে 1) যখন আপনি ফ্র্যাগমেন্ট স্ক্রীন থেকে বের হয়ে যান এবং 2) এটি তৈরি হওয়ার আগে, যখন আপনি প্রথমবার ফ্রেগমেন্ট স্ক্রীনে স্যুইচ করেন।

সমাধান:

private boolean fragmentResume=false;
private boolean fragmentVisible=false;
private boolean fragmentOnCreated=false;
...

@Override
public View onCreateView(...){
    ...
    //Initialize variables
    if (!fragmentResume && fragmentVisible){   //only when first time fragment is created
        myUIUpdate();
    }
    ...        
}

@Override
public void setUserVisibleHint(boolean visible){
    super.setUserVisibleHint(visible);
    if (visible && isResumed()){   // only at fragment screen is resumed
        fragmentResume=true;
        fragmentVisible=false;
        fragmentOnCreated=true;
        myUIUpdate();
    }else  if (visible){        // only at fragment onCreated
        fragmentResume=false;
        fragmentVisible=true;
        fragmentOnCreated=true;
    }
    else if(!visible && fragmentOnCreated){// only when you go out of fragment screen
        fragmentVisible=false;
        fragmentResume=false;
    }
}

ব্যাখ্যা:

fragmentResume myUIUpdate() , fragmentVisible myUIUpdate() : নিশ্চিত করুন যে myUIUpdate() তে myUIUpdate() কেবল তখনই বলা হয় যখন ফ্র্যাগমেন্ট তৈরি এবং দৃশ্যমান হয়, পুনরায় চালু না হয়। যখন আপনি 1 ম ট্যাবে থাকবেন তখন এটি সমস্যার সমাধান করে, দ্বিতীয় ট্যাবটি দৃশ্যমান না হলেও এটি তৈরি হয়। এটি সমাধান করে এবং যখন onCreate স্ক্রীন দৃশ্যমান হয় তখন চেক করে।

fragmentOnCreated : টুকরো টুকরা দৃশ্যমান নয় তা নিশ্চিত করে এবং আপনি যখন ফ্র্যাগমেন্টটি প্রথমবার তৈরি করেন তখন বলা হয় না। তাই এখন যদি আপনি ফাঁকা আউট স্যুইপ যখন শুধুমাত্র ধারা আহ্বান করা হয়।

হালনাগাদ আপনি এই কোডটি BaseFragment কোডের মতো এই এবং BaseFragment ওভাররাইড করতে পারেন


focused view দ্বারা সনাক্ত করা!

এটা আমার জন্য কাজ করে

public static boolean isFragmentVisible(Fragment fragment) {
    Activity activity = fragment.getActivity();
    View focusedView = fragment.getView().findFocus();
    return activity != null
            && focusedView != null
            && focusedView == activity.getWindow().getDecorView().findFocus();
}

আপডেট : অ্যান্ড্রয়েড সাপোর্ট লাইব্রেরী (রিভিউ 11) অবশেষে ব্যবহারকারীর দৃশ্যমান ইঙ্গিত সমস্যাটি স্থির করেছে , এখন যদি আপনি টুকরাগুলির জন্য সহায়তা লাইব্রেরী ব্যবহার করেন তবে আপনি gorn এর উত্তর অনুসারে বর্ণিত পরিবর্তনগুলি পেতে getUserVisibleHint() অথবা override setUserVisibleHint() করতে পারেন।

আপডেট 1 এখানে getUserVisibleHint() সহ একটি ছোট সমস্যা। এই মান ডিফল্ট true

// Hint provided by the app that this fragment is currently visible to the user.
boolean mUserVisibleHint = true;

setUserVisibleHint() নামক হওয়ার আগে এটি ব্যবহার করার সময় এটি একটি সমস্যা হতে পারে। একটি workaround হিসাবে আপনি এই মত onCreate পদ্ধতিতে মান সেট করতে পারে।

public void onCreate(@Nullable Bundle savedInstanceState) {
    setUserVisibleHint(false);

পুরনো উত্তর:

বেশিরভাগ ব্যবহারের ক্ষেত্রে, ViewPager শুধুমাত্র একবারে একটি পৃষ্ঠা দেখায়, তবে যদি আপনি Android Support Library pre-r11 FragmentStatePagerAdapter ব্যবহার করেন তবে প্রাক-ক্যাশেড টুকরাগুলি "দৃশ্যমান" অবস্থায় (আসলে অদৃশ্য) Android Support Library pre-r11

আমি override:

public class MyFragment extends Fragment {
    @Override
    public void setMenuVisibility(final boolean visible) {
        super.setMenuVisibility(visible);
        if (visible) {
            // ...
        }
    }
   // ...
}

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







android-viewpager