Reputation: 4816
What's up guys, I need a little help with this one. I'm trying to achieve a simple(but not really) folding animation on a listview that is being scrolled. Basically, I'm attempting to fold the listview's first visible child backward as if a sheet of paper is being folded downward along the X axis. This goes on on continuously as the user scrolls up and down the list. This is my first time playing around with Matrix animations and Android's camera from the graphics api, so I'm definitely off the mark here.
This is the effect I'm trying to achieve
And this is the effect I'm getting.
I want the animation to begin at the origin(0,0) but both the left and right side, animating from the top of the list item instead of the upper left corner. I'm not very familiar with matrix translations or animations so If anyone much more experience with these techniques than myself can shed some knowledge, it'll be greatly appreciated.
Basically I'm overriding the onDrawChild method of ListView, grabbing the child's bitmap from a drawing cache, and using a matrix to perform the animation. The lighting and camera implementation is code that I took from another sample app in order to get the animation to look as 3D as possible.
I tried playing around with the ListView animations library, but without much luck. I also tried to hack together a solution using code from the developer guides here that uses object animators to achieve a nice little card flip animation, but it started feeling a bit hacky and I couldn't quite get it the way I wanted.
Here's my current implementation. If anyone can shed some light or direction on this one, or maybe if anyone wrote an awesome library that I didn't come across on my searches, please feel free to share. Thanks
@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
View first = getChildAt(0);
if (child == first) {
if (child.getTop() < 0) {
Bitmap bitmap = getChildDrawingCache(child);
final int top = child.getTop();
child.getRight();
child.getBottom();
child.getLeft();
final int childCenterY = child.getHeight() / 2;
// final int childCenterX = child.getWidth() / 2;
final int parentCenterY = getHeight() / 2; // center point of
// child relative to list
final int absChildCenterY = child.getTop() + childCenterY;
// final int bottom = child.getBottom();
// distance of child center to the list center final int
int distanceY = parentCenterY - absChildCenterY;
final int r = getHeight() / 2;
if (mAnimate) {
prepareMatrix(mMatrix, distanceY, r);
mMatrix.preTranslate(0, top);
mMatrix.postTranslate(0, -top);
}
canvas.drawBitmap(bitmap, mMatrix, mPaint);
}
else {
super.drawChild(canvas, child, drawingTime);
}
} else {
super.drawChild(canvas, child, drawingTime);
}
return false;
}
private void prepareMatrix(final Matrix outMatrix, int distanceY, int r) { // clip
// the
// distance
final int d = Math.min(r, Math.abs(distanceY)); //
// circle formula
final float translateZ = (float) Math.sqrt((r * r) - (d * d));
double radians = Math.acos((float) d / r);
double degree = 45 - (180 / Math.PI) * radians;
// double degree = -180;
mCamera.save();
mCamera.translate(0, 0, r - translateZ);
mCamera.rotateX((float) degree);
if (distanceY < 0) {
degree = 360 - degree;
}
mCamera.rotateY((float) degree);
mCamera.getMatrix(outMatrix);
mCamera.restore();
// highlight elements in the middle
mPaint.setColorFilter(calculateLight((float) degree));
}
private Bitmap getChildDrawingCache(final View child) {
Bitmap bitmap = child.getDrawingCache();
if (bitmap == null) {
child.setDrawingCacheEnabled(true);
child.buildDrawingCache();
bitmap = child.getDrawingCache();
}
return bitmap;
}
private LightingColorFilter calculateLight(final float rotation) {
final double cosRotation = Math.cos(Math.PI * rotation / 180);
int intensity = AMBIENT_LIGHT + (int) (DIFFUSE_LIGHT * cosRotation);
int highlightIntensity = (int) (SPECULAR_LIGHT * Math.pow(cosRotation,
SHININESS));
if (intensity > MAX_INTENSITY) {
intensity = MAX_INTENSITY;
}
if (highlightIntensity > MAX_INTENSITY) {
highlightIntensity = MAX_INTENSITY;
}
final int light = Color.rgb(intensity, intensity, intensity);
final int highlight = Color.rgb(highlightIntensity, highlightIntensity,
highlightIntensity);
return new LightingColorFilter(light, highlight);
}
Upvotes: 1
Views: 1006
Reputation: 1425
has a lot of stuff that's similar to what you want if not exactly what you want. Take a look at how they're defined under jazzy effect and mix and match. I think reverse fly or maybe flip is close to what you want.
Upvotes: 3