快速滑动时奇怪的视图寻呼机行为
Strange view pager behavior when swiping fast
我好像遇到了一个奇怪的问题。
当我滑动时,我的 ViewPager 工作得非常好 "slowly"(例如,我的滑动之间有间隙 - 甚至半秒)但是如果我滑动得足够快(2-3 页一次)第二),在 3-4 页之后,我观察到以下行为之一:
- 有时好像跳回了几页
- 或者再次显示同一页面
- 或者显示一个白色页面(我想那是一个空白页面,因为我的背景是白色的)
- 或将自己固定在两页之间(每页显示一半)。
这是我的适配器:
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
private SparseArray<String> _fragmentHeaders = new SparseArray<String>();
private SparseArray<Fragment> _fragments = new SparseArray<Fragment>();
private Integer _previousCount = null;
private boolean _isDatasetBeingChanged;
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
registerDataSetObserver(new DataSetObserver() {
@Override
public void onChanged() {
_previousCount = getContentCount();
super.onChanged();
}
});
}
public Fragment getExistingItem(int position) {
Fragment fragment = _fragments.get(position, null);
if (fragment != null) {
return fragment;
}
return null;
}
@Override
public Fragment getItem(int position) {
TType content = findContentWithPosition(position);
if (_fragmentHeaders.get(position, null) == null) {
_fragmentHeaders.put(position, content.getTitle());
}
Fragment fragment = createFragmentFromType(content);
_fragments.put(position, fragment);
return fragment;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
RoboFragment fragment = (RoboFragment) object;
if (fragment != null) {
fragment.onDestroy();
}
if (_fragmentHeaders.get(position, null) != null) {
_fragmentHeaders.remove(position);
}
if (_fragments.get(position, null) != null) {
_fragments.remove(position);
}
super.destroyItem(container, position, object);
}
@Override
public int getCount() {
int count = getContentCount();
if (_isDatasetBeingChanged) {
return count;
}
if (_previousCount != null && _previousCount != count) {
_isDatasetBeingChanged = true;
notifyDataSetChanged();
}
_previousCount = count;
_isDatasetBeingChanged = false;
return _previousCount;
}
@Override
public CharSequence getPageTitle(int position) {
return _fragmentHeaders.get(position);
}
}
正如我提到的,如果我慢慢滑动,它就会起作用。我只是像这样添加适配器:
_sectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
_viewPager.setAdapter(_sectionsPagerAdapter);
有人以前看过这个吗?我正在使用支持库的第 22 版,并且 SDK 方面的所有内容都是最新的。
我已经在 5.0 和 4.4 版本上测试了这个行为,并且都出现了这个问题。
非常感谢,
p.s。问题不在于调用 notifyDataSetChanged()。删除它没有任何效果,即使基础页数没有改变也会发生这种情况。
更新 1:
我看到这个 Google 页面似乎描述了我在这里提到的问题:
http://code.google.com/p/android-developer-preview/issues/detail?id=1190
唯一的区别是,无论有没有 CardView,我都会得到同样的错误,所以我认为问题不限于卡片视图。
虽然没有解决这个问题,但如果有人能提供帮助,我将不胜感激。
在你的getItem方法中,你的意思是每次都创建一个新的片段吗? _fragments 是什么?而是尝试:
@Override
public Fragment getItem(int position) {
Fragment fragment = _fragments.get(position);
if (fragment == null) {
fragment = createFragmentFromType(content);
_fragments.put(position, fragment);
//save your fragment names, or better, create a custom fragment with a getTitle method.
}
return fragment;
}
对于您的 getCount() 方法,请尝试:
@Override
public int getCount() {
return _fragments.size();
}
取消对 destroyItem() 的重写,似乎过于复杂且不必要。
我在对 ViewPager 的源代码进行了数小时的调试后发现了这个问题。问题是我的片段包含一个也在监听触摸事件的视图。当以正常速度滚动时,两者不会相互干扰(ViewPager 中有一个 Runnable() 我建议查看并了解它与滚动的交互,并了解 VP 中的速度和“页面跳转”操作)但是当我滚动事实时,VP onTouch
中的可运行和速度的组合不会很好地符合我的观点。
解决方案是删除正在监听 onTouch
的内部视图。虽然这是一个极端的措施,并且改变了我的代码和布局的一些相当重要的部分,但我实在太害怕复制整个 VP 的源代码并更改导致问题的部分。
我好像遇到了一个奇怪的问题。
当我滑动时,我的 ViewPager 工作得非常好 "slowly"(例如,我的滑动之间有间隙 - 甚至半秒)但是如果我滑动得足够快(2-3 页一次)第二),在 3-4 页之后,我观察到以下行为之一:
- 有时好像跳回了几页
- 或者再次显示同一页面
- 或者显示一个白色页面(我想那是一个空白页面,因为我的背景是白色的)
- 或将自己固定在两页之间(每页显示一半)。
这是我的适配器:
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
private SparseArray<String> _fragmentHeaders = new SparseArray<String>();
private SparseArray<Fragment> _fragments = new SparseArray<Fragment>();
private Integer _previousCount = null;
private boolean _isDatasetBeingChanged;
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
registerDataSetObserver(new DataSetObserver() {
@Override
public void onChanged() {
_previousCount = getContentCount();
super.onChanged();
}
});
}
public Fragment getExistingItem(int position) {
Fragment fragment = _fragments.get(position, null);
if (fragment != null) {
return fragment;
}
return null;
}
@Override
public Fragment getItem(int position) {
TType content = findContentWithPosition(position);
if (_fragmentHeaders.get(position, null) == null) {
_fragmentHeaders.put(position, content.getTitle());
}
Fragment fragment = createFragmentFromType(content);
_fragments.put(position, fragment);
return fragment;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
RoboFragment fragment = (RoboFragment) object;
if (fragment != null) {
fragment.onDestroy();
}
if (_fragmentHeaders.get(position, null) != null) {
_fragmentHeaders.remove(position);
}
if (_fragments.get(position, null) != null) {
_fragments.remove(position);
}
super.destroyItem(container, position, object);
}
@Override
public int getCount() {
int count = getContentCount();
if (_isDatasetBeingChanged) {
return count;
}
if (_previousCount != null && _previousCount != count) {
_isDatasetBeingChanged = true;
notifyDataSetChanged();
}
_previousCount = count;
_isDatasetBeingChanged = false;
return _previousCount;
}
@Override
public CharSequence getPageTitle(int position) {
return _fragmentHeaders.get(position);
}
}
正如我提到的,如果我慢慢滑动,它就会起作用。我只是像这样添加适配器:
_sectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
_viewPager.setAdapter(_sectionsPagerAdapter);
有人以前看过这个吗?我正在使用支持库的第 22 版,并且 SDK 方面的所有内容都是最新的。
我已经在 5.0 和 4.4 版本上测试了这个行为,并且都出现了这个问题。
非常感谢,
p.s。问题不在于调用 notifyDataSetChanged()。删除它没有任何效果,即使基础页数没有改变也会发生这种情况。
更新 1:
我看到这个 Google 页面似乎描述了我在这里提到的问题:
http://code.google.com/p/android-developer-preview/issues/detail?id=1190
唯一的区别是,无论有没有 CardView,我都会得到同样的错误,所以我认为问题不限于卡片视图。
虽然没有解决这个问题,但如果有人能提供帮助,我将不胜感激。
在你的getItem方法中,你的意思是每次都创建一个新的片段吗? _fragments 是什么?而是尝试:
@Override
public Fragment getItem(int position) {
Fragment fragment = _fragments.get(position);
if (fragment == null) {
fragment = createFragmentFromType(content);
_fragments.put(position, fragment);
//save your fragment names, or better, create a custom fragment with a getTitle method.
}
return fragment;
}
对于您的 getCount() 方法,请尝试:
@Override
public int getCount() {
return _fragments.size();
}
取消对 destroyItem() 的重写,似乎过于复杂且不必要。
我在对 ViewPager 的源代码进行了数小时的调试后发现了这个问题。问题是我的片段包含一个也在监听触摸事件的视图。当以正常速度滚动时,两者不会相互干扰(ViewPager 中有一个 Runnable() 我建议查看并了解它与滚动的交互,并了解 VP 中的速度和“页面跳转”操作)但是当我滚动事实时,VP onTouch
中的可运行和速度的组合不会很好地符合我的观点。
解决方案是删除正在监听 onTouch
的内部视图。虽然这是一个极端的措施,并且改变了我的代码和布局的一些相当重要的部分,但我实在太害怕复制整个 VP 的源代码并更改导致问题的部分。