我正在使用兼容性库中的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) {
        }
    }
}

当前回答

1.首先,您必须在Pageradapter类中设置getItemposition方法 2.您必须阅读您的视图寻呼机的确切位置 3.然后将该位置作为新位置的数据位置发送 4.在setonPageChange监听器中写入更新按钮的点击监听器

我修改了程序代码,只设置了特定的位置元素

public class MyActivity extends Activity {

private ViewPager myViewPager;
private List<String> data;
public int location=0;
public Button updateButton;
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

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

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

      updateButton = (Button) findViewById(R.id.update);

    myViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int i, float v, int i2) {
             //Toast.makeText(MyActivity.this, i+"  Is Selected  "+data.size(), Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onPageSelected( int i) {
          // here you will get the position of selected page
            final int k = i;
             updateViewPager(k);

        }

        @Override
        public void onPageScrollStateChanged(int i) {

        }
    });
}

private void updateViewPager(final int i) {  
    updateButton.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {

            Toast.makeText(MyActivity.this, i+"  Is Selected  "+data.size(), Toast.LENGTH_SHORT).show();
            data.set(i, "Replaced "+i);         
            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 int getItemPosition(Object object) {
        return POSITION_NONE;
    }

    @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) {
    }
}
}

其他回答

我遇到过类似的问题,我有四个页面,其中一个页面更新了其他三个页面的视图。我能够更新widget (SeekBars, TextViews等)上的页面相邻的当前页面。当调用mTabsAdapter.getItem(position)时,最后两个页面将有未初始化的小部件。

为了解决我的问题,我在调用getItem(位置)之前使用了setSelectedPage(索引)。这将实例化页面,使我能够更改每个页面上的值和小部件。

在所有的更新之后,我将使用setSelectedPage(位置),然后是notifyDataSetChanged()。

您可以在主更新页面的ListView中看到轻微的闪烁,但并不明显。我还没有完全测试它,但它确实解决了我眼前的问题。

我只是把这个答案贴出来,以防其他人觉得有用。为了做完全相同的事情,我只是从兼容性库中获取了ViewPager和PagerAdapter的源代码,并在我的代码中编译它(您需要整理所有错误并导入,但这肯定是可以做到的)。

然后,在CustomViewPager中,创建一个名为updateViewAt(int position)的方法。视图本身可以从ViewPager类中定义的ArrayList mItems中获得(您需要在实例化项目时为视图设置一个Id,并将这个Id与updateViewAt()方法中的位置进行比较)。然后可以根据需要更新视图。

This is for all those like me, which need to update the Viewpager from a service (or other background thread) and none of the proposals have worked: After a bit of logchecking i realized, that the notifyDataSetChanged() method never returns. getItemPosition(Object object) is called an all ends there without further processing. Then i found in the docs of the parent PagerAdapter class (is not in the docs of the subclasses), "Data set changes must occur on the main thread and must end with a call to notifyDataSetChanged() ". So, the working solution in this case was (using FragmentStatePagerAdapter and getItemPosition(Object object) set to return POSITION_NONE) :

然后调用notifyDataSetChanged():

runOnUiThread(new Runnable() {
         @Override
         public void run() {
             pager.getAdapter().notifyDataSetChanged();
         }
     });

在我的情况下,每次片段进入onCreateView,我重新启动值处理空值或空值,如:

if (var == null) {
    var = new Something();
}

if (list.isEmpty()) {
    list = new ArrayList<MyItem>();
}

if (myAdapter == null) {
    myAdapter = new CustomAdapter();
    recyclerView.setAdapter(myAdapter);
}

// etc...

Fragment类可以在每次更改时进入onCreateView,并在运行时从UI返回到视图。

好了,伙计们,我用instantiateItem找到了一个解决方案。11年后再看这个视频的人:

 viewModel.mImage.observe(this, imagePath -> {
            int pos = binding.sliderIntro.getCurrentPagePosition();
            adapter.editList(pos, imagePath);
            if (binding.sliderIntro.findViewWithTag("" + pos) != null)
                adapter.instantiateItem(binding.sliderIntro.findViewWithTag("" + pos), pos);
        });

以及您的适配器:

 public void editList(int position, String imagePath) {
        this.sliderItems.set(position, imagePath);
    }

and:

  @Override
    public void onBindViewHolder(IntroSliderAdapterViewHolder viewHolder, final int position) {
            viewHolder.itemView.setTag("" + position);
       
    }