web-dev-qa-db-ja.com

メインアクティビティごとにViewPagerのフラグメントをプログラムで更新および更新する方法

Fragmentと単一のMainActivityを使用して、同じViewPagerで異なるフラグメントを表示するアプリを作成して、典型的なMVCアプリケーションの動作を再現しています。

問題は、フラグメントをプログラムで更新して、新しいフラグメントの変更でViewPagerを更新する方法を理解していないことです。

たとえば、チャートを表示するこのFragmentがあります(意図的に)メインからsetFragment(int interval, Point[] snodePoint)を呼び出すと、チャートはViewPagerで更新されます

public class LineFragment extends Fragment {
    static int interval;
    static Point snodePoints[];


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        final View v = inflater.inflate(R.layout.fragment_linegraph, container,
                false);
        Bundle bundle = this.getArguments();
        ChartConfig cg = bundle.getParcelable("FragmentData");

        snodePoints = cg.getPoints();
        interval= cg.getInterval();
        Line l = new Line();

        for(int i=0; i<snodePoints.length; i++){
          LinePoint p = new LinePoint();
          Point sp=snodePoints[i];
          p.setX(sp.getX());
          p.setY(sp.getY());
          l.addPoint(p)
        }
        l.setColor(getResources().getColor(R.color.green));

        LineGraph li = (LineGraph) v.findViewById(R.id.linegraph);
        li.addLine(l);
        li.setRangeY(0, interval);
        li.setLineToFill(0);

        li.setOnPointClickedListener(new OnPointClickedListener() {

            @Override
            public void onClick(int lineIndex, int pointIndex) {
                // TODO Auto-generated method stub

            }

        });

        return v;
    }
}

いくつかの言葉で私がする必要がある

  • 1-メインアクティビティが受信したデータに基づいてフラグメントを作成します。
  • 2-アクティビティのたびにフラグメントのデータを変更し、setFragment(...)のような何かが新しいデータ(メインによって常に生成される)で発生します。

どうすればこれができますか?

FragmentAdapterを使用した主なアクティビティ

public class MainActivity extends FragmentActivity {

ViewPager mViewPager;
MyFragmentAdapter mMyFragmentAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mViewPager = (ViewPager) findViewById(R.id.view_pager);
    final ActionBar bar = this.getActionBar();
    bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    LineFragment lineFrag = new LineFragment();
    BarFragment barFrag = new BarFragment();
    PieFragment pieFrag = new PieFragment();

    mMyFragmentAdapter = new MyFragmentAdapter(this, mViewPager);
    mMyFragmentAdapter.addTab(bar.newTab().setText("Line"), LineFragment.class,
            null, lineFrag);
    mMyFragmentAdapter.addTab(bar.newTab().setText("Bar"), BarFragment.class,
            null, barFrag);
    mMyFragmentAdapter.addTab(bar.newTab().setText("Pie"), PieFragment.class,
            null, pieFrag);
    mViewPager.setOffscreenPageLimit(mMyFragmentAdapter.getCount() - 1);
}

public static class MyFragmentAdapter extends FragmentStatePagerAdapter implements
        ActionBar.TabListener, ViewPager.OnPageChangeListener {

    private final MainActivity mContext;
    private final ActionBar mActionBar;
    private final ViewPager mViewPager;
    private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
    private final ArrayList<Fragment> mFrag = new ArrayList<Fragment>();

    static final class TabInfo {
        private final Class<?> clss;
        private final Bundle args;

        TabInfo(Class<?> _class, Bundle _args) {
            clss = _class;
            args = _args;
        }
    }

    public MyFragmentAdapter(MainActivity activity, ViewPager pager) {
        super(activity.getSupportFragmentManager());
        mContext = activity;
        mActionBar = activity.getActionBar();
        mViewPager = pager;
        mViewPager.setAdapter(this);
        mViewPager.setOnPageChangeListener(this);
    }

    public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args,
            Fragment frag) {
        TabInfo info = new TabInfo(clss, args);
        tab.setTag(info);
        tab.setTabListener(this);
        mTabs.add(info);
        mFrag.add(frag);
        mActionBar.addTab(tab);
        notifyDataSetChanged();
    }

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

    @Override
    public Fragment getItem(int position) {
        TabInfo info = mTabs.get(position);
        Bundle args = new Bundle();
        ChartConfig cg = new ChartConfig(interval, snodePoint);
        args.putParcelable("FragmentData", cg);
        Fragment f = mFrag.get(position);
        f.setArguments(args);

        return f;
    }

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

    @Override
    public void onPageSelected(int position) {
        mActionBar.setSelectedNavigationItem(position);

    }

    @Override
    public void onPageScrollStateChanged(int state) {
    }

    public void onTabSelected(Tab tab, Android.app.FragmentTransaction ft) {
        Object tag = tab.getTag();
        for (int i = 0; i < mTabs.size(); i++) {
            if (mTabs.get(i) == tag) {
                mViewPager.setCurrentItem(i);
            }
        }
    }

    public void onTabUnselected(Tab tab, Android.app.FragmentTransaction ft) {
    }

    @Override
    public void onTabReselected(Tab tab, Android.app.FragmentTransaction ft) {
    }

}

}

フラグメントを初めて作成したとき、メインアクティビティはオーバーライドされたgetItem(int position)を介してフラグメントにパラメータを正常に渡しますが、データを変更しようとした場合、またはnotifyDataSetChanged()を呼び出した場合もアダプタmMyFragmentAdapterでは何も起こらず、ViewPagerのフラグメントは作成時に渡された同じデータを引き続き使用します。

[〜#〜] edit [〜#〜]

フラグメントの更新に関する他の質問に見られる部分的なコードに続いて、私もこれを試しました

public void update() {
        try{
            LineFragment fragment = 
                      (LineFragment) getSupportFragmentManager().findFragmentByTag(
                                   "Android:switcher:"+R.id.view_pager+":0");
                  if(fragment != null)
                  {
                     if(fragment.getView() != null) 
                     {

                        fragment.updateDisplay();
                     }
                  }
        }
        catch(RuntimeException e){
            e.printStackTrace();
        }

    }

0が最初のFragment-TabフラグメントのIDであると仮定しますが(この種の操作についてはわかりません)、fragment.updateDisplay();は呼び出されません。

21
AndreaF

アダプタでgetItemPositionをオーバーライドします

@Override
public int getItemPosition(Object object) {
    // POSITION_NONE makes it possible to reload the PagerAdapter
    return POSITION_NONE;
}

その後

viewPager.getAdapter().notifyDataSetChanged() 

動作するはずです。

46
luckyhandler

フラグメントがメインから渡されるデータを取得する方法を理解する必要があります。おそらく何かが欠けているかもしれませんが、実際にこれを行う方法を理解していません。

これから、Fragmentの作成時にデータを渡したいようです。これが必要な場合は、カスタムコンストラクターを作成しないでください(通常、Fragmentに対しては、デフォルトの引数なしのコンストラクターのみを使用する必要があります(特定の時点でプラットフォームがFragment回))。

代わりに、データを Bundle で渡す必要があります。

@Override
public Fragment getItem(int position) {
     switch (position) {
        //...
        Bundle args = new Bundle();
        args.put("a_string_representing_theKey", data)
        LineFragment f = new LineFragment();
        f.setArguments(args);
        return f;
        //...
     } 
}

これは、データをBundleに入れることができる場合にのみ機能します(Bundleクラスのput...メソッド、すべてのプリミティブ+ Parcelableであるオブジェクトを参照)。フラグメントでは、getArguments()を使用して引数を取得できます。

FragmentからActivityから直接データを取得することもできます。

// in the lifecycle method where you want the data
((MainActivity)getActivity()).getDataForFragment(); // use the data

たとえば、メインからsetFragment(int interval、Point [] snodePoint)を呼び出すと、グラフを表示するこのフラグメントがあります(グラフはViewPagerで更新する必要があります)。

あなたは自分自身に矛盾するようです。これには、私がリンクした質問のコードを使用します。もちろん、現在のsetFragment()メソッドを呼び出しても、2つの変数の値を更新するだけなので、UIに変更を通知する必要があります。 (別のメソッドを呼び出してビュー階層を再作成する、チャートビューで新しい値を設定する、invalidate()などを呼び出すなど)。

編集:

リンクした質問で使用したコードは動作するはずですが、適切なコードを使用していません。 FragmentStatePagerAdapterがありますが、使用できないFragmentPagerAdapterのコードを使用しています:

FragmentStatePagerAdapter a = (FragmentStatePagerAdapter) mViewPager.getAdapter();
LineFragment f = (LineFragment) a.instantiateItem(pager, thePositionYouWant);

上記のコードは、目に見えるフラグメントと各側に1つずつのフラグメントに対してのみ機能し、他のフラグメントは使用できないことに注意してください(そして、ユーザーはそれらを表示しないか、すぐに移動できないため、更新される)。

3
Luksprog
#How to update-refresh Fragment in ViewPager by Main Activity programmatically
#after long struggle I find proper solution

tablayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {

                refreshTab(tab.getPosition());// create a method
                viewpager.setCurrentItem(tab.getPosition());
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });
 private void refreshTab(int position) {
    switch (position) {
        case 0:


            break;
        case 1:

            CompaniesInterest comP1 = (CompaniesInterest) viewpager.getAdapter().instantiateItem(viewpager, viewpager.getCurrentItem());
            comP1.refreshpage();
            break;
        case 2:

            TotalSelectedCompanies toTal = (TotalSelectedCompanies) viewpager.getAdapter().instantiateItem(viewpager, viewpager.getCurrentItem());
            toTal.refreshpage();

    }
}
// Create a interface for refresh data for fragmen
public interface Refreshpage {
    void refreshpage();
}
// implements Refreshpage interface in both fragment TotalSelectedCompanies and CompaniesInterest
//
@Override`enter code here`
    public void refreshpage() {
        // do what you want to refresh 
    }
2
Shiv Kumar

フラグメント内のメソッドをオーバーライドするのは非常に簡単です

@オーバーライド

public void setUserVisibleHint(boolean isVisibleToUser) {

    super.setUserVisibleHint(isVisibleToUser);
    if(isVisibleToUser){

        actionView();
    }
    else{
        //no
    }

}
2
Issac Balaji