我有一个FragmentStatePagerAdapter,每秒刷新一次,为他的某些页面添加新数据。
问题是某些页面有很多内容和垂直滚动,所以每当调用notifyDataSetChanged()时,滚动都会被压缩到他的上层。这是一种非常不正常和烦人的行为。
我在stackoverflow上找到了这个:notifyDataSetChanged() makes the list refresh and scroll jumps back to the top
问题是这些解决方案是针对普通的ViewPager或普通适配器而设计的,并且不能使用FragmentStatePageAdapter或其他东西,因为在尝试它们之后我仍然遇到同样的问题。
这是我的适配器:
public class CollectionPagerAdapter extends FragmentStatePagerAdapter {
public CollectionPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int i) {
Fragment fragment = new ObjectFragment();
Bundle args = new Bundle();
args.putString(ObjectFragment.ARG_TEXT, children[i]);
fragment.setArguments(args);
return fragment;
}
@Override
public int getCount() {
return infoTitlesArray.length;
}
@Override
public CharSequence getPageTitle(int position) {
return infoTitlesArray[position];
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
ViewPager有问题:
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.PagerTitleStrip
android:id="@+id/pager_title_strip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:paddingTop="4dp"
android:paddingBottom="4dp"
style="@style/CustomPagerTitleStrip"/>
</android.support.v4.view.ViewPager>
片段的布局:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbarSize="5dip"
style="@style/CustomScrollBar">
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="left"
android:textSize="16sp"
android:padding="5dp"
style="@style/CustomTextView"/>
</ScrollView>
片段的java代码:
public static class ObjectFragment extends Fragment {
public static final String ARG_TEXT = "object";
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_collection_object, container, false);
Bundle args = getArguments();
TextView tv = ((TextView) rootView.findViewById(R.id.text));
tv.setText(Html.fromHtml(args.getString(ARG_TEXT)));
return rootView;
}
}
答案 0 :(得分:1)
编辑:
我创建了一个演示项目。这是一些重要的部分。
使用FragmentStatePagerAdapter
子类。
我们需要一个FragmentStatePagerAdapter
基类来保存片段的状态。
将ScrollView
的滚动位置保存在onSaveInstanceState()
中,并在(重新)创建片段视图时将滚动位置设置为保存的值。
现在我们正在保存/恢复片段状态,我们将滚动位置置于该状态:
@Override
public void onSaveInstanceState(Bundle outState) {
int scrollY = scrollView.getScrollY();
outState.putInt("scrollY", scrollY);
super.onSaveInstanceState(outState);
}
并在onCreateView()
中恢复
if (savedInstanceState != null) {
final int scrollY = savedInstanceState.getInt("scrollY");
scrollView.post(new Runnable() {
@Override
public void run() {
scrollView.setScrollY(scrollY);
}
});
}
为更新设置侦听器通知系统。
我们有一个名为DataUpdateListener
的接口,由片段实现。该活动提供了注册/取消注册方法:
public void addDataUpdateListener(DataUpdateListener listener) {
mListenerMap.put(listener.getPage(), listener);
}
public void removeDataUpdateListener(DataUpdateListener listener) {
mListenerMap.remove(listener.getPage());
}
...和片段寄存器&amp;取消注册活动:
onCreateView()
中的:
((MainActivity) getActivity()).addDataUpdateListener(this);
也
@Override
public void onDestroyView() {
((MainActivity) getActivity()).removeDataUpdateListener(this);
super.onDestroyView();
}
然后,只要数据发生变化,片段都会收到更新通知:
for (int i = 0; i < children.length; i++) {
notifyUpdateListener(i, children[i]);
}
请注意,代码中的任何地方都没有在视图寻呼机适配器上调用onNotifyDataSetChanged()
。
该演示位于https://github.com/klarson2/View-Pager-Data-Update
的GitHub上这是导致滚动的原因:
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
当您致电notifyDataSetChanged()
时,ViewPager
所做的就是询问您如何处理已有的网页。
因此,它会调用getItemPosition
来查明:此页面应该放在哪里?您有三种选择:
返回索引。因此,如果您为第0页返回2,则ViewPager
会将页面从0移动到2。
返回POSITION_UNCHANGED。该页面将保持现在的位置。
返回POSITION_NONE。这意味着不再显示该页面。
一旦ViewPager
知道页面移动到的位置,它就会调用getItem()
来查找页面中的任何空白。
因此,如果您不希望滚动受到干扰,请告诉ViewPager
放置页面的位置,而不是告诉它去除它并创建一个新页面。