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);
}
}
ViewPagerからフラグメントを更新
getItemPosition(Object obj)
メソッドを実装する必要があります。
このメソッドは、呼び出すときに呼び出されます
notifyDataSetChanged()
ViewPagerAdaper
で。暗黙的にこのメソッドは、次のような意味のPOSITION_UNCHANGED
値を返します。"フラグメントがあるべき場所なので、何も変更しないでください。"
したがって、Fragmentを更新する必要がある場合は、次の方法で実行できます。
getItemPosition()
メソッドから常にPOSITION_NONE
を返します。つまり、"フラグメントは常に再作成する必要があります"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;
}
注:どのアプローチを採用するかを考える価値があります。
この場合、常にFragmentPagerAdapterを避け、FragmentStatePagerAdapterを使用してください
それは私のために働く。それがあなたにも役立つことを願っています。
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) {
}
});
動作するはずです。
フラグメント内のメソッドを非常に簡単にオーバーライドします。
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser){
actionView();
}
else{
//no
}
}
2つの異なる方法でフラグメントを更新できます。
最初の方法
@Sajmonのような
getItemPosition(Object obj)
メソッドを実装する必要があります。
このメソッドは、呼び出すときに呼び出されます
notifyDataSetChanged()
例は Github にあり、詳細はこの post にあります。
第二の方法
ビューページャー内でフラグメントを更新する私のアプローチは、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;
}
受け入れられた答えは理解されていません、それが簡単な解決策を追加した理由です。長い闘争の後実用的な解決策を見つけます。
ただアダプタに通知、それは驚くほど機能しています、
参照コード
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
を使用します。
このコードは、解決策を見つける助けとなる目的のみを共有します。
Kotlinを使用する場合、次のことができます。
1。最初、Interface
を作成し、Fragment
に実装する必要があります
interface RefreshData {
fun refresh()
}
class YourFragment : Fragment(), RefreshData {
...
override fun refresh() {
//do what you want
}
}
2。次のステップはOnPageChangeListener
をViewPager
に追加します
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) { }
})
。getItemPosition
のAdapter
をオーバーライドします
override fun getItemPosition(obj: Any): Int {
if (obj is RefreshData) {
obj.refresh()
}
return super.getItemPosition(obj)
}
フラグメントビューを更新するの非常にシンプルで効果的なソリューション。 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
}
}
私の場合はうまくいきました。それが役に立てば幸い!
おそらく、アイテムをフラグメントに追加するためのメソッドはpublic(必要なFragmentに配置)であり、selectedItemsと同じタイプのパラメーターが必要です。
これにより、selectiveItems配列と出来事を持つアクティビティから見えるようになります。
追伸より良い名前addItemsFromArray(typeOfSelectedItems[] pSelectedItems)
原因名addItem()
はまったく説明的ではありません
編集:stackoverflowは同様のトピックを提案しました:)詳細なアイデアの実装については here を確認してください。:)
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つのフラグメントだけをリフレッシュ/リロードします。
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();
}
上記の答えのどれも私にとってはうまくいかなかったので、ここに私の解決策があります:
setUserVisibleHint(boolean isVisibleToUser)
の代わりにPOSITION_NONE
をonStart()
にロードして結合しました
ここに見られるように: 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
}
}
サイモンドロシアックからの一番上の回答に見られるFragmentStatePagerAdapter
で https://stackoverflow.com/a/18088509/497366 :
@Override
public int getItemPosition(@NonNull Object object) {
return POSITION_NONE;
}
現在、フラグメントは、ユーザーに表示されるたびにデータをビューにリロードします。