我有一个包含ViewPager的Activity,它显示N个片段。每个片段都在我的ViewPager自定义适配器中的ArrayList中显示对象的属性(扩展FragmentStatePagerAdapter
)。
该片段具有(除其他外)一个按钮,该按钮应该删除当前显示的片段并使用setCurrentItem(position, true)
滚动到下一个片段,以便在用户向后滚动时,前一个项目消失。我这样做是通过使用这样的(简化):
deleteButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
MyActivity parentActivity = (MyActivity)getActivity();
// First, scroll to next item (smoothly)
parentActivity.pager.setCurrentItem(parentActivity.pager.getCurrentItem()+1, true);
// Database stuff...
doSomeDBOperations();
// Method in Activity that removes the current object (I believe this method is working fine and yes, it calls notifyDataSetChanged())
parent.removeObject(currentObject);
}
});
这具有所需的行为,因为按下删除按钮的片段所代表的对象将被删除,并且viewpager将转到下一页。
我的问题是ViewPager不能平滑滚动,而是“立即跳转”到下一个片段。如果我评论removeObject()
来电,则平滑滚动有效(但该项目未被删除)。我相信它与setCurrentItem()完成平滑滚动动画之前调用的removeObject()
有关吗?
有关如何解决此问题并实现项目删除+平滑滚动的任何想法?如果我的假设是正确的,我怎样才能确保在删除对象之前完成平滑滚动?
编辑1:
我的假设似乎是正确的。如果我把parent.removeObject(currentObject)
放在
// ...inside the previously shown public void onClick(View v)...
confirm.postDelayed(new Runnable() {
@Override
public void run() {
// Method in Activity that removes the current object (I believe this method is working fine and yes, it calls notifyDataSetChanged())
parent.removeObject(currentObject);
}
}, 1000);
以便removeObject()
调用等待一秒钟,它按预期工作:滚动到下一个项目,删除前一个。但这是一个非常难看的解决方法,所以我仍然想要一个更好的方法。
编辑2:
我找到了一个可能的解决方案(见下文)。
答案 0 :(得分:12)
我最终压倒了
public void onPageScrollStateChanged(int state)
方法:
每当用户按下片段中的删除按钮时,监听器在当前项中设置一个bool(标记为删除)并滚动到下一个。
当onPageScrollStateChanged
检测到滚动状态更改为ViewPager.SCROLL_STATE_IDLE
时(在平滑滚动结束时发生),它会检查前一项是否已标记为删除,如果是,则将其从ArrayList并调用notifyDataSetChanged()
。
通过这样做,我设法让ViewPager顺利滚动到下一个位置,并在按下“删除”按钮时删除上一个项目。
编辑:代码段。
@Override
public void onPageScrollStateChanged(int state)
{
switch(state)
{
case ViewPager.SCROLL_STATE_DRAGGING:
break;
case ViewPager.SCROLL_STATE_IDLE:
int previousPosition = currentPosition - 1;
if(previousPosition < 0){
previousPosition = 0;
}
MyItem previousItem = itemList.get(previousPosition);
if(previousItem.isDeleted())
{
deleteItem(previousItem);
// deleteItem() Does some DB operations, then calls itemList.remove(position) and notifyDataSetChanged()
}
break;
case ViewPager.SCROLL_STATE_SETTLING:
break;
}
}
答案 1 :(得分:1)
你试过ViewPager.OnPageChangeListener吗? 我将在OnPageChangeListener.onPageSelected(n + 1)方法中调用removeObject(n)方法。
答案 2 :(得分:1)
我做了一些与众不同的事情,使工作顺利。想法是删除带有动画的当前项目(将其alpha设置为0),然后将左侧或右侧项目(带有动画)水平平移到现在不可见的项目位置。
动画制作完成后,我将进行实际的数据删除和notfyDataSetChanged()
调用。
我将此remove()
方法放入ViewPager
的子类中
public void remove(int position, OnViewRemovedListener onViewRemovedListener) {
final int childCount = getChildCount();
if (childCount > 0) {
View toRemove = getChildAt(position);
int to = toRemove.getLeft();
final PagerAdapter adapter = getAdapter();
toRemove.animate()
.alpha(0)
.setDuration(getResources().getInteger(android.R.integer.config_shortAnimTime))
.setListener(new SimpleAnimatorListener() {
@Override
public void onAnimationEnd(Animator animation) {
if (childCount == 1) {
if (onViewRemovedListener != null) onViewRemovedListener.onRemoved(position, -1);
if (adapter!= null) adapter.notifyDataSetChanged();
}
}
})
.start();
if (childCount > 1) {
int newPosition = position + 1 <= childCount - 1 ? position + 1 : position - 1;
View replacement = getChildAt(newPosition);
int from = replacement.getLeft();
replacement.animate()
.setInterpolator(new DecelerateInterpolator())
.setDuration(getResources().getInteger(android.R.integer.config_mediumAnimTime))
.translationX(to - from)
.setListener(new SimpleAnimatorListener() {
@Override
public void onAnimationEnd(Animator animation) {
if (onViewRemovedListener != null) onViewRemovedListener.onRemoved(position, newPosition);
if (adapter!= null) adapter.notifyDataSetChanged();
}
})
.start();
}
}
}
public interface OnViewRemovedListener {
void onRemoved(int position, int newPosition);
}