【问题标题】:Update Fragment from ViewPager从 ViewPager 更新片段
【发布时间】:2013-08-06 18:43:13
【问题描述】:

我有一个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);

    }


}

【问题讨论】:

标签: android android-fragments android-viewpager


【解决方案1】:

从 ViewPager 更新片段

你需要实现getItemPosition(Object obj)方法。

调用的时候调用这个方法

notifyDataSetChanged()

在您的ViewPagerAdaper 上。此方法隐含地返回 POSITION_UNCHANGED 值,其含义如下: “片段是它应该在的地方,所以不要改变任何东西。”

因此,如果您需要更新 Fragment,您可以这样做:

  • 总是从getItemPosition() 方法返回POSITION_NONE。它哪 表示:“必须始终重新创建片段”
  • 您可以创建一些 update() 方法来更新您的 片段(片段将自己处理更新)

第二种方法的示例:

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;
}

注意:值得考虑一下您将采用哪种方法。

【讨论】:

  • 感谢您的回答。但是,它没有更新它!你能看一下我刚刚创建的Gist 吗?我选择了选项 2。
  • @LuisLavieri 你应该这样称呼它yourPager.getAdapter().notifyDataSetChanged()
  • 美丽。经过一番努力,终于奏效了。谢谢哥们。问题是我的mContainerView;它没有正确实例化。
  • +1 for @Override public int getItemPosition(Object object) { return POSITION_NONE; }
  • 我在 FragmentPagerAdapter 中有 5 个片段。我已经尝试了这两种解决方案,但没有一个对我有用,因为每次我刷卡时都会多次调用 MyFragment。如果有人找到解决方案,请提供帮助。
【解决方案2】:

我遇到过一些问题,所以在这种情况下总是避免使用 FragmentPagerAdapter 并使用 FragmentStatePagerAdapter。

它对我有用。我希望它也对你有用。

【讨论】:

  • @akhilesh0707 欢迎:)
  • 谢谢 :) 我可以使用这个适配器创建动态标签
  • @busetekin 欢迎
  • 谢谢,救了我...:-)
  • 投票,为我节省一小时
【解决方案3】:

我按照 Sajmon 的回答实现了一个应用演示。 仅适用于搜索此问题的其他人。

您可以在GitHub访问源代码

【讨论】:

    【解决方案4】:

    在您的 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) {
    
            }
        });
    

    应该可以。

    【讨论】:

    • 它可以工作,但是在标签之间滑动时 UI 开始变慢。谢谢。
    • 请点赞,经过 2 小时的研究帮助了我 :)
    【解决方案5】:

    您可以通过两种不同的方式更新片段,

    第一种方式

    喜欢@Sajmon

    你需要实现getItemPosition(Object obj)方法。

    调用的时候调用这个方法

    notifyDataSetChanged()
    

    您可以在Github 中找到示例,在此post 中找到更多信息。

    第二种方式

    我在 viewpager 中更新片段的方法是对 instantiateItem() 方法中的任何实例化视图使用 setTag() 方法。所以当你想更改数据或使你需要的视图失效时,你可以调用 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 中找到更多信息:

    【讨论】:

      【解决方案6】:

      在片段中重写方法非常简单:

      @Override
      
      public void setUserVisibleHint(boolean isVisibleToUser) {
          super.setUserVisibleHint(isVisibleToUser);
      
          if(isVisibleToUser){
              actionView();
          }
          else{
              //no
          }      
      }
      

      【讨论】:

      • 目前此答案已弃用,请查看 Simon 答案,该答案更正确。
      【解决方案7】:

      接受的答案不明白,这就是为什么添加了简单的解决方案。经过长时间的努力 找到可行的解决方案。

      只需通知您的适配器,它的效果非常好,

      参考代码

       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 作为演员表上下文。

      此代码仅用于帮助找到解决方案的目的。

      【讨论】:

        【解决方案8】:

        更新片段视图的非常简单而有效的解决方案。使用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
            }
        }
        

        它在我的情况下有效。希望能帮助到你!

        【讨论】:

          【解决方案9】:

          如果您使用 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) { }
          })
          

          3. 在您的Adapter 中覆盖getItemPosition

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

          【讨论】:

            【解决方案10】:

            我在 ViewPager 中有 4 个 Fragment,但每次用户单击此 Fragment 时,我只想在 viewPager 的位置 0 处更新一个 Fragment“FavoriteFragment”。 但是上面的代码都没有帮助我重新加载我想要的一个片段。 所以我尝试了这个,它对我有用:

            在我的 FavoriteFragment 中,我重写了 onResume()

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

            在托管 viewPager 的 Activity 中覆盖 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();
                            }
                        }
                    });
            

            它非常适合我,只刷新/重新加载我想要的一个片段。

            【讨论】:

            • 感谢您分享解决方案:)
            【解决方案11】:

            很多答案,但是为我完成工作的快速而肮脏的解决方案是有一种方法可以在 MainActivity 中初始化 pagerAdapter:

            public void initPagerAdapter(){
                    pagerAdapter = new MainPagerAdapter(getSupportFragmentManager());
                    viewPager.setAdapter(pagerAdapter);
                    tabLayout.setupWithViewPager(viewPager);
            }
            

            在我想要刷新的片段中,我只需获取 MainActivity 并调用该方法:

            MainActivity activity = (MainActivity) getContext();
            activity.initPagerAdapter();
            

            【讨论】:

              【解决方案12】:

              也许您将项目添加到片段中的方法应该是 public (放置在所需的片段中)并且应该具有与 selectedItems 相同类型的参数..

              这将使它从活动中可见,该活动将具有 selectedItems 数组和瞧..

              附言最好将其命名为 addItemsFromArray(typeOfSelectedItems[] pSelectedItems),因为名称 addItem() 很难描述

              编辑:stackoverflow 刚刚提出了类似的主题 :) 检查 here 以了解详细的想法实施.. :)

              【讨论】:

                【解决方案13】:

                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) 在 Activity/Fragment/Dialog 中,无论您希望在何处触发更新调用,获取对该处理程序的引用并发送一条消息(告诉您的 Fragment 进行更新)

                // 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();
                }
                

                【讨论】:

                  【解决方案14】:

                  因为以上答案都没有对我有用,所以这是我的解决方案:

                  我将POSITION_NONEsetUserVisibleHint(boolean isVisibleToUser) 上的加载相结合,而不是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 中,如 Simon Dorociak https://stackoverflow.com/a/18088509/497366 的最佳答案所示:

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

                  现在片段每次向用户显示时都会将数据重新加载到视图中。

                  【讨论】:

                    【解决方案15】:

                    这对我有用:

                    活动:

                    for (Fragment fragment : getSupportFragmentManager().getFragments()) {
                        if (fragment.isVisible() && fragment instanceof MyFragment) {
                            ((MyFragment) fragment).refreshContent();
                            break;
                        }
                    }
                    

                    片段:

                    public void refreshContent() {
                        //refresh content
                    }
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2015-10-20
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多