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>