效果
ScrollView滚动到最顶端和最底端时,还可以继续拉伸出一片空白区域,手松开后再回弹到正常状态
实现思路
- 到达顶端和底端后,还想继续拉伸,这个可以通过layout方法对Content重新定位就能实现
- 回弹效果,可以通过平移动画TranslateAnimation来实现
- 当内容没到达顶端或底端时,通过ScrollView默认的onTouchEvent处理来正常滚动即可
- 根据ScrollView的大小,ScrollView的滚动距离,ContentView的大小,可以判断控件是否滚动到顶端
核心代码
package com.easing.commons.android.ui.control.scroll;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.TranslateAnimation;
import android.widget.ScrollView;
import com.easing.commons.android.R;
import com.easing.commons.android.manager.Device;
import com.easing.commons.android.ui.dialog.TipBox;
//带回弹效果的ScrollView,拉到顶部和底部时,仍可以继续拉出一部分空白区域,松手后回弹至正常状态
//这个控件没有对padding进行处理,请不要为ScrollView设置padding
@SuppressWarnings("all")
public class BounceScrollView extends ScrollView {
//ScrollView包裹的子View
View contentView;
//记录最近一次正常状态下的控件边界,即没有重定位时的状态
//当控件处于弹性拉伸状态时,最近一次的正常状态,就是刚滑到顶端或底端时的状态
Rect recentNormalBound = new Rect();
//上次点击时的Y坐标
float y;
//动画是否在进行中
TranslateAnimation animation;
boolean isAnimationFinished = true;
//最大宽高
int maxWidth = Integer.MAX_VALUE;
int maxHeight = Integer.MAX_VALUE;
//让控件宽高,保持是某个值的整数倍
int widthRadix = 0;
int heightRadix = 0;
//宽高占屏幕的最大比例
float maxScreenRatioX = 0F;
float maxScreenRatioY = 0F;
public BounceScrollView(Context context) {
this(context, null);
}
public BounceScrollView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
init(context, attributeSet);
}
//初始化,读取属性
protected void init(Context context, AttributeSet attributeSet) {
int screenWidth = Device.screenWidth();
int screenHeight = Device.screenHeight();
TypedArray attrs = context.obtainStyledAttributes(attributeSet, R.styleable.BounceScrollView);
maxWidth = (int) attrs.getDimension(R.styleable.BounceScrollView_maxWidth, Integer.MAX_VALUE);
maxHeight = (int) attrs.getDimension(R.styleable.BounceScrollView_maxHeight, Integer.MAX_VALUE);
widthRadix = (int) attrs.getDimension(R.styleable.BounceScrollView_widthDivision, 0);
heightRadix = (int) attrs.getDimension(R.styleable.BounceScrollView_heightDivision, 0);
maxScreenRatioX = attrs.getFloat(R.styleable.BounceScrollView_maxScreenRatioX, 0);
maxScreenRatioY = attrs.getFloat(R.styleable.BounceScrollView_maxScreenRatioY, 0);
if (maxScreenRatioX > 0)
if (maxScreenRatioX * screenWidth 0)
if (maxScreenRatioY * screenHeight 0)
contentView = getChildAt(0);
super.onFinishInflate();
}
//重写测量方法,以支持最大宽高、整倍宽高功能
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
if (widthMode == MeasureSpec.EXACTLY)
widthSize = widthSize
关注
打赏