【问题标题】:Android: vertical 3d listviewAndroid:垂直 3d 列表视图
【发布时间】:2012-04-05 08:36:47
【问题描述】:

我想制作垂直 3d 列表视图like here,但对于 ImageButtons 并且是免费的。是否有任何库或示例代码?我是 Android 开发新手,所以我不知道如何为这些东西制作动画

【问题讨论】:

    标签: android listview 3d imagebutton


    【解决方案1】:

    其实很简单。您需要扩展 ListView 并覆盖 onDrawChild()。在那里你可以应用 3d 变换矩阵来获得你想要的效果。 我的github 上有一个工作示例 或者你可以看看这个question,它非常相似。

    为方便起见,这是我的 3d ListView 实现:

    public class ListView3d extends ListView {
    
        /** Ambient light intensity */
        private static final int AMBIENT_LIGHT = 55;
        /** Diffuse light intensity */
        private static final int DIFFUSE_LIGHT = 200;
        /** Specular light intensity */
        private static final float SPECULAR_LIGHT = 70;
        /** Shininess constant */
        private static final float SHININESS = 200;
        /** The max intensity of the light */
        private static final int MAX_INTENSITY = 0xFF;
    
        private final Camera mCamera = new Camera();
        private final Matrix mMatrix = new Matrix();
        /** Paint object to draw with */
        private Paint mPaint;
    
        public ListView3d(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        @Override
        protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
            // get top left coordinates
            final int top = child.getTop();
            final int left = child.getLeft();
            Bitmap bitmap = child.getDrawingCache();
            if (bitmap == null) {
                child.setDrawingCacheEnabled(true);
                child.buildDrawingCache();
                bitmap = child.getDrawingCache();
            }
    
            final int centerY = child.getHeight() / 2;
            final int centerX = child.getWidth() / 2;
            final int radius = getHeight() / 2;
            final int absParentCenterY = getTop() + getHeight() / 2;
            final int absChildCenterY = child.getTop() + centerX;
            final int distanceY = absParentCenterY - absChildCenterY;
            final int absDistance = Math.min(radius, Math.abs(distanceY));
    
            final float translateZ = (float) Math.sqrt((radius * radius) - (absDistance * absDistance));
    
            double radians = Math.acos((float) absDistance / radius);
            double degree = 90 - (180 / Math.PI) * radians;
    
            mCamera.save();
            mCamera.translate(0, 0, radius - translateZ);
            mCamera.rotateX((float) degree); // remove this line..
            if (distanceY < 0) {
                degree = 360 - degree;
            }
            mCamera.rotateY((float) degree); // and change this to rotateX() to get a
                                                // wheel like effect
            mCamera.getMatrix(mMatrix);
            mCamera.restore();
    
            // create and initialize the paint object
            if (mPaint == null) {
                mPaint = new Paint();
                mPaint.setAntiAlias(true);
                mPaint.setFilterBitmap(true);
            }
            //highlight elements in the middle
            mPaint.setColorFilter(calculateLight((float) degree));
    
            mMatrix.preTranslate(-centerX, -centerY);
            mMatrix.postTranslate(centerX, centerY);
            mMatrix.postTranslate(left, top);
            canvas.drawBitmap(bitmap, mMatrix, mPaint);
            return false;
        }
    
        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);
        }
    }
    

    干杯

    【讨论】:

    • 当我尝试通过 Git 下载您的项目时,Eclipse 在其中找不到任何项目。我尝试以 Zip 格式直接从 git 下载。同样的问题。也尝试配置您的项目,但出现很多错误
    • 我不喜欢在我的存储库中有项目文件。但这应该没问题,因为您可以简单地执行以下操作: 1. 以 zip 格式下载。 2. 解压到您选择的文件夹。 3.在eclipse中做new->Android Project->Create Project from existing source。 4. 将 Build target 设置为 android 4 或从清单中删除 hardwareacceleration。也许您还需要清理项目..
    • 经过一些更正,我让您的代码正常工作,但还有另一个问题:如何将位置更改为选定的行?另外,如何使行相互重叠。喜欢这里:link
    • ListView.setSelection(int) 将滚动到您选择的位置。对于重叠,您可以使用 mMatrix 来定位子视图。
    • 您可以使用 setChildrenDrawingOrderEnabled() 和覆盖 getChildDrawingOrder() 来更改孩子的绘图顺序。这样,您应该设法获得正确的重叠(绘制顺序基本上取决于 z 值)。至于行之间的空间,您可以尝试增加子视图的 layout-xml 中的填充或边距。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多