我正在使用兼容性库中的ViewPager。我已经成功地让它显示几个视图,我可以通过页面。

但是,我很难弄清楚如何用一组新的视图更新ViewPager。

我已经尝试了各种各样的事情,比如调用mAdapter.notifyDataSetChanged(), mviewpage .invalidate(),甚至在每次我想使用新的数据列表时创建一个全新的适配器。

没有任何帮助,textviews保持不变,从原始数据。

更新: 我做了一个小测试项目,我几乎能够更新视图。我将在下面粘贴这个类。

然而,似乎没有更新的是第二个视图,“B”仍然存在,它应该在按下更新按钮后显示“Y”。

public class ViewPagerBugActivity extends Activity {

    private ViewPager myViewPager;
    private List<String> data;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        data = new ArrayList<String>();
        data.add("A");
        data.add("B");
        data.add("C");

        myViewPager = (ViewPager) findViewById(R.id.my_view_pager);
        myViewPager.setAdapter(new MyViewPagerAdapter(this, data));

        Button updateButton = (Button) findViewById(R.id.update_button);
        updateButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                updateViewPager();
            }
        });
    }

    private void updateViewPager() {
        data.clear();
        data.add("X");
        data.add("Y");
        data.add("Z");
        myViewPager.getAdapter().notifyDataSetChanged();
    }

    private class MyViewPagerAdapter extends PagerAdapter {

        private List<String> data;
        private Context ctx;

        public MyViewPagerAdapter(Context ctx, List<String> data) {
            this.ctx = ctx;
            this.data = data;
        }

        @Override
        public int getCount() {
            return data.size();
        }

        @Override
        public Object instantiateItem(View collection, int position) {
            TextView view = new TextView(ctx);
            view.setText(data.get(position));
            ((ViewPager)collection).addView(view);
            return view;
        }

        @Override
        public void destroyItem(View collection, int position, Object view) {
             ((ViewPager) collection).removeView((View) view);
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }

        @Override
        public Parcelable saveState() {
            return null;
        }

        @Override
        public void restoreState(Parcelable arg0, ClassLoader arg1) {
        }

        @Override
        public void startUpdate(View arg0) {
        }

        @Override
        public void finishUpdate(View arg0) {
        }
    }
}

当前回答

重写getItemPosition()的正确方法:

@Override
public int getItemPosition(@NonNull Object object) {
    if (!(object instanceof MyPageView)) {
        // Should never happen
        return super.getItemPosition(object);
    }
    MyDataObject dataObject = ((MyPageView) object).getData();
    if (!(dataObject instanceof MyDataObject)) {
        // Should never happen
        return super.getItemPosition(object);
    }
    if (lstItems.contains(dataObject)) {
        return POSITION_UNCHANGED;
    }
    return POSITION_NONE;
}

简而言之,您需要将用于绘制视图的数据附加/保存到视图。从那里,当调用getItemPosition()时,ViewPager可以确定当前显示的视图是否仍然存在于适配器上,并据此采取行动。

其他回答

我知道我迟到了,但还是能帮到别人。我只是扩展了接受的答案,我也添加了评论。

答案本身说明它是低效的

为了让它只在需要时刷新,你可以这样做

private boolean refresh;

public void refreshAdapter() {
    refresh = true;
    notifyDataSetChanged();
}

@Override
public int getItemPosition(@NonNull Object object) {
    if (refresh) {
        refresh = false;
        return POSITION_NONE;
    } else {
        return super.getItemPosition(object);
    }
}

所有这些答案对我都不起作用。

唯一对我有用的是,我必须再次将适配器设置为viewpager,然后它将刷新内容。

removeView(int pos)在我的PagerAdaper

public void removeView(int index) {
       imageFileNames.remove(index);
       notifyDataSetChanged();
}

无论我在哪里删除文件,我都必须这样做

imagePagerAdapter.removeView(currentPosition);
viewPager.setAdapter(imagePagerAdapter);

编辑:

下面的方法是有效的,你可以使用下面的方法。

public void updateView(int pos){
      viewPager.setAdapter(null);
      imagePagerAdapter =new ImagePagerAdapter(YOUR_CONTEXT,YOUR_CONTENT);
      viewPager.setAdapter(imagePagerAdapter);
      viewPager.setCurrentItem(pos);
}

用你的上下文替换你的YOUR_CONTEXT,用你的内容名称替换你的内容,即更新列表或其他东西。

以防任何人使用FragmentStatePagerAdapter的适配器(这将让ViewPager创建显示所需的最小页面,对于我的情况最多2个页面),@rui。araujo在适配器中覆盖getItemPosition的答案不会造成重大浪费,但仍然可以改进。

在伪代码中:

public int getItemPosition(Object object) {
    YourFragment f = (YourFragment) object;
    YourData d = f.data;
    logger.info("validate item position on page index: " + d.pageNo);

    int dataObjIdx = this.dataPages.indexOf(d);

    if (dataObjIdx < 0 || dataObjIdx != d.pageNo) {
        logger.info("data changed, discard this fragment.");
        return POSITION_NONE;
    }

    return POSITION_UNCHANGED;
}

触发mTabsAdapter.onTabChanged (mTabHost.getCurrentTabTag ());在更新视图之前。这是可行的。

我把我自己的解决方案留在这里,这是一个变通办法,因为问题似乎是FragmentPagerAdapter不清理之前的片段,你可以添加到ViewPager,在片段管理器。所以,在添加FragmentPagerAdapter之前,我创建了一个方法来执行:

(在我的情况下,我从来没有添加超过3个片段,但你可以使用例如getFragmentManager(). getbackstackentrycount(),并检查所有的片段。

/**
 * this method is solving a bug in FragmentPagerAdapter which don't delete in the fragment manager any previous fragments in a ViewPager.
 *
 * @param containerId
 */
public void cleanBackStack(long containerId) {
    FragmentTransaction transaction = getFragmentManager().beginTransaction();
    for (int i = 0; i < 3; ++i) {
        String tag = "android:switcher:" + containerId + ":" + i;
        Fragment f = getFragmentManager().findFragmentByTag(tag);
        if (f != null) {
            transaction.remove(f);
        }
    }
    transaction.commit();
}

我知道这是一种变通方法,因为如果框架创建标签的方式发生变化,它将停止工作。

(当前为"android:switcher:" + containerId + ":" + i ")

那么使用方法是在得到容器之后:

ViewPager viewPager = (ViewPager) view.findViewById(R.id.view_pager);
cleanBackStack(viewPager.getId());