作者:波波利一_830 | 来源:互联网 | 2023-10-10 20:01
该库被使用较多,而其manual又较为简单。所以决定分析一下,先从几个问题入手:
icon怎么做到随着下拉的进行而联动旋转的?
通过关系图发现我们所有用到的组件都继承自PullToRefreshBase
对,它就是分析的出发点:
1. 类PullToRefreshBase
onTouchEvent(MotionEvent event) –MotionEvent.ACTION_MOVE – >
pullEvent()
newScrollValue = Math.round(Math.min(initialMotionValue - lastMotionValue, 0) / FRICTION);itemDimension = getHeaderSize();
看的出,将初始位置减去当前移动到的位置 得到位置增量 再除一个摩擦系数(FRICTION),接着
float scale = Math.abs(newScrollValue) / (float) itemDimension;
mHeaderLayout.onPull(scale);
通过header和footer的宽/高度来计算得到一个scale,并调用mHeaderLayout的方法。
注:
1.如果对 PullToRefreshScrollView组件中的xml参数有疑问,一定要看看PullToRefreshBase.init(Context context, AttributeSet attrs)中利用这些参数都干了些啥。
2. LoadingLayout?
在PullToRefreshBase.createLoadingLayout()方法会根据传递的参数(flip or rotate)来创建相应的LoadingLayout,LoadingLayout其有两个子类:RotateLoadingLayout 和 FlipLoadingLayout 分别代表了两种下拉时候所执行的动画所在,这个时候基本上有谱了。
PullToRefreshBase.init()–>createLoadingLayout() –>AnimationStyle.createLoadingLayout()–>RotateLoadingLayout or FlipLoadingLayout.
也就是mHeaderLayout 就是 RotateLoadingLayout or FlipLoadingLayout的对象。
下拉时默认的动画如何替换为自己定义的
以RotateLoadingLayout为例,只需要在两处地方替换自己的实现就可以了。
public class RotateLoadingLayout extends LoadingLayout {static final int ROTATION_ANIMATION_DURATION = 1200;private final Animation mRotateAnimation;private final Matrix mHeaderImageMatrix;private float mRotationPivotX, mRotationPivotY;private final boolean mRotateDrawableWhilePulling;public RotateLoadingLayout(Context context, Mode mode, Orientation scrollDirection, TypedArray attrs) {super(context, mode, scrollDirection, attrs);mRotateDrawableWhilePulling = attrs.getBoolean(R.styleable.PullToRefresh_ptrRotateDrawableWhilePulling, true);mHeaderImage.setScaleType(ScaleType.MATRIX);mHeaderImageMatrix = new Matrix();mHeaderImage.setImageMatrix(mHeaderImageMatrix);/*** mRotateAnimation 是在手下拉结束后 加载中的动画效果,* 可以替换为自己的动画*/mRotateAnimation = new RotateAnimation(0, 720, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,0.5f);mRotateAnimation.setInterpolator(ANIMATION_INTERPOLATOR);mRotateAnimation.setDuration(ROTATION_ANIMATION_DURATION);mRotateAnimation.setRepeatCount(Animation.INFINITE);mRotateAnimation.setRepeatMode(Animation.RESTART);}public void onLoadingDrawableSet(Drawable imageDrawable) {if (null != imageDrawable) {mRotationPivotX = Math.round(imageDrawable.getIntrinsicWidth() / 2f);mRotationPivotY = Math.round(imageDrawable.getIntrinsicHeight() / 2f);}}protected void onPullImpl(float scaleOfLayout) {/*** 这个函数里是下拉过程中的联动动画,* 这里根据scaleOfLayout提供的值来在不同阶段展现不同的效果动画*/float angle;if (mRotateDrawableWhilePulling) {angle = scaleOfLayout * 90f;} else {angle = Math.max(0f, Math.min(180f, scaleOfLayout * 360f - 180f));}mHeaderImageMatrix.setRotate(angle, mRotationPivotX, mRotationPivotY);mHeaderImage.setImageMatrix(mHeaderImageMatrix);}@Overrideprotected void refreshingImpl() {mHeaderImage.startAnimation(mRotateAnimation);}@Overrideprotected void resetImpl() {mHeaderImage.clearAnimation();resetImageRotation();}private void resetImageRotation() {if (null != mHeaderImageMatrix) {mHeaderImageMatrix.reset();mHeaderImage.setImageMatrix(mHeaderImageMatrix);}}@Overrideprotected void pullToRefreshImpl() {}@Overrideprotected void releaseToRefreshImpl() {}@Overrideprotected int getDefaultDrawableResId() {return R.drawable.default_ptr_rotate;}}