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

当前回答

在我的情况下,每次片段进入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返回到视图。

其他回答

一个更简单的方法:使用FragmentPagerAdapter,并将页面视图包装到片段上。它们确实会更新

有几种方法可以实现这一点。

第一种方法更简单,但效率更低。

重写PagerAdapter中的getItemPosition,如下所示:

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

这样,当您调用notifyDataSetChanged()时,视图分页器将删除所有视图并重新加载它们。这样就得到了装填效果。

第二个选项是Alvaro Luis Bustamante(以前是alvarolb)建议的,在实例化一个新视图时使用instantiateItem()中的setTag()方法。然后,您可以使用findViewWithTag()来查找要更新的视图,而不是使用notifyDataSetChanged()。

结论

如果您有很多视图,或者希望支持修改任何特定的项和/或视图(在任何时候快速),那么第二种方法(标记)是非常灵活和高性能的,因为它可以防止重新创建所有未修改的视图。 (alvarolb的原创研究值得称赞。)

但如果你的应用只有“刷新”功能(甚至不允许单个条目的更改),或者只有很少的条目,请使用第一种方法,因为它节省了开发时间。

我使用Tablayout与ViewPagerAdapter。为了在片段之间传递数据或在片段之间进行通信,使用下面的代码,它工作得非常好,并在片段出现时刷新它。第二段点击按钮里面写下面的代码。

b.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            String text=e1.getText().toString(); // get the text from EditText

            // move from one fragment to another fragment on button click
            TabLayout tablayout = (TabLayout) getActivity().findViewById(R.id.tab_layout); // here tab_layout is the id of TabLayout which is there in parent Activity/Fragment
            if (tablayout.getTabAt(1).isSelected()) { // here 1 is the index number of second fragment i-e current Fragment

                LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(getContext());
                Intent i = new Intent("EDIT_TAG_REFRESH");
                i.putExtra("MyTextValue",text);
                lbm.sendBroadcast(i);

            }
            tablayout.getTabAt(0).select(); // here 0 is the index number of first fragment i-e to which fragment it has to moeve

        }
    });

下面是必须在第一个片段(在我的情况下)i-e中接收片段的代码。

MyReceiver r;
Context context;
String newValue;
public void refresh() {
    //your code in refresh.
    Log.i("Refresh", "YES");
}
public void onPause() {
    super.onPause();

    LocalBroadcastManager.getInstance(context).unregisterReceiver(r);
}
public void onResume() {
    super.onResume();
    r = new MyReceiver();
    LocalBroadcastManager.getInstance(getActivity()).registerReceiver(r,
            new IntentFilter("EDIT_TAG_REFRESH"));
} // this code has to be written before onCreateview()


 // below code can be written any where in the fragment
 private class MyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
    PostRequestFragment.this.refresh();
        String action = intent.getAction();
        newValue=intent.getStringExtra("MyTextValue");
        t1.setText(newValue); // upon Referesh set the text
    }
}

我想,我有ViewPager的逻辑。

如果我需要刷新一组页面并基于新的数据集显示它们,我调用notifyDataSetChanged()。 然后,ViewPager对getItemPosition()进行多次调用,将Fragment作为对象传递给那里。这个片段可以来自旧数据集(我想要丢弃的数据集),也可以来自新数据集(我想要显示的数据集)。因此,我重写了getItemPosition(),在那里我必须以某种方式确定我的片段是来自旧数据集还是来自新数据集。

In my case I have a 2-pane layout with a list of top items on the left pane and a swipe view (ViewPager) on the right. So, I store a link to my current top item inside my PagerAdapter and also inside of each instantiated page Fragment. When the selected top item in the list changes, I store the new top item in PagerAdapter and call notifyDataSetChanged(). And in the overridden getItemPosition() I compare the top item from my adapter to the top item from my fragment. And only if they are not equal, I return POSITION_NONE. Then, PagerAdapter reinstantiates all the fragments that have returned POSITION_NONE.

请注意。存储顶部项id而不是引用可能是一个更好的主意。

下面的代码片段有点示意图,但我从实际工作的代码中改编了它。

public class SomeFragment extends Fragment {
  private TopItem topItem;
}

public class SomePagerAdapter extends FragmentStatePagerAdapter {
  private TopItem topItem;

  public void changeTopItem(TopItem newTopItem) {
    topItem = newTopItem;
    notifyDataSetChanged();
  }

  @Override
  public int getItemPosition(Object object) {
    if (((SomeFragment) object).getTopItemId() != topItem.getId()) {
      return POSITION_NONE;
    }
    return super.getItemPosition(object);
  }
}

感谢之前所有的研究人员!

你可以像这样在Viewpager上添加分页器转换

myPager.setPageTransformer(true, new MapPagerTransform());

在下面的代码中,我改变了我的视图颜色在运行时,当寻呼机滚动

public class MapPagerTransform implements ViewPager.PageTransformer {

    public void transformPage(View view, float position) {
        LinearLayout showSelectionLL = (LinearLayout) view.findViewById(R.id.showSelectionLL);

        if (position < 0) {
            showSelectionLL.setBackgroundColor(Color.WHITE);
        } else if (position > 0) {
            showSelectionLL.setBackgroundColor(Color.WHITE);
        } else {
            showSelectionLL.setBackgroundColor(Color.RED);
        }
    }
}