首先上截图
Animation.gif
就是就是仿照华为手机设置界面的下拉回弹
这个功能实现的核心就是根据手势下拉的距离,动态调用scrollview的layout方法,不停地重新摆放scrollview的位置
这里贴上核心代码以防忘了
在根据xml生成视图之后,首先得到子view
@Override
protected void onFinishInflate()
{
if (getChildCount() > 0)
mView = getChildAt(0);
super.onFinishInflate();
}
touch事件处理
@Override
public boolean onTouchEvent(MotionEvent ev)
{
if (mView != null)
{
int action = ev.getAction();
int cy = (int) ev.getY();
switch (action)
{
case MotionEvent.ACTION_DOWN:
break;
/**
* 跟随手指移动
/
case MotionEvent.ACTION_MOVE:
int dy = cy - y;
if (isFirst)
{
dy = 0;
isFirst = false;
}
y = cy;
if (isNeedMove())
{
if (mRect.isEmpty())
{
/*
* 记录移动前的位置
/
mRect.set(mView.getLeft(), mView.getTop(),
mView.getRight(), mView.getBottom());
}
mView.layout(mView.getLeft(), mView.getTop() + 2 * dy / 3,
mView.getRight(), mView.getBottom() + 2 * dy / 3);
}
break;
/*
* 反弹回去
*/
case MotionEvent.ACTION_UP:
if (!mRect.isEmpty())
{
resetPosition();
}
break;
}
}
return super.onTouchEvent(ev);
}
回弹时运用了一个小技巧
private void resetPosition()
{
Animation animation = new TranslateAnimation(0, 0, mView.getTop(),
mRect.top);
animation.setDuration(200);
animation.setFillAfter(true);
mView.startAnimation(animation);
mView.layout(mRect.left, mRect.top, mRect.right, mRect.bottom);
mRect.setEmpty();
isFirst = true;
}
这里首先使用补间动画完成了scrollview的回弹,由于补间动画只是给用户产生错觉,实际上view并没有移动,所以又调用了view.layout的方法再把view的位置移回去,另外rect的作用是记录scrollview原本的位置。
判断当前位置是否可以下拉也是一个重点
public boolean isNeedMove()
{
int offset = mView.getHeight() - getHeight();
Log.e("bouncescroll", "view.measureheight = "+ mView.getMeasuredHeight() +" view.height = "+ mView.getHeight() + " scrollview.getheight = "+ this.getHeight());
int scrollY = getScrollY();
// 0是顶部,后面那个是底部
if (scrollY == 0 || scrollY == offset)
{
return true;
}
return false;
}
如果当前scrollview的scrolly距离是0则可以下拉
如果当前scrollview的滚动距离和listview的滚动距离一样,亦可以下拉
网友评论