2012-04-05 95 views

回答

10

其實很簡單。您需要擴展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); 
    } 
} 

乾杯

+0

當我試圖通過Git的下載項目時,Eclipse不能在那裏找到的所有項目。我嘗試下載爲Zip並直接從git下載。同樣的問題。也試圖配置你的項目,但有很多錯誤 – 2012-04-05 10:59:08

+0

我不喜歡在我的倉庫中有項目文件。但這應該不成問題,因爲您可以簡單地執行以下操作:1.以zip形式下載。 2.解壓縮到您選擇的文件夾。 3.在eclipse中執行新建 - > Android項目 - >從現有源創建項目。 4.將構建目標設置爲android 4或從清單中刪除硬件加速。也許你還需要清理項目.. – Renard 2012-04-05 11:15:19

+0

有了一些更正,我得到你的代碼工作,但還有一個問題:如何改變位置選定的行?另外,如何使行相互重疊。像這樣:[鏈接](http://img6.imageshack.us/img6/1375/snor1.jpg) – 2012-04-10 08:44:38