Android 动态更新ViewPager?
我无法更新ViewPager中的内容 FragmentPagerAdapter类中实例化Item()和getItem()方法的正确用法是什么 我只使用getItem()实例化并返回片段:Android 动态更新ViewPager?,android,android-fragments,android-viewpager,Android,Android Fragments,Android Viewpager,我无法更新ViewPager中的内容 FragmentPagerAdapter类中实例化Item()和getItem()方法的正确用法是什么 我只使用getItem()实例化并返回片段: @Override public Fragment getItem(int position) { return new MyFragment(context, paramters); } 这很有效。除了我不能改变内容 所以我发现: “我的方法是对InstanceItem()方法中的任何实例化视图使用
@Override
public Fragment getItem(int position) {
return new MyFragment(context, paramters);
}
这很有效。除了我不能改变内容
所以我发现:
“我的方法是对InstanceItem()方法中的任何实例化视图使用setTag()方法”
现在我想实现instanceItem()来实现这一点。但是我不知道我必须返回什么(类型是Object)以及与getItem(int位置)的关系是什么
我读到:
- 公共抽象片段getItem(int位置) 返回与指定位置关联的片段
- 公共对象实例化项(视图组容器,int位置) 为给定位置创建页面。适配器负责将视图添加到此处给定的容器中,尽管它只需确保在从finishUpdate(ViewGroup)返回时完成此操作。 参数 包含将在其中显示页面的视图的容器。 定位要实例化的页面位置 返回 返回表示新页的对象。这不需要是视图,但可以是页面的其他容器
public class ViewPagerTest extends FragmentActivity {
private ViewPager pager;
private MyFragmentAdapter adapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pager1);
pager = (ViewPager)findViewById(R.id.slider);
String[] data = {"page1", "page2", "page3", "page4", "page5", "page6"};
adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
pager.setAdapter(adapter);
((Button)findViewById(R.id.button)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
reload();
}
});
}
private void reload() {
String[] data = {"changed1", "changed2", "changed3", "changed4", "changed5", "changed6"};
//adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
adapter.setData(data);
adapter.notifyDataSetChanged();
pager.invalidate();
//pager.setCurrentItem(0);
}
}
MyFragmentAdapter
class MyFragmentAdapter extends FragmentPagerAdapter {
private int slideCount;
private Context context;
private String[] data;
public MyFragmentAdapter(FragmentManager fm, int slideCount, Context context, String[] data) {
super(fm);
this.slideCount = slideCount;
this.context = context;
this.data = data;
}
@Override
public Fragment getItem(int position) {
return new MyFragment(data[position], context);
}
@Override
public int getCount() {
return slideCount;
}
public void setData(String[] data) {
this.data = data;
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
我的碎片
public final class MyFragment extends Fragment {
private String text;
public MyFragment(String text, Context context) {
this.text = text;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.slide, null);
((TextView)view.findViewById(R.id.text)).setText(text);
return view;
}
}
这里也有人有类似的问题,没有答案
使用FragmentPagerAdapter或FragmentStatePagerAdapter时,最好只处理
getItem()
,而不要触摸InstanceItem()
。PagerAdapter上的实例化Item()
-destroyItem()
接口是FragmentPagerAdapter用于实现更简单的getItem()
接口的低级接口
在讨论这个问题之前,我应该澄清一下
如果要切换显示的实际片段,需要避免使用FragmentPagerAdapter并使用
FragmentStatePagerAdapter.
这个答案的一个早期版本犯了一个错误,使用FragmentPagerAdapter作为例子——这不起作用,因为FragmentPagerAdapter在第一次显示片段后从不销毁它
我不推荐您链接的帖子中提供的setTag()
和findViewWithTag()
解决方法。正如您所发现的,使用setTag()
和findViewWithTag()
无法处理片段,因此这不是一个很好的匹配
正确的解决方案是重写getItemPosition()
。调用notifyDataSetChanged()
时,ViewPager会对其适配器中的所有项调用getItemPosition()
,查看它们是否需要移动到其他位置或删除
默认情况下,getItemPosition()
返回POSITION\u UNCHANGED
,这意味着,“此对象在其所在位置很好,不要销毁或删除它。”返回POSITION\u NONE
修复了问题,改为说:“此对象不再是我正在显示的项目,请将其删除。”因此,它可以删除并重新创建适配器中的每一项
这是一个完全合法的修复!此修复程序使notifyDataSetChanged的行为类似于常规适配器,无需视图回收。如果您实现了此修复并且性能令人满意,那么您就可以开始比赛了。工作完成了
如果需要更好的性能,可以使用更高级的getItemPosition()
实现。下面是一个寻呼机从字符串列表中创建片段的示例:
ViewPager pager = /* get my ViewPager */;
// assume this actually has stuff in it
final ArrayList<String> titles = new ArrayList<String>();
FragmentManager fm = getSupportFragmentManager();
pager.setAdapter(new FragmentStatePagerAdapter(fm) {
public int getCount() {
return titles.size();
}
public Fragment getItem(int position) {
MyFragment fragment = new MyFragment();
fragment.setTitle(titles.get(position));
return fragment;
}
public int getItemPosition(Object item) {
MyFragment fragment = (MyFragment)item;
String title = fragment.getTitle();
int position = titles.indexOf(title);
if (position >= 0) {
return position;
} else {
return POSITION_NONE;
}
}
});
ViewPager-pager=/*获取我的ViewPager*/;
//假设这里面有东西
最终ArrayList标题=新ArrayList();
FragmentManager fm=getSupportFragmentManager();
寻呼机设置适配器(新FragmentStatePagerAdapter(fm){
public int getCount(){
返回titles.size();
}
公共片段getItem(int位置){
MyFragment fragment=新的MyFragment();
fragment.setTitle(titles.get(position));
返回片段;
}
public int getItemPosition(对象项){
MyFragment fragment=(MyFragment)项;
String title=fragment.getTitle();
int position=titles.indexOf(title);
如果(位置>=0){
返回位置;
}否则{
返回位置\无;
}
}
});
在这个实现中,只会显示显示新标题的片段。任何显示仍在列表中的标题的片段都将被移动到列表中的新位置,而标题已完全不在列表中的片段将被销毁
如果片段尚未重新创建,但仍需要更新,该怎么办?对活动片段的更新最好由片段本身来处理。毕竟,这就是拥有片段的优势——它是自己的控制器。片段可以向onCreate()
中的另一个对象添加侦听器或观察者,然后在onDestroy()
中删除它,从而管理更新本身。您不必像在ListView或其他AdapterView类型的适配器中那样,将所有更新代码放入getItem()
最后一件事——仅仅因为FragmentPagerAdapter不销毁片段并不意味着getItemPosition在FragmentPagerAdapter中完全无用。您仍然可以使用此回调对ViewPager中的片段重新排序。但是,它永远不会从FragmentManager中完全删除它们。在代码中的
notifyDataSetChanged()
之后,在ViewPager上尝试destroyDrawingCache()
。而不是从getItemPosition()
返回POSITION\u NONE
,并导致完全错误
//call this method to update fragments in ViewPager dynamically
public void update(UpdateData xyzData) {
this.updateData = xyzData;
notifyDataSetChanged();
}
@Override
public int getItemPosition(Object object) {
if (object instanceof UpdateableFragment) {
((UpdateableFragment) object).update(updateData);
}
//don't return POSITION_NONE, avoid fragment recreation.
return super.getItemPosition(object);
}
public class SomeFragment extends Fragment implements
UpdateableFragment{
@Override
public void update(UpdateData xyzData) {
// this method will be called for every fragment in viewpager
// so check if update is for this fragment
if(forMe(xyzData)) {
// do whatever you want to update your UI
}
}
}
public interface UpdateableFragment {
public void update(UpdateData xyzData);
}
public class UpdateData {
//whatever you want here
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Object o = super.instantiateItem(container, position);
if(o instanceof FragmentX){
myFragments[0] = (FragmentX)o;
}else if(o instanceof FragmentY){
myFragments[1] = (FragmentY)o;
}else if(o instanceof FragmentZ){
myFragments[2] = (FragmentZ)o;
}
return o;
}
public class myPagerAdapter extends FragmentPagerAdapter {
public class PagerItem {
private String mTitle;
private Fragment mFragment;
public PagerItem(String mTitle, Fragment mFragment) {
this.mTitle = mTitle;
this.mFragment = mFragment;
}
public String getTitle() {
return mTitle;
}
public Fragment getFragment() {
return mFragment;
}
public void setTitle(String mTitle) {
this.mTitle = mTitle;
}
public void setFragment(Fragment mFragment) {
this.mFragment = mFragment;
}
}
private FragmentManager mFragmentManager;
private ArrayList<PagerItem> mPagerItems;
public MyPagerAdapter(FragmentManager fragmentManager, ArrayList<PagerItem> pagerItems) {
super(fragmentManager);
mFragmentManager = fragmentManager;
mPagerItems = pagerItems;
}
public void setPagerItems(ArrayList<PagerItem> pagerItems) {
if (mPagerItems != null)
for (int i = 0; i < mPagerItems.size(); i++) {
mFragmentManager.beginTransaction().remove(mPagerItems.get(i).getFragment()).commit();
}
mPagerItems = pagerItems;
}
ArrayList<PagerItem> pagerItems = new ArrayList<PagerItem>();
pagerItems.add(new PagerItem("Fragment1", new MyFragment1()));
pagerItems.add(new PagerItem("Fragment2", new MyFragment2()));
mPagerAdapter.setPagerItems(pagerItems);
mPagerAdapter.notifyDataSetChanged();
private class PagerAdapter extends FragmentStatePagerAdapter{
Bundle oBundle;
FragmentManager oFragmentManager;
ArrayList<Fragment> oPooledFragments;
public PagerAdapter(FragmentManager fm) {
super(fm);
oFragmentManager=fm;
}
@Override
public int getItemPosition(Object object) {
Fragment oFragment=(Fragment)object;
oPooledFragments=new ArrayList<>(oFragmentManager.getFragments());
if(oPooledFragments.contains(oFragment))
return POSITION_NONE;
else
return POSITION_UNCHANGED;
}
}
if (!(mPagerAdapter == null)) {
mPagerAdapter.notifyDataSetChanged();
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
public class UpdateCountEvent {
public final int count;
public UpdateCountEvent(int count) {
this.count = count;
}
}
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
public void onEvent(UpdateCountEvent event) {//get update message
Toast.makeText(getActivity(), event.count, Toast.LENGTH_SHORT).show();
}
//input update message
EventBus.getDefault().post(new UpdateCountEvent(count));
class PagerAdapter extends FragmentPagerAdapter {
public boolean flag_refresh=false;
public PagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int page) {
FragmentsMain f;
f=new FragmentsMain();
f.page=page;
return f;
}
@Override
public int getCount() {
return 4;
}
@Override
public int getItemPosition(Object item) {
int page= ((FragmentsMain)item).page;
if (page == 0 && flag_refresh) {
flag_refresh=false;
return POSITION_NONE;
} else {
return super.getItemPosition(item);
}
}
@Override
public void destroyItem(View container, int position, Object object) {
((ViewPager) container).removeView((View) object);
}
}
adapter=new PagerAdapter(getSupportFragmentManager());
pager.setAdapter(adapter);
@Override
protected void onResume() {
super.onResume();
if (adapter!=null) {
adapter.flag_refresh=true;
adapter.notifyDataSetChanged();
}
}
public class FragmentsMain extends Fragment {
private Cursor cursor;
private static Context context;
public int page=-1;
private class MyAdapter extends FragmentStatePagerAdapter {
// [Rest of implementation]
@Override
public void restoreState(Parcelable state, ClassLoader loader) {}
}
private void updateFragment(Item item) {
List<Fragment> fragments = getSupportFragmentManager().getFragments();
for (Fragment fragment : fragments) {
if (fragment instanceof MyItemFragment && fragment.isVisible()) {
((MyItemFragment) fragment).update(item);
}
}
}
@Override
public void notifyDataSetChanged() {
mFragments.clear();
super.notifyDataSetChanged();
}
if (position < mFragments.size()) {
mFragments.set(position, null);
}
public class MyFragmentStatePageAdapter extends FragmentStatePagerAdapter {
private static final String TAB1_TITLE = "Tab 1";
private static final String TAB2_TITLE = "Tab 2";
private static final String TAB3_TITLE = "Tab 3";
private ArrayList<String> titles = new ArrayList<>();
private Map<Fragment, Integer> fragmentPositions = new HashMap<>();
public MyFragmentStatePageAdapter(FragmentManager fm) {
super(fm);
}
public void update(boolean showTab1, boolean showTab2, boolean showTab3) {
titles.clear();
if (showTab1) {
titles.add(TAB1_TITLE);
}
if (showTab2) {
titles.add(TAB2_TITLE);
}
if (showTab3) {
titles.add(TAB3_TITLE);
}
notifyDataSetChanged();
}
@Override
public int getCount() {
return titles.size();
}
@Override
public Fragment getItem(int position) {
Fragment fragment = null;
String tabName = titles.get(position);
if (tabName.equals(TAB1_TITLE)) {
fragment = Tab1Fragment.newInstance();
} else if (tabName.equals(TAB2_TITLE)) {
fragment = Tab2Fragment.newInstance();
} else if (tabName.equals(TAB3_TITLE)) {
fragment = Tab3Fragmen.newInstance();
}
((BaseFragment)fragment).setTitle(tabName);
fragmentPositions.put(fragment, position);
return fragment;
}
@Override
public CharSequence getPageTitle(int position) {
return titles.get(position);
}
@Override
public int getItemPosition(Object item) {
BaseFragment fragment = (BaseFragment)item;
String title = fragment.getTitle();
int position = titles.indexOf(title);
Integer fragmentPosition = fragmentPositions.get(item);
if (fragmentPosition != null && position == fragmentPosition) {
return POSITION_UNCHANGED;
} else {
return POSITION_NONE;
}
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
fragmentPositions.remove(object);
}
}
myVPager.setAdapter(null);
myFragmentAdapter = new MyFragmentAdapter(getSupportFragmentManager(),newList);
myVPager.setAdapter(myFragmentAdapter);
public int getItemPosition(Object item) {
if(item instanceof FirstFragment){
return 0;
}
return POSITION_NONE;
}
private boolean mIsUpdating = false;
public void setIsUpdating(boolean mIsUpdating) {
this.mIsUpdating = mIsUpdating;
}
@Override
public int getItemPosition(@NonNull Object object) {
if (mIsUpdating) {
return POSITION_NONE;
}
else {
return super.getItemPosition(object);
}
}
mAdapter.setIsUpdating(true);
mAdapter.notifyDataSetChanged();
mAdapter.setIsUpdating(false);
if (mFragments.size() > position) {
Fragment f = mFragments.get(position);
if (f != null) {
int newPosition = getItemPosition(f);
if (newPosition == POSITION_UNCHANGED) {
return f;
} else if (newPosition == POSITION_NONE) {
mFragments.set(position, null);
} else {
mFragments.set(newPosition, f);
}
}
}