Android 如何实现此ListView动画?

Android 如何实现此ListView动画?,android,listview,animation,folding,Android,Listview,Animation,Folding,怎么了,伙计们,我需要一点帮助。我试图在正在滚动的listview上实现一个简单的(但不是真正的)折叠动画。基本上,我试图向后折叠listview的第一个可见子对象,就像一张纸沿着X轴向下折叠一样。当用户在列表上下滚动时,这种情况会持续出现。这是我第一次在graphics api上玩矩阵动画和Android摄像头,所以我在这里绝对是做不到的 这就是我想要达到的效果 这就是我得到的效果。 我希望动画从原点(0,0)开始,但同时从左侧和右侧开始,从列表项的顶部而不是左上角开始制作动画。我不太熟悉

怎么了,伙计们,我需要一点帮助。我试图在正在滚动的listview上实现一个简单的(但不是真正的)折叠动画。基本上,我试图向后折叠listview的第一个可见子对象,就像一张纸沿着X轴向下折叠一样。当用户在列表上下滚动时,这种情况会持续出现。这是我第一次在graphics api上玩矩阵动画和Android摄像头,所以我在这里绝对是做不到的

这就是我想要达到的效果

这就是我得到的效果。

我希望动画从原点(0,0)开始,但同时从左侧和右侧开始,从列表项的顶部而不是左上角开始制作动画。我不太熟悉矩阵翻译或动画,所以如果有比我更熟悉这些技术的人能学到一些知识,我将不胜感激

基本上,我覆盖了ListView的onDrawChild方法,从图形缓存中获取孩子的位图,并使用矩阵来执行动画。照明和相机实现是我从另一个示例应用程序中获取的代码,目的是使动画看起来尽可能3D

我试着去图书馆玩,但运气不好。我还试着用开发者指南中的代码拼凑出一个解决方案,使用对象动画来实现一个漂亮的小卡片翻转动画,但它开始感觉有点粗糙,我不能完全按照我想要的方式得到它

这是我当前的实现。如果有人能在这方面提供一些启示或方向,或者有人写了一个我在搜索中没有遇到的很棒的库,请随时与我分享。谢谢

   @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);
}
@覆盖
受保护的布尔drawChild(画布、视图子对象、长drawingTime){
首先查看=getChildAt(0);
if(child==第一个){
if(child.getTop()<0){
位图位图=getChildDrawingCache(子级);
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;//中心点
//相对于列表的子对象
final int absChildCenterY=child.getTop()+childCenterY;
//final int bottom=child.getBottom();
//子中心到列表中心的距离最终整数
int distance=parentcentry-abschildcentry;
final int r=getHeight()/2;
if(人体模型){
准备矩阵(m矩阵,距离,r);
mMatrix.预翻译(0,顶部);
mMatrix.postTranslate(0,-顶部);
}
drawBitmap(位图、mMatrix、mPaint);
}
否则{
super.drawChild(canvas,child,drawingTime);
}
}否则{
super.drawChild(canvas,child,drawingTime);
}
返回false;
}
私有void prepareMatrix(final Matrix outMatrix,int distance,int r){//clip
//
//距离
final int d=Math.min(r,Math.abs(distance))//
//圆公式
final float translateZ=(float)Math.sqrt((r*r)-(d*d));
双弧度=数学acos((浮动)d/r);
双度=45-(180/数学π)*弧度;
//双度=-180;
mCamera.save();
翻译(0,0,r-translateZ);
旋转度((浮动)度);
如果(距离<0){
度=360度;
}
旋转度((浮动)度);
mCamera.getMatrix(outMatrix);
mCamera.restore();
//中间突出元素
mPaint.setColorFilter(calculateLight((float)degree));
}
私有位图getChildDrawingCache(最终视图子级){
位图位图=child.getDrawingCache();
如果(位图==null){
setDrawingCacheEnabled(true);
buildDrawingCache();
位图=child.getDrawingCache();
}
返回位图;
}
专用LightingColorFilter calculateLight(最终浮点旋转){
最终双余弦旋转=Math.cos(Math.PI*旋转/180);
int强度=环境光+(int)(漫反射光*旋转);
int highlightIntensity=(int)(镜面反射光*Math.pow(余弦旋转),
光泽);
如果(强度>最大强度){
强度=最大强度;
}
if(高亮度>最大亮度){
highlightIntensity=最大亮度;
}
最终int灯光=Color.rgb(强度、强度、强度);
最终int highlight=Color.rgb(highlightIntensity,highlightIntensity,
强光强度);
返回新的LightingColorFilter(灯光、高光);
}


有很多东西和你想要的相似,如果不是你想要的。看看他们是如何定义爵士效应和混搭。我认为反向飞行或者翻转接近你想要的。

谢谢你,伙计。看起来很有希望。我一定要看看这个!