扩展系统的gallery,我们需要重写两个方法,getChildStaticTransformation()和getChildDrawingOrder(),同时,要使这两个方法能被调用,必须执行如下两行代码,文档上面是有说明的。
// Enable set transformation.
this.setStaticTransformationsEnabled(true);
// Enable set the children drawing order.
this.setChildrenDrawingOrderEnabled(true);
getChildDrawingOrder的实现
@Override
protected int getChildDrawingOrder(int childCount, int i)
{
// Current selected index.
int selectedIndex = getSelectedItemPosition() - getFirstVisiblePosition();
if (selectedIndex < 0)
{
return i;
}
if (i < selectedIndex)
{
return i;
}
else if (i >= selectedIndex)
{
return childCount - 1 - i + selectedIndex;
}
else
{
return i;
}
}
这里为什么要计算drawing order,因为从上图中看到,我们的效果是:中间左边的顺序是 0, 1, 2,右边的child覆盖左边的child,而在中间右边的顺序正好相反,左边的覆盖右边的,所以我们要重写这个方法,而gallery自身的实现,不是这种效果。
getChildStaticTransformation的实现
@Override
protected boolean getChildStaticTransformation(View child, Transformation t)
{
super.getChildStaticTransformation(child, t);
final int childCenter = getCenterOfView(child);
final int childWidth = child.getWidth();
int rotationAngle = 0;
t.clear();
t.setTransformationType(Transformation.TYPE_MATRIX);
// If the child is in the center, we do not rotate it.
if (childCenter == mCoveflowCenter)
{
transformImageBitmap(child, t, 0);
}
else
{
// Calculate the rotation angle.
rotationAngle = (int)(((float)(mCoveflowCenter - childCenter) / childWidth) * mMaxRotationAngle);
// Make the angle is not bigger than maximum.
if (Math.abs(rotationAngle) > mMaxRotationAngle)
{
rotationAngle = (rotationAngle < 0) ? -mMaxRotationAngle : mMaxRotationAngle;
}
transformImageBitmap(child, t, rotationAngle);
}
return true;
}
这个方法就是根据child来计算它的transformation(变换),我们需要去修改它里面的matrix,从而达到旋转的效果。根据位置和角度来计算的matrix的方法写在另外一个方法transformImageBitmap中实现。
transformImageBitmap()的实现
private void transformImageBitmap(View child, Transformation t, int rotationAngle)
{
mCamera.save();
final Matrix imageMatrix = t.getMatrix();
final int imageHeight = child.getHeight();
final int imageWidth = child.getWidth();
final int rotation = Math.abs(rotationAngle);
// Zoom on Z axis.
mCamera.translate(0, 0, mMaxZoom);
if (rotation < mMaxRotationAngle)
{
float zoomAmount = (float)(mMaxZoom + rotation * 1.5f);
mCamera.translate(0, 0, zoomAmount);
}
// Rotate the camera on Y axis.
mCamera.rotateY(rotationAngle);
// Get the matrix from the camera, in fact, the matrix is S (scale) transformation.
mCamera.getMatrix(imageMatrix);
// The matrix final is T2 * S * T1, first translate the center point to (0, 0),
// then scale, and then translate the center point to its original point.
// T * S * T
// S * T1
imageMatrix.postTranslate((imageWidth / 2), (imageHeight / 2));
// (T2 * S) * T1
imageMatrix.preTranslate(-(imageWidth / 2), -(imageHeight / 2));
mCamera.restore();
}
这里,简单说明一个,
第一,先在Z轴上平称,其实就是得到一个缩放矩阵变换,我这里简写为 S。
第二,是利用camera这个类来生成matrix,其实mCamera.rotateY就是围绕Y轴旋转。这里生成了一个旋转矩阵,记为 R 。经过这两步,此时调用mCamera.getMatrix(imageMatrix); 从Camera中得到matrix,此时这个矩阵中包含了S * R。
第三,最关键是下面两句
// S * T1
imageMatrix.postTranslate((imageWidth / 2), (imageHeight / 2));
// (T2 * S) * T1
imageMatrix.preTranslate(-(imageWidth / 2), -(imageHeight / 2));
由于这里涉及到旋转与缩放,缩放操作其实应该是针对Child中点进行了,这里就是作一个平衡操作,我们必须是先平移,再缩放,再平移回原来位置,所以,我们最终的矩阵变换应该是这样的:
M = T * (S * R) * T1 (这里在T1表示与T相反)。