描述
直接上图。拖动绳子的时候广告板出现,再拉绳子广告板收起,主要在收和拉得时候表现一种弹性的感觉。
思路
1.通过继承viewgroup来实现,包括2个基本元素:广告板和拉绳
2.通过监听绳子的ontouch事件来获取拉伸广告板的动作
3.通过scroller类来实现view弹性滑动(当然通过延时动画也是一种思路)
实战
1.先把包含广告板和绳子的布局加载到自定义view中
View view = LayoutInflater.from(context).inflate(R.layout.curtain, null, false);
adImg = (ImageView) view.findViewById(R.id.img_curtain_ad);
ropeImg = (ImageView) view.findViewById(R.id.img_curtain_rope);
addView(view);
2.重写绳子的ontouch()方法,监听绳子的动作
@Override
public boolean onTouch(View v, MotionEvent event) {
if (isMove) {
return false;
}
y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
//跟手滑动
scrollBy(0, (int) (mLastY - y));
break;
case MotionEvent.ACTION_UP:
//松手时将布局放到正确的位置,弹性的
if (isOpen) {
mScroller.startScroll(0, mScroller.getFinalY(), 0, adHeight - mScroller.getFinalY(), duration);
} else {
mScroller.startScroll(0, mScroller.getFinalY(), 0, 0 - mScroller.getFinalY(), duration);
}
isOpen = !isOpen;
invalidate();
break;
default:
break;
}
mLastY = y;
return true;
}
3.注意上边scroller的用法,同时要重写computeScroll(),下边是computeScroll()的常用写法
@Override
public void computeScroll() {
//先判断mScroller滚动是否完成
if (mScroller.computeScrollOffset())
{
//这里调用View的scrollTo()完成实际的滚动
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
//必须调用该方法,否则不一定能看到滚动效果
postInvalidate();
}
super.computeScroll();
}
4.最后附上完整的代码
public class CurtainView extends RelativeLayout implements View.OnTouchListener {
private Scroller mScroller;
private ImageView adImg,ropeImg;
private int adHeight;
private float mLastY,y;
//是否动画
private boolean isMove = false;
//是否打开
private boolean isOpen = false;
//动画时间
private static final int duration = 1500;
public CurtainView(Context context) {
super(context);
init(context);
}
public CurtainView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context context) {
Interpolator interpolator = new BounceInterpolator();
mScroller = new Scroller(context, interpolator);
//设置透明背景
this.setBackgroundColor(Color.argb(0, 0, 0, 0));
View view = LayoutInflater.from(context).inflate(R.layout.curtain, null, false);
adImg = (ImageView) view.findViewById(R.id.img_curtain_ad);
ropeImg = (ImageView) view.findViewById(R.id.img_curtain_rope);
addView(view);
//先把广告板一次起来
post(new Runnable() {
@Override
public void run() {
adHeight = adImg.getHeight();
CurtainView.this.scrollTo(0, adHeight);
}
});
ropeImg.setOnTouchListener(this);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if (isMove) {
return false;
}
y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
scrollBy(0, (int) (mLastY - y));
break;
case MotionEvent.ACTION_UP:
if (isOpen) {
mScroller.startScroll(0, mScroller.getFinalY(), 0, adHeight - mScroller.getFinalY(), duration);
} else {
mScroller.startScroll(0, mScroller.getFinalY(), 0, 0 - mScroller.getFinalY(), duration);
}
isOpen = !isOpen;
//必须执行invalidate才能保证computeScroll被调用到
invalidate();
break;
default:
break;
}
mLastY = y;
return true;
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
isMove = true;
} else {
isMove = false;
}
super.computeScroll();
}
}
结论
1.主要是scroller的使用,注意scrollBy和scrollTo的区别
2.项目中使用上边的例子请自行改造