103

私のViewPagerインスタンスで使用するフラグメントは非常にリソースを大量に消費するため、一度に1つだけロードしたいと思います。私が次のことを試してみると:

mViewPager.setOffscreenPageLimit(0);
mViewPager.setAdapter(mPagerAdapter);

私のFragmentStatePagerAdapter.getItem(int position)オーバーライド関数は3回呼び出されます。これは、を呼び出すと発生しますmViewPager.setOffscreenPageLimit(1)。オフスクリーンページを0と指定したので、一度だけ呼び出されると思います。

私はすべてを正しく呼んでいると思います。なぜなら、私が呼んだ場合mViewPager.setOffscreenPageLimit(2)FragmentStatePagerAdapter.getItem(int position)私が期待するように5回呼び出されるからです。

ViewPagerには少なくとも1つのオフスクリーンページが必要ですか、それともここで何か間違ったことをしていますか?

4

13 に答える 13

126

私が見つけた最良の方法は、setUserVisibleHint
をフラグメントに追加することでした

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
        // load data here
    }else{
       // fragment is no longer visible
    }
}
于 2014-09-04T23:08:35.777 に答える
117

ViewPagerには少なくとも1つのオフスクリーンページが必要ですか?

はい。ソースコードを正しく読んでいると、LogCatで次のような警告が表示されるはずです。

Requested offscreen page limit 0 too small; defaulting to 1
于 2012-04-09T13:27:29.743 に答える
9

あなたはこのように試すことができます:

public abstract class LazyFragment extends Fragment {
    protected boolean isVisible;
    /**
     * 在这里实现Fragment数据的缓加载.
     * @param isVisibleToUser
     */
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if(getUserVisibleHint()) {
            isVisible = true;
            onVisible();
        } else {
            isVisible = false;
            onInvisible();
        }
    }
    protected void onVisible(){
        lazyLoad();
    }
    protected abstract void lazyLoad();
    protected void onInvisible(){}

protected abstract void lazyLoad();
protected void onInvisible(){}
于 2015-06-20T01:47:03.817 に答える
7

最初に追加

   boolean isFragmentLoaded = false;

よりも

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser && !isFragmentLoaded) {
        //Load Your Data Here like.... new GetContacts().execute();

        isFragmentLoaded = true;
    }
else{
     }
}
于 2015-09-23T05:30:22.360 に答える
2

これは古いスレッドかもしれませんが、これは私にとってはうまくいくようです。この関数をオーバーライドします:

@Override
public void setMenuVisibility(boolean menuVisible) { 
    super.setMenuVisibility(menuVisible);

    if ( menuVisible ) {
        /**
         * Load your stuffs here.
         */
    } else  { 
        /**
         * Fragment not currently Visible.
         */
    } 
}

幸せなコーディング...

于 2014-12-09T01:27:44.377 に答える
2

ViewPagerは、setOffscreenPageLimit(0)で変更できない次のページ(フラグメント)をロードするデフォルトです。しかし、あなたはハッキングするために何かをすることができます。ViewPagerを含むActivityにonPageSelected関数を実装できます。次のフラグメント(ロードしたくない)では、関数を記述します。たとえば、showViewContent()を記述します。この関数では、リソースを消費するすべてのinitコードを挿入し、onResume()メソッドの前に何もしません。次に、onPageSelected内でshowViewContent()関数を呼び出します。これがお役に立てば幸いです。

于 2015-05-23T08:47:11.170 に答える
2

私の場合、ビューでいくつかのアニメーションを開始したかったのですが、setUserVisibleHintでいくつかの問題が発生しました...
私の解決策は:

1 /アダプタのaddOnPageChangeListener:

mViewPager.addOnPageChangeListener(this);

2 / OnPageChangeListenerを実装します:

public class PagesFragment extends Fragment implements ViewPager.OnPageChangeListener

3 / 3つのメソッドをオーバーライドします:

@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
{

}

@Override
public void onPageSelected(int position)
{ 
}

@Override
public void onPageScrollStateChanged(int state)
{
}

4/クラスでこの変数を宣言して初期化します

private static int mTabState = 1;

注意:アダプターに3つのフラグメントがあり、setCurrentItemとアダプターの現在の位置にmTabStateを使用して、時間内にユーザーに表示されるフラグメントを認識します... 5 / onPageSelectedメソッドでこのコードを追加します:

if (mTabState == 0 || position == 0)
    {
        Intent intent = new Intent("animation");
        intent.putExtra("current_position", position);
        LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
    }

前のページまたは現在のページがページ0(位置0のフラグメント)の場合は、この処理を実行します

6 /フラグメントクラス(アダプタの位置0のフラグメント)で、ブロードキャストレシーバーを作成し、onResumeメソッドに登録して、onPauseメソッドの登録を解除する必要があります。

BroadcastReceiver broadcastReceiver = new BroadcastReceiver()
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        if (Objects.equals(intent.getAction(), "animation"))
        {
            int currentPosition = intent.getIntExtra("current_position", 0);
            if (currentPosition == 0)
            {
                startAnimation();
                setViewsVisible();
            } else
            {
                setViewsInvisible();
            }
        }
    }
};

@Override
public void onResume()
{
    super.onResume();
    LocalBroadcastManager.getInstance(mContext).registerReceiver(broadcastReceiver, new IntentFilter("animation"));
}

@Override
public void onPause()
{
    super.onPause();
    LocalBroadcastManager.getInstance(mContext).unregisterReceiver(broadcastReceiver);
}

要約:フラグメントページャーアダプターの魔女が3つのフラグメントを表示しているので、アダプターの位置0にあるフラグメントのビューにアニメーションを表示したいのですが、このためにBroadcastReceiverを使用します。フラグメントが選択されている場合、アニメーションメソッドを開始してビューをユーザーに表示します。フラグメントがユーザーに表示されていない場合は、ビューを非表示にしようとします。

于 2018-09-24T11:54:05.657 に答える
1

Viewpagerでのビューの更新の問題を解決するには、このコードを試してください。

/* DO NOT FORGET! The ViewPager requires at least “1” minimum OffscreenPageLimit */
int limit = (mAdapter.getCount() > 1 ? mAdapter.getCount() - 1 : 1);
mViewPager.setOffscreenPageLimit(limit);
于 2019-06-03T06:28:15.713 に答える
1

ページが1つしかないポケットベルの表示:

これは2021年です-2月、Alhamdulillah、viewPagerで1ページしか追加できませんでした。アプローチは: ViewPager、、、、FragmentPagerAdapterおよびTablayoutですfragment。私の場合、多くの人Pagesに多くのtabsPageを住まわせることができTabます。1つのタブと1つのページを左または右にスワイプすると、ドキュメントの章を変更できます(次に表示したい)。そして、多くのページと多くのタブがあるとき、私はドキュメントの本全体を変更することができます。

メインのアクティビティOncreate:(これが私の作業コードのアプローチです。ここでは私の作業コードから何も変更していません):

if(getIntent()!=null){
            if(getIntent().getStringExtra("ONLY_TAFHEEM")!=null)
             sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager(), suraName, suraId, ayatId, true);
            else
            sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager(), suraName, suraId, ayatId, false);
        }else {
            sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager(), suraName, suraId, ayatId, false);
        }

        final ViewPager viewPager = findViewById(R.id.view_pager);
        viewPager.setAdapter(sectionsPagerAdapter);
        tabsLayout = findViewById(R.id.tabs);
        tabsLayout.animate();

        tabsLayout.setupWithViewPager(viewPager);

アダプター内:

 @NonNull
    @Override
    public Fragment getItem(int position) {

          
    // getItem is called to instantiate the fragment for the given page.
    // Return a PlaceholderFragment (defined as a static inner class below).
    return PlaceholderFragment.sendData(mContext, postion, suraName, suraId, ayahId, ARABIC_AYAH, BENGALI_AYAH, actualDbNames[position], tafsirDisplayNames[position]);
}


@Nullable
@Override
public CharSequence getPageTitle(int position) {
   
    return tafsirDisplayNames[position];
}

@Override
public int getCount() {
   // this is the tricky part // Show pages according to array length. // this may only one // this is the tricky part : 
    return tafsirDisplayNames.length;
}

そしてついにフラグメントパブリックコンストラクター:

 public static PlaceholderFragment sendData(Context mContext, int tabIndex, String suraName, String suraId, String ayahNumber, String arabicAyah, String bengaliAyah, String actualDbName, String displayDbName) {

        Log.i("PlaceHolder", "Tafhim sendData: " + bengaliAyah);
        PlaceholderFragment fragment = new PlaceholderFragment();
        Bundle bundle = new Bundle();
        mContext_ = mContext;
        BENGALI_AYAH = bengaliAyah;
        _DISPLAY_DB_NAME = displayDbName;
        bundle.putInt(ARG_SECTION_NUMBER, tabIndex);
        bundle.putString(SURA_NAME, suraName);
        bundle.putString(SURA_ID, suraId);
        bundle.putString(AYAH_NUMBER, ayahNumber);
        bundle.putString(ARABIC_AYAH, arabicAyah);
        bundle.putString(ACTUAL_DB_NAME, actualDbName);
        bundle.putString(DISPLAY_DB_NAME, displayDbName);
        fragment.setArguments(bundle);
        return fragment;
    }

以上で、(タブラベルの)配列をアダプターに渡すだけで(1ページの場合は1つの要素のみになる可能性があります)、必要に応じて1ページ以上を入力できます。これに応じて入力します。 1つのタブまたは複数のタブ:上記のコードでは、配列は:tafsirDisplayNamesです。アダプターが最初に呼び出されたときに、アダプターで配列を手動で作成することもできます。または、MainActivityを再作成するときに、+要素を使用して配列を再作成します。

それ、すべて、アルハムドゥリッラー、ハッピーコーディング.......。

于 2021-02-13T15:51:47.983 に答える
0

「instantiateItem」関数の場合は、フラグメントを準備するだけですが、重いコンテンツはロードしないでください。

「onPageChangeListener」を使用して、特定のページに移動するたびに、その重いコンテンツをロードして表示するようにします。

于 2014-07-06T12:41:12.777 に答える
0

私も同じ問題を抱えています。このサイトで便利なコードを見つけて変換しました。

mViewPager.setOffscreenPageLimit(...);の最小整数 は1なので、0に変更しても、2ページが読み込まれます。

最初に行うことは、静的intを作成し、maxPageCountを呼び出し、FragmentStatePagerAdapterメソッドgetCount()をオーバーライドしてmaxPageCountを返すことです。

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

次に、このmaxCountを変更できるようにするプログラム内の任意の場所からアクセス可能な静的メソッドを作成します。

public static void addPage(){
    maxPageCount++; //or maxPageCount = fragmentPosition+2
    mFragmentStatePagerAdapter.notifyDataSetChanged(); //notifyDataSetChanged is important here.
}

次に、maxPageCountを1に初期化します。必要に応じて、別のページを追加できます。私の場合、他のページを生成する前に、ユーザーが最初に現在のページを処理する必要がありました。彼はそれを行い、問題なく次のページにスワイプできます。

それが誰かを助けることを願っています。

于 2016-08-20T11:36:32.353 に答える
0

これを使用する//データをフェッチするためのブール値を作成するprivatebooleanisViewShown = false;

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (getView() != null) {
        isViewShown = true;
        // fetchdata() contains logic to show data when page is selected mostly asynctask to fill the data
        fetchData();
    } else {
        isViewShown = false;
    }
} 
于 2018-08-24T11:14:14.593 に答える
0
// step 1: add  BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT FragmentPagerAdapter contractor
   
    public class BottomTabViewPager extends FragmentPagerAdapter {
    
        private final List<Fragment> mFragmentList = new ArrayList<>();
        private final List<String> mFragmentTitleList = new ArrayList<>();
    
        public BottomTabViewPager(FragmentManager manager) {
            super(manager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
    
        }
    
        @Override
        public Fragment getItem(int position) {
            return mFragmentList.get(position);
        }
    
        @Override
        public int getCount() {
            return mFragmentList.size();
        }
    
        public void addFragment(Fragment fragment, String title) {
            mFragmentList.add(fragment);
            mFragmentTitleList.add(title);
        }
    
        public void addTabs(String title) {
    
            mFragmentTitleList.add(title);
        }
    
    
        @Override
        public CharSequence getPageTitle(int position) {
            return mFragmentTitleList.get(position);
            // return null;
        }
    }
    
    
   // step  2:  You can try like this :

    
    public class MyFragment extends Fragment  {
    
       
    
        public MyFragment() {
            // Required empty public constructor
        }
    
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            // Inflate the layout for this fragment
            View view = inflater.inflate(R.layout.fragment_ui, container, false);
            
            return view;
        }
    
     @Override
        public void onResume() {
            super.onResume();
            /**
             * Load your stuffs here.
             */
        }
    
      }
于 2021-04-05T08:11:10.160 に答える