1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.gallery3d.ui;
import com.android.gallery3d.ui.PositionRepository.Position;
import com.android.gallery3d.util.GalleryUtils;
import android.opengl.Matrix;
import javax.microedition.khronos.opengles.GL11;
import javax.microedition.khronos.opengles.GL11ExtensionPack;
// This class does the overscroll effect.
class Paper {
private static final String TAG = "Paper";
private static final int ROTATE_FACTOR = 4;
private OverscrollAnimation mAnimationLeft = new OverscrollAnimation();
private OverscrollAnimation mAnimationRight = new OverscrollAnimation();
private int mWidth, mHeight;
private float[] mMatrix = new float[16];
public void overScroll(float distance) {
if (distance < 0) {
mAnimationLeft.scroll(-distance);
} else {
mAnimationRight.scroll(distance);
}
}
public boolean advanceAnimation(long currentTimeMillis) {
return mAnimationLeft.advanceAnimation(currentTimeMillis)
| mAnimationRight.advanceAnimation(currentTimeMillis);
}
public void setSize(int width, int height) {
mWidth = width;
mHeight = height;
}
public float[] getTransform(Position target, Position base,
float scrollX, float scrollY) {
float left = mAnimationLeft.getValue();
float right = mAnimationRight.getValue();
float screenX = target.x - scrollX;
float t = ((mWidth - screenX) * left - screenX * right) / (mWidth * mWidth);
// compress t to the range (-1, 1) by the function
// f(t) = (1 / (1 + e^-t) - 0.5) * 2
// then multiply by 90 to make the range (-45, 45)
float degrees =
(1 / (1 + (float) Math.exp(-t * ROTATE_FACTOR)) - 0.5f) * 2 * -45;
Matrix.setIdentityM(mMatrix, 0);
Matrix.translateM(mMatrix, 0, mMatrix, 0, base.x, base.y, base.z);
Matrix.rotateM(mMatrix, 0, degrees, 0, 1, 0);
Matrix.translateM(mMatrix, 0, mMatrix, 0,
target.x - base.x, target.y - base.y, target.z - base.z);
return mMatrix;
}
}
class OverscrollAnimation {
private static final String TAG = "OverscrollAnimation";
private static final long START_ANIMATION = -1;
private static final long NO_ANIMATION = -2;
private static final long ANIMATION_DURATION = 500;
private long mAnimationStartTime = NO_ANIMATION;
private float mVelocity;
private float mCurrentValue;
public void scroll(float distance) {
mAnimationStartTime = START_ANIMATION;
mCurrentValue += distance;
}
public boolean advanceAnimation(long currentTimeMillis) {
if (mAnimationStartTime == NO_ANIMATION) return false;
if (mAnimationStartTime == START_ANIMATION) {
mAnimationStartTime = currentTimeMillis;
return true;
}
long deltaTime = currentTimeMillis - mAnimationStartTime;
float t = deltaTime / 100f;
mCurrentValue *= Math.pow(0.5f, t);
mAnimationStartTime = currentTimeMillis;
if (mCurrentValue < 1) {
mAnimationStartTime = NO_ANIMATION;
mCurrentValue = 0;
return false;
}
return true;
}
public float getValue() {
return mCurrentValue;
}
}
|