效果
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
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?