Android gallery 3D效果
来源:互联网 发布:淘宝备注怎么备注 编辑:程序博客网 时间:2024/05/16 15:34
转:http://www.open-open.com/lib/view/open1350309480336.html
在看了iOS上面的CoverFlow后,感觉效果真的不错,就想在android上面实现一个,这个程序在网上参考了一此核心的代码,当然我添加了一些其他的东西,废话不多话,先看效果,不然就是无图无真相了。
其实实现这个效果很简单,下面作一个简单的介绍
一,创建倒影效果
这个基本思路是:
1,创建一个源图一样的图,利用martrix将图片旋转180度。这个倒影图的高是源图的一半。
Matrix matrix =
new
Matrix();
// 1表示放大比例,不放大也不缩小。
// -1表示在y轴上相反,即旋转180度。
matrix.preScale(
1
, -
1
);
Bitmap reflectionBitmap = Bitmap.createBitmap(
srcBitmap,
0
,
srcBitmap.getHeight() /
2
,
// top为源图的一半
srcBitmap.getWidth(),
// 宽度与源图一样
srcBitmap.getHeight() /
2
,
// 高度与源图的一半
matrix,
false
);
2,创建一个最终效果的图,即源图 + 间隙 + 倒影。
final
int
REFLECTION_GAP =
5
;
Bitmap bitmapWithReflection = Bitmap.createBitmap(
reflectionWidth,
srcHeight + reflectionHeight + REFLECTION_GAP,
Config.ARGB_8888);
3,依次将源图、倒影图绘制在最终的bitmap上面。
// Prepare the canvas to draw stuff.
Canvas canvas =
new
Canvas(bitmapWithReflection);
// Draw the original bitmap.
canvas.drawBitmap(srcBitmap,
0
,
0
,
null
);
// Draw the reflection bitmap.
canvas.drawBitmap(reflectionBitmap,
0
, srcHeight + REFLECTION_GAP,
null
);
Paint paint =
new
Paint();
paint.setAntiAlias(
true
);
LinearGradient shader =
new
LinearGradient(
0
,
srcHeight,
0
,
bitmapWithReflection.getHeight() + REFLECTION_GAP,
0x70FFFFFF
,
0x00FFFFFF
,
TileMode.MIRROR);
paint.setShader(shader);
paint.setXfermode(
new
PorterDuffXfermode(android.graphics.PorterDuff.Mode.DST_IN));
// Draw the linear shader.
canvas.drawRect(
0
,
srcHeight,
srcWidth,
bitmapWithReflection.getHeight() + REFLECTION_GAP,
paint);
二,扩展Gallery
扩展系统的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
));
M = T * (S * R) * T1 (这里在T1表示与T相反)。
三,完整代码
GalleryFlow.java
import
android.content.Context;
import
android.graphics.Camera;
import
android.graphics.Matrix;
import
android.util.AttributeSet;
import
android.view.View;
import
android.view.animation.Transformation;
import
android.widget.Gallery;
public
class
GalleryFlow
extends
Gallery
{
/**
* The camera class is used to 3D transformation matrix.
*/
private
Camera mCamera =
new
Camera();
/**
* The max rotation angle.
*/
private
int
mMaxRotationAngle =
60
;
/**
* The max zoom value (Z axis).
*/
private
int
mMaxZoom = -
120
;
/**
* The center of the gallery.
*/
private
int
mCoveflowCenter =
0
;
public
GalleryFlow(Context context)
{
this
(context,
null
);
}
public
GalleryFlow(Context context, AttributeSet attrs)
{
this
(context, attrs,
0
);
}
public
GalleryFlow(Context context, AttributeSet attrs,
int
defStyle)
{
super
(context, attrs, defStyle);
// Enable set transformation.
this
.setStaticTransformationsEnabled(
true
);
// Enable set the children drawing order.
this
.setChildrenDrawingOrderEnabled(
true
);
}
public
int
getMaxRotationAngle()
{
return
mMaxRotationAngle;
}
public
void
setMaxRotationAngle(
int
maxRotationAngle)
{
mMaxRotationAngle = maxRotationAngle;
}
public
int
getMaxZoom()
{
return
mMaxZoom;
}
public
void
setMaxZoom(
int
maxZoom)
{
mMaxZoom = maxZoom;
}
@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;
}
}
@Override
protected
void
onSizeChanged(
int
w,
int
h,
int
oldw,
int
oldh)
{
mCoveflowCenter = getCenterOfCoverflow();
super
.onSizeChanged(w, h, oldw, oldh);
}
private
int
getCenterOfView(View view)
{
return
view.getLeft() + view.getWidth() /
2
;
}
@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
;
}
private
int
getCenterOfCoverflow()
{
return
(getWidth() - getPaddingLeft() - getPaddingRight()) /
2
+ getPaddingLeft();
}
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();
}
}
BitmapUtil.java
package
com.lee.gallery3d.utils;
import
android.graphics.Bitmap;
import
android.graphics.Bitmap.Config;
import
android.graphics.Canvas;
import
android.graphics.LinearGradient;
import
android.graphics.Matrix;
import
android.graphics.Paint;
import
android.graphics.PixelFormat;
import
android.graphics.PorterDuffXfermode;
import
android.graphics.Shader.TileMode;
import
android.graphics.drawable.Drawable;
public
class
BitmapUtil
{
public
static
Bitmap createReflectedBitmap(Bitmap srcBitmap)
{
if
(
null
== srcBitmap)
{
return
null
;
}
// The gap between the reflection bitmap and original bitmap.
final
int
REFLECTION_GAP =
4
;
int
srcWidth = srcBitmap.getWidth();
int
srcHeight = srcBitmap.getHeight();
int
reflectionWidth = srcBitmap.getWidth();
int
reflectionHeight = srcBitmap.getHeight() /
2
;
if
(
0
== srcWidth || srcHeight ==
0
)
{
return
null
;
}
// The matrix
Matrix matrix =
new
Matrix();
matrix.preScale(
1
, -
1
);
try
{
// The reflection bitmap, width is same with original's, height is half of original's.
Bitmap reflectionBitmap = Bitmap.createBitmap(
srcBitmap,
0
,
srcHeight /
2
,
srcWidth,
srcHeight /
2
,
matrix,
false
);
if
(
null
== reflectionBitmap)
{
return
null
;
}
// Create the bitmap which contains original and reflection bitmap.
Bitmap bitmapWithReflection = Bitmap.createBitmap(
reflectionWidth,
srcHeight + reflectionHeight + REFLECTION_GAP,
Config.ARGB_8888);
if
(
null
== bitmapWithReflection)
{
return
null
;
}
// Prepare the canvas to draw stuff.
Canvas canvas =
new
Canvas(bitmapWithReflection);
// Draw the original bitmap.
canvas.drawBitmap(srcBitmap,
0
,
0
,
null
);
// Draw the reflection bitmap.
canvas.drawBitmap(reflectionBitmap,
0
, srcHeight + REFLECTION_GAP,
null
);
Paint paint =
new
Paint();
paint.setAntiAlias(
true
);
LinearGradient shader =
new
LinearGradient(
0
,
srcHeight,
0
,
bitmapWithReflection.getHeight() + REFLECTION_GAP,
0x70FFFFFF
,
0x00FFFFFF
,
TileMode.MIRROR);
paint.setShader(shader);
paint.setXfermode(
new
PorterDuffXfermode(android.graphics.PorterDuff.Mode.DST_IN));
// Draw the linear shader.
canvas.drawRect(
0
,
srcHeight,
srcWidth,
bitmapWithReflection.getHeight() + REFLECTION_GAP,
paint);
return
bitmapWithReflection;
}
catch
(Exception e)
{
e.printStackTrace();
}
return
null
;
}
}
- Android gallery 3D效果(扩展Gallery)
- Android gallery 3D效果
- Android gallery 3D效果
- Android gallery 3D效果
- Android gallery 3D效果
- Android gallery 3D效果
- Android gallery 3D效果
- Android gallery 3D效果
- Android gallery 3D效果
- Android Gallery 3D效果
- Android gallery 3D效果
- Android gallery 3D效果
- Android控件Gallery 3D效果
- Android控件Gallery 3D效果
- Android控件Gallery 3D效果
- Android控件Gallery 3D效果
- Android开发_Android gallery 3D效果
- android 重叠gallery 3D效果实现
- iOS oc 回顾与复习
- spark问题归纳
- 如何用PS处理虚的照片.使它变的清晰
- iOS UITableView单元格单击出现延迟,双击正常执行事件问题
- 【笔试】19、该类型添加赋值运算符函数
- Android gallery 3D效果
- 如何将ppt或其他文档转为pdf格式
- QT简单软键盘+SYSZUXpinyin修改
- 1660 - Cable TV Network(最大流最小割)
- linux sed 命令
- python 语言技巧特点
- 循环链表的有趣遍历
- MSSQL Server的连接问题分析和解决(1)
- 9.12测试(一)——应用程序一运行就崩溃,且每次崩溃的位置都不一样