61

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

    }


}
4

15 回答 15

138

从 ViewPager 更新片段

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

调用时调用此方法

notifyDataSetChanged()

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

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

  • 总是POSITION_NONEgetItemPosition()方法返回。这意味着:“必须始终重新创建片段”
  • 您可以创建一些 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;
}

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

于 2013-08-06T19:08:44.263 回答
32

我有时会遇到问题,因此在这种情况下始终避免使用 FragmentPagerAdapter 并使用 FragmentStatePagerAdapter。

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

于 2014-11-27T06:08:03.080 回答
15

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

您可以在GitHub 上访问源代码

在此处输入图像描述

于 2015-08-10T06:54:08.800 回答
14

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

        }
    });

应该管用。

于 2016-11-09T07:07:17.017 回答
5

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

第一种方式

像@Sajmon

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

调用时调用此方法

notifyDataSetChanged()

您可以在Github中找到一个示例,并在这篇文章中找到更多信息。

在此处输入图像描述

第二种方式

我在 viewpager 中更新片段的方法是将该setTag()方法用于该方法中的任何实例化视图instantiateItem()。因此,当您想要更改数据或使所需的视图无效时,您可以调用findViewWithTag()ViewPager 上的方法来检索先前实例化的视图并根据需要修改/使用它,而不必每次都删除/创建新视图想要更新一些值。

@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中找到示例或在这篇文章中找到更多信息:

在此处输入图像描述

于 2017-01-07T17:57:16.697 回答
4

覆盖片段中的方法非常简单:

@Override

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

    if(isVisibleToUser){
        actionView();
    }
    else{
        //no
    }      
}
于 2016-11-24T07:31:48.207 回答
3

接受的答案不明白,这就是为什么添加了简单的解决方案。经过长期的斗争 找到工作解决方案。

只需通知您的适配器,它的工作非常棒,

参考代码

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

此代码仅共享帮助找到解决方案的目的。

于 2016-09-24T11:19:50.553 回答
2

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

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

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

MainActivity activity = (MainActivity) getContext();
activity.initPagerAdapter();
于 2021-04-07T03:30:02.607 回答
2

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

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

于 2017-07-27T05:24:33.920 回答
2

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

在我的 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();
                }
            }
        });

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

于 2019-02-23T15:06:15.407 回答
2

如果您使用 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.覆盖getItemPosition你的Adapter

override fun getItemPosition(obj: Any): Int {
    if (obj is RefreshData) {
        obj.refresh()
    }
    return super.getItemPosition(obj)
}
于 2018-03-18T11:30:14.400 回答
1

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

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

ps 更好的名称,addItemsFromArray(typeOfSelectedItems[] pSelectedItems)因为名称addItem()非常难以描述

编辑:stackoverflow 刚刚提出了类似的主题 :)在这里查看详细的想法实现.. :)

于 2013-08-06T19:05:58.633 回答
0

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

我结合了POSITION_NONE加载setUserVisibleHint(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
    }
}

并在FragmentStatePagerAdapterSimon Dorociak https://stackoverflow.com/a/18088509/497366的最佳答案中看到:

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

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

于 2019-04-12T07:37:59.393 回答
0

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();
}
于 2016-03-30T12:28:18.487 回答
0

这对我有用:

活动:

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

分段:

public void refreshContent() {
    //refresh content
}
于 2021-10-06T20:14:55.530 回答