01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
private
void
transformImageBitmap(ImageView child, Transformation t,
int
rotationAngle) {
//对效果进行保存
mCamera.save();
final
Matrix imageMatrix = t.getMatrix();
//图片高度
final
int
imageHeight = child.getLayoutParams().height;
//图片宽度
final
int
imageWidth = child.getLayoutParams().width;
//返回旋转角度的绝对值
final
int
rotation = Math.abs(rotationAngle);
// 在Z轴上正向移动camera的视角,实际效果为放大图片。
// 如果在Y轴上移动,则图片上下移动;X轴上对应图片左右移动。
mCamera.translate(
0
.0f,
0
.0f,
100
.0f);
// As the angle of the view gets less, zoom in
if
(rotation < mMaxRotationAngle) {
float
zoomAmount = (
float
) (mMaxZoom + (rotation *
1.5
));
mCamera.translate(
0
.0f,
0
.0f, zoomAmount);
}
// 在Y轴上旋转,对应图片竖向向里翻转。
// 如果在X轴上旋转,则对应图片横向向里翻转。
mCamera.rotateY(rotationAngle);
mCamera.getMatrix(imageMatrix);
imageMatrix.preTranslate(-(imageWidth /
2
), -(imageHeight /
2
));
imageMatrix.postTranslate((imageWidth /
2
), (imageHeight /
2
));
mCamera.restore();
}
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
public
class
GalleryDemoActivity
extends
Activity {
/** Called when the activity is first created. */
@Override
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
Integer[] images = { R.drawable.image01,
R.drawable.image02,
R.drawable.image03,
R.drawable.image04,
R.drawable.image05};
ImageAdapter adapter =
new
ImageAdapter(
this
, images);
adapter.createReflectedImages();
//创建倒影效果
GalleryFlow galleryFlow = (GalleryFlow)
this
.findViewById(R.id.gallery);
galleryFlow.setFadingEdgeLength(
0
);
galleryFlow.setSpacing(
10
);
//图片之间的间距
galleryFlow.setAdapter(adapter);
galleryFlow.setOnItemClickListener(
new
OnItemClickListener() {
public
void
onItemClick(AdapterView<?> parent, View view,
int
position,
long
id) {
Toast.makeText(getApplicationContext(), String.valueOf(position), Toast.LENGTH_SHORT).show();
}
});
galleryFlow.setSelection(
4
);
}
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
/**
* 创建倒影效果
* @return
*/
public
boolean
createReflectedImages() {
//倒影图和原图之间的距离
final
int
reflectionGap =
4
;
int
index =
0
;
for
(
int
imageId : mImageIds) {
//返回原图解码之后的bitmap对象
Bitmap originalImage = BitmapFactory.decodeResource(mContext.getResources(), imageId);
int
width = originalImage.getWidth();
int
height = originalImage.getHeight();
//创建矩阵对象
Matrix matrix =
new
Matrix();
//指定一个角度以0,0为坐标进行旋转
// matrix.setRotate(30);
//指定矩阵(x轴不变,y轴相反)
matrix.preScale(
1
, -
1
);
//将矩阵应用到该原图之中,返回一个宽度不变,高度为原图1/2的倒影位图
Bitmap reflectionImage = Bitmap.createBitmap(originalImage,
0
,
height/
2
, width, height/
2
, matrix,
false
);
//创建一个宽度不变,高度为原图+倒影图高度的位图
Bitmap bitmapWithReflection = Bitmap.createBitmap(width,
(height + height /
2
), Config.ARGB_8888);
//将上面创建的位图初始化到画布
Canvas canvas =
new
Canvas(bitmapWithReflection);
canvas.drawBitmap(originalImage,
0
,
0
,
null
);
Paint deafaultPaint =
new
Paint();
deafaultPaint.setAntiAlias(
false
);
// canvas.drawRect(0, height, width, height + reflectionGap,deafaultPaint);
canvas.drawBitmap(reflectionImage,
0
, height + reflectionGap,
null
);
Paint paint =
new
Paint();
paint.setAntiAlias(
false
);
/**
* 参数一:为渐变起初点坐标x位置,
* 参数二:为y轴位置,
* 参数三和四:分辨对应渐变终点,
* 最后参数为平铺方式,
* 这里设置为镜像Gradient是基于Shader类,所以我们通过Paint的setShader方法来设置这个渐变
*/
LinearGradient shader =
new
LinearGradient(
0
,originalImage.getHeight(),
0
,
bitmapWithReflection.getHeight() + reflectionGap,
0x70ffffff
,
0x00ffffff
, TileMode.MIRROR);
//设置阴影
paint.setShader(shader);
paint.setXfermode(
new
PorterDuffXfermode(android.graphics.PorterDuff.Mode.DST_IN));
//用已经定义好的画笔构建一个矩形阴影渐变效果
canvas.drawRect(
0
, height, width, bitmapWithReflection.getHeight()+ reflectionGap, paint);
//创建一个ImageView用来显示已经画好的bitmapWithReflection
ImageView imageView =
new
ImageView(mContext);
imageView.setImageBitmap(bitmapWithReflection);
//设置imageView大小 ,也就是最终显示的图片大小
imageView.setLayoutParams(
new
GalleryFlow.LayoutParams(
200
,
300
));
//imageView.setScaleType(ScaleType.MATRIX);
mImages[index++] = imageView;
}
return
true
;
}
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
public
static
Bitmap createBitmap (Bitmap source,
int
x,
int
y,
int
width,
int
height, Matrix m,
boolean
filter)
Since: API Level
1
Returns an immutable bitmap from subset of the source bitmap, transformed by the optional matrix. It is initialized with the same density as the original bitmap.
Parameters
source The bitmap we are subsetting
x The x coordinate of the first pixel in source
y The y coordinate of the first pixel in source
width The number of pixels in each row
height The number of rows
m Optional matrix to be applied to the pixels
filter
true
if
the source should be filtered. Only applies
if
the matrix contains more than just translation.
Returns
A bitmap that represents the specified subset of source
Throws
IllegalArgumentException
if
the x, y, width, height values are outside of the dimensions of the source bitmap.
|
01
02
03
04
05
06
07
08
09
|
/**
* 参数一:为渐变起初点坐标x位置,
* 参数二:为y轴位置,
* 参数三和四:分辨对应渐变终点,
* 最后参数为平铺方式,
* 这里设置为镜像Gradient是基于Shader类,所以我们通过Paint的setShader方法来设置这个渐变
*/
LinearGradient shader =
new
LinearGradient(
0
,originalImage.getHeight(),
0
,
bitmapWithReflection.getHeight() + reflectionGap,
0x70ffffff
,
0x00ffffff
, TileMode.MIRROR);
|
01
02
03
04
05
06
07
08
09
10
11
12
13
|
<?xml version=
"1.0"
encoding=
"utf-8"
?>
<LinearLayout xmlns:android=
"http://schemas.android.com/apk/res/android"
android:layout_width=
"fill_parent"
android:layout_height=
"fill_parent"
android:orientation=
"vertical"
>
<nsouth.jonas.android.GalleryFlow
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:gravity=
"center_vertical"
android:id=
"@+id/gallery"
/>
</LinearLayout>
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
public
class
GalleryFlow
extends
Gallery{
private
Camera mCamera =
new
Camera();
//相机类
private
int
mMaxRotationAngle =
60
;
//最大转动角度
private
int
mMaxZoom = -
280
;
////最大缩放值
private
int
mCoveflowCenter;
//半径值
public
GalleryFlow(Context context) {
super
(context);
//支持转换 ,执行getChildStaticTransformation方法
this
.setStaticTransformationsEnabled(
true
);
}
public
GalleryFlow(Context context, AttributeSet attrs) {
super
(context, attrs);
this
.setStaticTransformationsEnabled(
true
);
}
public
GalleryFlow(Context context, AttributeSet attrs,
int
defStyle) {
super
(context, attrs, defStyle);
this
.setStaticTransformationsEnabled(
true
);
}
/**
* 获取旋转最大角度
* @return
*/
public
int
getMaxRotationAngle() {
return
mMaxRotationAngle;
}
/**
* 设置旋转最大角度
* @param maxRotationAngle
*/
public
void
setMaxRotationAngle(
int
maxRotationAngle) {
mMaxRotationAngle = maxRotationAngle;
}
/**
* 获取最大缩放值
* @return
*/
public
int
getMaxZoom() {
return
mMaxZoom;
}
/**
* 设置最大缩放值
* @param maxZoom
*/
public
void
setMaxZoom(
int
maxZoom) {
mMaxZoom = maxZoom;
}
/**
* 获取半径值
* @return
*/
private
int
getCenterOfCoverflow() {
return
(getWidth() - getPaddingLeft() - getPaddingRight()) /
2
+ getPaddingLeft();
}
/**
* @param view
* @return
*/
private
static
int
getCenterOfView(View view) {
return
view.getLeft() + view.getWidth() /
2
;
}
//控制gallery中每个图片的旋转(重写的gallery中方法)
protected
boolean
getChildStaticTransformation(View child, Transformation t) {
//取得当前子view的半径值
final
int
childCenter = getCenterOfView(child);
final
int
childWidth = child.getWidth();
//旋转角度
int
rotationAngle =
0
;
//重置转换状态
t.clear();
//设置转换类型
t.setTransformationType(Transformation.TYPE_MATRIX);
//如果图片位于中心位置不需要进行旋转
if
(childCenter == mCoveflowCenter) {
transformImageBitmap((ImageView) child, t,
0
);
}
else
{
//根据图片在gallery中的位置来计算图片的旋转角度
rotationAngle = (
int
) (((
float
) (mCoveflowCenter - childCenter) / childWidth) * mMaxRotationAngle);
System.out.println(
"rotationAngle:"
+rotationAngle);
//如果旋转角度绝对值大于最大旋转角度返回(-mMaxRotationAngle或mMaxRotationAngle;)
if
(Math.abs(rotationAngle) > mMaxRotationAngle) {
rotationAngle = (rotationAngle <
0
) ? -mMaxRotationAngle : mMaxRotationAngle;
}
transformImageBitmap((ImageView) child, t, rotationAngle);
}
return
true
;
}
/**
*
*/
protected
void
onSizeChanged(
int
w,
int
h,
int
oldw,
int
oldh) {
mCoveflowCenter = getCenterOfCoverflow();
super
.onSizeChanged(w, h, oldw, oldh);
}
}
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
//控制gallery中每个图片的旋转(重写的gallery中方法)
protected
boolean
getChildStaticTransformation(View child, Transformation t) {
//取得当前子view的半径值
final
int
childCenter = getCenterOfView(child);
final
int
childWidth = child.getWidth();
//旋转角度
int
rotationAngle =
0
;
//重置转换状态
t.clear();
//设置转换类型
t.setTransformationType(Transformation.TYPE_MATRIX);
//如果图片位于中心位置不需要进行旋转
if
(childCenter == mCoveflowCenter) {
transformImageBitmap((ImageView) child, t,
0
);
}
else
{
//根据图片在gallery中的位置来计算图片的旋转角度
rotationAngle = (
int
) (((
float
) (mCoveflowCenter - childCenter) / childWidth) * mMaxRotationAngle);
System.out.println(
"rotationAngle:"
+rotationAngle);
//如果旋转角度绝对值大于最大旋转角度返回(-mMaxRotationAngle或mMaxRotationAngle;)
if
(Math.abs(rotationAngle) > mMaxRotationAngle) {
rotationAngle = (rotationAngle <
0
) ? -mMaxRotationAngle : mMaxRotationAngle;
}
transformImageBitmap((ImageView) child, t, rotationAngle);
}
return
true
;
}
|
01
02
03
04
05
06
07
08
|
//根据图片在gallery中的位置来计算图片的旋转角度
rotationAngle = (
int
) (((
float
) (mCoveflowCenter - childCenter) / childWidth) * mMaxRotationAngle);
System.out.println(
"rotationAngle:"
+rotationAngle);
//如果旋转角度绝对值大于最大旋转角度返回(-mMaxRotationAngle或mMaxRotationAngle;)
if
(Math.abs(rotationAngle) > mMaxRotationAngle) {
rotationAngle = (rotationAngle <
0
) ? -mMaxRotationAngle : mMaxRotationAngle;
}
transformImageBitmap((ImageView) child, t, rotationAngle);
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
private
void
transformImageBitmap(ImageView child, Transformation t,
int
rotationAngle) {
//对效果进行保存
mCamera.save();
final
Matrix imageMatrix = t.getMatrix();
//图片高度
final
int
imageHeight = child.getLayoutParams().height;
//图片宽度
final
int
imageWidth = child.getLayoutParams().width;
//返回旋转角度的绝对值
final
int
rotation = Math.abs(rotationAngle);
// 在Z轴上正向移动camera的视角,实际效果为放大图片。
// 如果在Y轴上移动,则图片上下移动;X轴上对应图片左右移动。
mCamera.translate(
0
.0f,
0
.0f,
100
.0f);
// As the angle of the view gets less, zoom in
if
(rotation < mMaxRotationAngle) {
float
zoomAmount = (
float
) (mMaxZoom + (rotation *
1.5
));
mCamera.translate(
0
.0f,
0
.0f, zoomAmount);
}
// 在Y轴上旋转,对应图片竖向向里翻转。
// 如果在X轴上旋转,则对应图片横向向里翻转。
mCamera.rotateY(rotationAngle);
mCamera.getMatrix(imageMatrix);
imageMatrix.preTranslate(-(imageWidth /
2
), -(imageHeight /
2
));
imageMatrix.postTranslate((imageWidth /
2
), (imageHeight /
2
));
mCamera.restore();
}
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
private
boolean
isScrollingLeft(MotionEvent e1, MotionEvent e2) {
return
e2.getX() > e1.getX();
}
@Override
public
boolean
onFling(MotionEvent e1, MotionEvent e2,
float
velocityX,
float
velocityY) {
// e1是按下的事件,e2是抬起的事件
int
keyCode;
if
(isScrollingLeft(e1, e2)) {
keyCode = KeyEvent.KEYCODE_DPAD_LEFT;
}
else
{
keyCode = KeyEvent.KEYCODE_DPAD_RIGHT;
}
onKeyDown(keyCode,
null
);
return
true
;
}
|