ScrollView在项目中使用的特别多但如果想实现那种下拉或者上滑时带有拉伸感的就需要自己继承ScrollView去重写里面的方法了,今天就实现一下自定义ScrollView。
定义一个名为DefinitionScrollView的类代码如下
package com.ranlegeran.leranfinancial.view;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.ScrollView;
/**
* 创建日期:2019/01/20 on 14:10
* 作 者: RANLEGERAN RANLEGERAN
* 类 名: DefinitionScrollView
* 简 述:自定义ScrollView实现拉伸效果
*/
public class DefinitionScrollView extends ScrollView {
private View mView;
private int mLastY; //上一次y轴方向操作的坐标位置
private Rect mRect = new Rect(); // 用来记录临界状态的左上右下
private boolean isFinishAnimation = true; //判断是否结束动画
public DefinitionScrollView(Context context) {
super(context);
}
public DefinitionScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public DefinitionScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
* 获取子视图
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate();
if (getChildCount() > 0) {
mView = getChildAt(0);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (mView == null || !isFinishAnimation) {
return super.onTouchEvent(event);
}
int eventY = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastY = eventY;
break;
case MotionEvent.ACTION_MOVE:
int dy = eventY - mLastY; // 微小的偏移量
if (isNeedMove()) {
if (mRect.isEmpty()) {
mRect.set(mView.getLeft(),mView.getTop(),mView.getRight(),mView.getBottom()); //记录临界状态的左上右下
}
mView.layout(mView.getLeft(),mView.getTop() + dy / 2, mView.getRight(),mView.getBottom() + dy / 2);
}
mLastY = eventY;
break;
case MotionEvent.ACTION_UP:
//使用平移动画
int translateY = mView.getBottom() - mRect.bottom;
TranslateAnimation translateAnimation = new TranslateAnimation(0, 0, 0, -translateY);
translateAnimation.setDuration(200);
translateAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
isFinishAnimation = false;
}
@Override
public void onAnimationEnd(Animation animation) {
isFinishAnimation = true;
mView.clearAnimation(); //清除动画
mView.layout(mRect.left,mRect.top,mRect.right,mRect.bottom);
mRect.setEmpty();
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
//启动动画
mView.startAnimation(translateAnimation);
break;
}
return super.onTouchEvent(event);
}
private boolean isNeedMove() {
int measuredHeight = mView.getMeasuredHeight(); //获取子视图的高度
int scrollViewMeasuredHeight = this.getMeasuredHeight(); //获取布局的高度
Log.e("TAG","measuredHeight" + measuredHeight);
Log.e("TAG","scrollViewMeasuredHeight" + scrollViewMeasuredHeight);
int dy = measuredHeight - scrollViewMeasuredHeight; //dy>= 0的
int scrollY = this.getScrollY(); //获取用户在y轴方向上的偏移量往上滑+ 往下滑-
if (scrollY <= 0 || scrollY >= dy) {
return true; //按照自定义的DefinitionScrollView方式处理
}
//其他处在临界范围内的返回false 表示仍按照ScrollView的方式处理
return false;
}
}
然后在布局中使用即可
<com.ranlegeran.leranfinancial.view.DefinitionScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none">
</com.ranlegeran.leranfinancial.view.DefinitionScrollView>
```