web-dev-qa-db-ja.com

ViewPagerからフラグメントを更新

Activityを持つViewPagerがあります。また、ユーザーが選択するいくつかのアイテムのリストを取得するDialogもあります。さて、アイテムがこのフラグメントにアタッチされた新しいビューとして表示されることになっているFragmentをどのように更新できますか?

ここに私のViewPagerのアダプターがあります:

public static class MyAdapter extends FragmentPagerAdapter {
    public MyAdapter(FragmentManager fm) {
        super(fm);
    }

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

    @Override
    public Android.support.v4.app.Fragment getItem(int position) {
        switch (position) {
        case 0:
            return new Fragment1();

        default:
            return null;
        }
    }
}

さて、これがFragmentです:

public class Fragment1 extends Fragment{

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onActivityCreated(savedInstanceState);
}

@Override
public void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
}

@Override
public ViewGroup onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    ViewGroup view = (ViewGroup)inflater.inflate(R.layout.screen1, container, false);
    }
    return view;
}

}

これは、アイテムをFragmentに追加するために使用するメソッドです

private void addItem() {

    // Instantiate a new "row" view.

    final ViewGroup[] newViews = new ViewGroup[selectedItems.length];


    for(int i = 0; i < selectedItems.length; i++){
        newViews[i] = (ViewGroup) LayoutInflater.from(this).inflate(
                    R.layout.animated_layout_item, mContainerView, false);

        // Set the text in each new row.
        ((TextView) newViews[i].findViewById(Android.R.id.text1)).setText(selectedItems[i]);

        // Because mContainerView has Android:animateLayoutChanges set to true,
        // adding this view is automatically animated.

            mContainerView.addView(newViews[i], 0);


        // Set a click listener for the "X" button in the row that will remove the row.
        OnClickListener listener = new MyAddItemListener(newViews[i], mContainerView, this);
        newViews[i].findViewById(R.id.delete_button).setOnClickListener(listener);

    }


}
52
Luis Lavieri

ViewPagerからフラグメントを更新

getItemPosition(Object obj)メソッドを実装する必要があります。

このメソッドは、呼び出すときに呼び出されます

notifyDataSetChanged()

ViewPagerAdaperで。暗黙的にこのメソッドは、次のような意味のPOSITION_UNCHANGED値を返します。"フラグメントがあるべき場所なので、何も変更しないでください。"

したがって、Fragmentを更新する必要がある場合は、次の方法で実行できます。

  • getItemPosition()メソッドから常にPOSITION_NONEを返します。つまり、"フラグメントは常に再作成する必要があります"
  • フラグメントを更新するupdate()メソッドを作成できます(フラグメントは更新自体を処理します)

2番目のアプローチの例:

public interface Updateable {
   public void update();
}


public class MyFragment extends Fragment implements Updateable {

   ...

   public void update() {
     // do your stuff
   }
}

FragmentPagerAdapterでは、次のようなことを行います。

@Override
public int getItemPosition(Object object) {
   MyFragment f = (MyFragment ) object;
   if (f != null) {
      f.update();
   }
  return super.getItemPosition(object);
}

そして、最初のアプローチを選択すると、次のようになります。

@Override
public int getItemPosition(Object object) {
   return POSITION_NONE;
}

注:どのアプローチを採用するかを考える価値があります。

121
Simon Dorociak

この場合、常にFragmentPagerAdapterを避け、FragmentStatePagerAdapterを使用してください

それは私のために働く。それがあなたにも役立つことを願っています。

27
Yogendra

Sajmonの答えに従ってアプリのデモを実装します。この質問を検索する他の人のためだけに。

ソースコードには GitHub でアクセスできます

enter image description here

15
li2

PagerAdapterでgetItemPositionをオーバーライドします

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

その後、viewPager.getAdapter()。notifyDataSetChanged();このコードを以下のように追加します

viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        }

        @Override
        public void onPageSelected(int position) {
            viewPager.getAdapter().notifyDataSetChanged();
        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    });

動作するはずです。

12
madhu sudhan

フラグメント内のメソッドを非常に簡単にオーバーライドします。

@Override

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

    if(isVisibleToUser){
        actionView();
    }
    else{
        //no
    }      
}
4
Issac Balaji

2つの異なる方法でフラグメントを更新できます。

最初の方法

@Sajmonのような

getItemPosition(Object obj)メソッドを実装する必要があります。

このメソッドは、呼び出すときに呼び出されます

notifyDataSetChanged()

例は Github にあり、詳細はこの post にあります。

enter image description here

第二の方法

ビューページャー内でフラグメントを更新する私のアプローチは、setTag()メソッドでインスタンス化されたビューに対してinstantiateItem()メソッドを使用することです。したがって、データを変更したり、必要なビューを無効にしたい場合は、ViewPagerでfindViewWithTag()メソッドを呼び出して、以前にインスタンス化されたビューを取得し、削除/作成せずに必要に応じて変更/使用できます何らかの値を更新するたびに新しいビュー。

@Override
public Object instantiateItem(ViewGroup container, int position) {
    Object object = super.instantiateItem(container, position);
    if (object instanceof Fragment) {
        Fragment fragment = (Fragment) object;
        String tag = fragment.getTag();
        mFragmentTags.put(position, tag);
    }
    return object;
}

public Fragment getFragment(int position) {
    Fragment fragment = null;
    String tag = mFragmentTags.get(position);
    if (tag != null) {
        fragment = mFragmentManager.findFragmentByTag(tag);
    }
    return fragment;
}

Github で例を見つけるか、この post で詳細を確認できます。

enter image description here

4
Cabezas

受け入れられた答えは理解されていません、それが簡単な解決策を追加した理由です。長い闘争の後実用的な解決策を見つけます。

ただアダプタに通知、それは驚くほど機能しています、

参照コード

 void setAdapter(int position) {
        PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager());
        viewPager.setAdapter(pagerAdapter);
        // when notify then set manually current position.
        viewPager.setCurrentItem(position);
        pagerAdapter.notifyDataSetChanged();
    }

アダプタを設定するとき、およびUIを更新するときにこのコードを呼び出します。

フラグメントにこのコードを追加して更新します

((YourActivityName) getContext()).setAdapter(selectedTabPosition);

キャストコンテキストにはinstanceofを使用します。

このコードは、解決策を見つける助けとなる目的のみを共有します。

3
Yogesh Rathi

Kotlinを使用する場合、次のことができます。

1。最初Interfaceを作成し、Fragmentに実装する必要があります

interface RefreshData {
    fun refresh()
}

class YourFragment : Fragment(), RefreshData {
    ...
    override fun refresh() {
        //do what you want
    }
}

2。次のステップOnPageChangeListenerViewPagerに追加します

viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
    override fun onPageScrollStateChanged(state: Int) { }

    override fun onPageSelected(position: Int) {
        viewPagerAdapter.notifyDataSetChanged()
        viewPager.currentItem = position
    }

    override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) { }
})

getItemPositionAdapterをオーバーライドします

override fun getItemPosition(obj: Any): Int {
    if (obj is RefreshData) {
        obj.refresh()
    }
    return super.getItemPosition(obj)
}
2
Danil

フラグメントビューを更新するの非常にシンプルで効果的なソリューション。 setUserVisibleHint()メソッドを使用します。フラグメントがユーザーに表示されようとしているときに呼び出されます。そこでビューを更新できます(setText()またはsetVisibility()など)

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

    if(isVisibleToUser){
       //Write your code to be executed when it is visible to user
    }
}

私の場合はうまくいきました。それが役に立てば幸い!

2
Tahmid Rahman

おそらく、アイテムをフラグメントに追加するためのメソッドはpublic(必要なFragmentに配置)であり、selectedItemsと同じタイプのパラメーターが必要です。

これにより、selectiveItems配列と出来事を持つアクティビティから見えるようになります。

追伸より良い名前addItemsFromArray(typeOfSelectedItems[] pSelectedItems)原因名addItem()はまったく説明的ではありません

編集:stackoverflowは同様のトピックを提案しました:)詳細なアイデアの実装については here を確認してください。:)

1
Ewoks

viewPagerには4つのフラグメントがありましたが、ユーザーがこのフラグメントをクリックするたびに、viewPagerの位置0にあるフラグメント「FavoriteFragment」を1つだけ更新したかったのです。しかし、上記のコードのどれも、私が望むフラグメントをリロードするのに役立ちませんでした。だから私はこれを試してみたが、それは私のために働く:

私のFavoriteFragmentでは、onResume()をオーバーライドしました

@Override
    public void onResume() {
        super.onResume();
        updateUI(); // code to update the UI in the fragment
    }

viewPagerをホストするアクティビティでaddOnPageChangeListener()をオーバーライドし、このコードを追加します

mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                super.onPageSelected(position);

                if(position == 0) { // 0 = the first fragment in the ViewPager, in this case, the fragment i want to refresh its UI
                    FavoritesFragment fragment = (FavoritesFragment) mViewPager.getAdapter().instantiateItem(mViewPager, position); 
                    fragment.onResume(); // here i call the onResume of the fragment, where i have the method updateUI() to update its UI
                    mViewPager.getAdapter().notifyDataSetChanged();
                }
            }
        });

そして、それは私にとって完璧に機能し、私が望む1つのフラグメントだけをリフレッシュ/リロードします。

0
korchix

1)更新するフラグメントにハンドラーを作成します。

public static Handler sUpdateHandler;

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ...

        sUpdateHandler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                // call you update method here.
            }
        };
    }

2)アクティビティ/フラグメント/ダイアログで、更新呼び出しを起動したい場所で、そのハンドラーへの参照を取得し、メッセージを送信します(更新するようフラグメントを伝えます)

// Check if the fragment is visible by checking if the handler is null or not.
Handler handler = TaskTabCompletedFragment.sUpdateHandler;
if (handler != null) {
    handler.obtainMessage().sendToTarget();
}
0
Astonvish32

上記の答えのどれも私にとってはうまくいかなかったので、ここに私の解決策があります:

setUserVisibleHint(boolean isVisibleToUser)の代わりにPOSITION_NONEonStart()にロードして結合しました

ここに見られるように: https://stackoverflow.com/a/25676323/497366

Fragment内:

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
        // load data here
    }else{
       // fragment is no longer visible
    }
}

サイモンドロシアックからの一番上の回答に見られるFragmentStatePagerAdapterhttps://stackoverflow.com/a/18088509/497366

@Override
public int getItemPosition(@NonNull Object object) {
    return POSITION_NONE;
}

現在、フラグメントは、ユーザーに表示されるたびにデータをビューにリロードします。

0
Björn Kechel