android 动态向Gallery中添加图片及倒影&&3D效果

                                                  

在android中gallery可以提供一个很好的显示图片的方式,实现上面的效果以及动态添加数据库或者网络上下载下来的图片资源。我们首先实现一个自定义的Gallery类。

MyGallery.java
  1 package nate.android.Service;
2 import android.content.Context;
3 import android.graphics.Camera;
4 import android.graphics.Matrix;
5 import android.graphics.Rect;
6 import android.util.AttributeSet;
7 import android.view.View;
8 import android.view.animation.Transformation;
9 import android.widget.Gallery;
10 import android.widget.ImageView;
11 import android.widget.Toast;
12 public class MyGallery extends Gallery {
13 private Camera mCamera = new Camera();
14 private int mMaxRotationAngle = 45;
15 private int mMaxZoom = -120;
16 private int mCoveflowCenter;
17
18 public MyGallery(Context context) {
19 super(context);
20 this.setStaticTransformationsEnabled(true);
21 }
22
23 public MyGallery(Context context, AttributeSet attrs) {
24 super(context, attrs);
25 this.setStaticTransformationsEnabled(true);
26 }
27
28 public MyGallery(Context context, AttributeSet attrs, int defStyle) {
29 super(context, attrs, defStyle);
30 this.setStaticTransformationsEnabled(true);
31 }
32
33 public int getMaxRotationAngle() {
34 return mMaxRotationAngle;
35 }
36 public void setMaxRotationAngle(int maxRotationAngle) {
37 mMaxRotationAngle = maxRotationAngle;
38 }
39 public int getMaxZoom() {
40 return mMaxZoom;
41 }
42 public void setMaxZoom(int maxZoom) {
43 mMaxZoom = maxZoom;
44 }
45 private int getCenterOfCoverflow() {
46 return (getWidth() - getPaddingLeft() - getPaddingRight()) / 2
47 + getPaddingLeft();
48 }
49 private static int getCenterOfView(View view) {
50 return view.getLeft() + view.getWidth() / 2;
51 }
52 protected boolean getChildStaticTransformation(View child, Transformation t) {
53 final int childCenter = getCenterOfView(child);
54 final int childWidth = child.getWidth();
55 int rotationAngle = 0;
56 t.clear();
57 t.setTransformationType(Transformation.TYPE_MATRIX);
58
59 if (childCenter == mCoveflowCenter) {
60 transformImageBitmap((ImageView) child, t, 0);
61 } else {
62 rotationAngle = (int) (((float) (mCoveflowCenter - childCenter) / childWidth) * mMaxRotationAngle);
63 if (Math.abs(rotationAngle) > mMaxRotationAngle) {
64 rotationAngle = (rotationAngle < 0) ? -mMaxRotationAngle
65 : mMaxRotationAngle;
66 }
67 transformImageBitmap((ImageView) child, t, rotationAngle);
68 }
69 return true;
70 }
71
72 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
73 mCoveflowCenter = getCenterOfCoverflow();
74 super.onSizeChanged(w, h, oldw, oldh);
75 }
76
77 private void transformImageBitmap(ImageView child, Transformation t,
78 int rotationAngle) {
79 mCamera.save();
80 final Matrix imageMatrix = t.getMatrix();
81 final int imageHeight = child.getLayoutParams().height;
82 final int imageWidth = child.getLayoutParams().width;
83 final int rotation = Math.abs(rotationAngle);
84
85 // 在Z轴上正向移动camera的视角,实际效果为放大图片。
86 // 如果在Y轴上移动,则图片上下移动;X轴上对应图片左右移动。
87 mCamera.translate(0.0f, 0.0f, 100.0f);
88
89 // As the angle of the view gets less, zoom in
90 if (rotation < mMaxRotationAngle) {
91 float zoomAmount = (float) (mMaxZoom + (rotation * 1.5));
92 mCamera.translate(0.0f, 0.0f, zoomAmount);
93 }
94 // 在Y轴上旋转,对应图片竖向向里翻转。
95 // 如果在X轴上旋转,则对应图片横向向里翻转。
96 mCamera.rotateY(rotationAngle);
97 mCamera.getMatrix(imageMatrix);
98 imageMatrix.preTranslate(-(imageWidth / 2), -(imageHeight / 2));
99 imageMatrix.postTranslate((imageWidth / 2), (imageHeight / 2));
100 mCamera.restore();
101 }
102 }

  

  在布局文件中

View Code
 1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:orientation="vertical"
4 android:layout_width="fill_parent"
5 android:layout_height="fill_parent"
6 android:background="#ffffff"
7 >
8 <LinearLayout
9 android:layout_width="fill_parent" android:layout_height="wrap_content"
10 android:orientation="vertical" android:paddingTop="10px"
11 >
12 <LinearLayout
13 android:layout_width="fill_parent" android:layout_height="wrap_content"
14 android:orientation="horizontal"
15 >
16 <TextView
17 android:layout_width="wrap_content" android:layout_height="wrap_content"
18 android:id="@+id/dishName" android:textSize="18pt"
19 android:text="菜名"
20 />
21 <LinearLayout
22 android:layout_width="fill_parent" android:layout_height="wrap_content"
23 android:orientation="horizontal" android:paddingLeft="10px"
24 >
25 <TextView
26 android:layout_width="wrap_content" android:layout_height="wrap_content"
27 android:id="@+id/ds" android:textSize="18pt"
28 android:text="评分 : "
29 />
30 <RatingBar
31 android:numStars="5" android:rating="3"
32 android:stepSize="0.2" android:layout_width="wrap_content"
33 android:layout_height="wrap_content" android:isIndicator="true"
34 android:id="@+id/dishScores" style="?android:attr/ratingBarStyleSmall"
35 />
36 </LinearLayout>
37 </LinearLayout>
38 <LinearLayout
39 android:layout_width="fill_parent" android:layout_height="wrap_content"
40 android:orientation="horizontal"
41 >
42 <TextView
43 android:layout_width="fill_parent" android:layout_height="wrap_content"
44 android:id="@+id/dishPrice" android:text="价格" android:textSize="18pt"
45 />
46 </LinearLayout>
47 </LinearLayout>
48 <nate.android.Service.MyGallery
49 android:id="@+id/Gallery01"
50 android:layout_width="fill_parent"
51 android:layout_height="wrap_content"
52 android:layout_centerInParent="true"
53 />
54 <TextView
55 android:text="\n\n\n\n这里是关于每一道菜的信息,点击图片进入评论"
56 android:layout_width="fill_parent"
57 android:layout_height="wrap_content"
58 android:layout_below="@+id/gallery01"
59 android:paddingLeft="5px"
60 android:id="@+id/showHint"
61 />
62 </LinearLayout>

  

  在上面的XML文件中,我们使用了自定义的MyGallery。

然后顶一个ImageAdapter类继承自BaseAdapter。

View Code
 1 package nate.android.Service;
2
3 import java.util.ArrayList;
4 import android.content.Context;
5 import android.content.res.Resources;
6 import android.graphics.Bitmap;
7 import android.graphics.BitmapFactory;
8 import android.graphics.Canvas;
9 import android.graphics.LinearGradient;
10 import android.graphics.Matrix;
11 import android.graphics.Paint;
12 import android.graphics.PorterDuffXfermode;
13 import android.graphics.Bitmap.Config;
14 import android.graphics.PorterDuff.Mode;
15 import android.graphics.Shader.TileMode;
16 import android.view.View;
17 import android.view.ViewGroup;
18 import android.widget.BaseAdapter;
19 import android.widget.ImageView;
20
21 public class ImageAdapter extends BaseAdapter {
22
23 int mGalleryItemBackground;
24 private Context mContext;
25 private ArrayList<byte[]> dishImages = new ArrayList<byte[]>();
26 private ImageView[] mImages;
27
28 public ImageAdapter(Context c,ArrayList<byte[]> tmpDishImages) {
29 mContext = c;
30 dishImages = tmpDishImages;
31 mImages = new ImageView[dishImages.size()];
32 }
33 public boolean createReflectedImages() {
34 final int reflectionGap = 4;
35 int index = 0;
36 System.out.println("dishImages size " + dishImages.size());
37 for (int i =0; i < dishImages.size(); ++i ) {
38 System.out.println("dishImage --- " + dishImages.get(i));
39 Bitmap originalImage = BitmapFactory.decodeByteArray(dishImages.get(i), 0, dishImages.get(i).length);
40 int width = originalImage.getWidth();
41 int height = originalImage.getHeight();
42 Matrix matrix = new Matrix();
43 matrix.preScale(1, -1);
44 Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0,
45 height / 2, width, height / 2, matrix, false);
46
47 Bitmap bitmapWithReflection = Bitmap.createBitmap(width,
48 (height + height / 2), Config.ARGB_8888);
49
50 Canvas canvas = new Canvas(bitmapWithReflection);
51 canvas.drawBitmap(originalImage, 0, 0, null);
52 Paint deafaultPaint = new Paint();
53 canvas.drawRect(0, height, width, height + reflectionGap,
54 deafaultPaint);
55 canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);
56 Paint paint = new Paint();
57 LinearGradient shader = new LinearGradient(0, originalImage
58 .getHeight(), 0, bitmapWithReflection.getHeight()
59 + reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.CLAMP);
60 paint.setShader(shader);
61 paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
62 canvas.drawRect(0, height, width, bitmapWithReflection.getHeight()
63 + reflectionGap, paint);
64 ImageView imageView = new ImageView(mContext);
65 imageView.setImageBitmap(bitmapWithReflection);
66 // imageView.setLayoutParams(new GalleryFlow.LayoutParams(180, 240));
67 imageView.setLayoutParams(new MyGallery.LayoutParams(270, 360));
68 //imageView.setScaleType(ScaleType.MATRIX);
69 mImages[index++] = imageView;
70 }
71 return true;
72 }
73
74 private Resources getResources() {
75 return null;
76 }
77
78 public int getCount() {
79 return dishImages.size();
80 }
81
82 public Object getItem(int position) {
83 return position;
84 }
85
86 public long getItemId(int position) {
87 return position;
88 }
89
90 public View getView(int position, View convertView, ViewGroup parent) {
91 return mImages[position];
92 }
93
94 public float getScale(boolean focused, int offset) {
95 return Math.max(0, 1.0f / (float) Math.pow(2, Math.abs(offset)));
96 }
97 }

  

在这个类中构造函数需要传入将要在gallery中绘制的图片数据,(以byte[]类型的为例,因为我在存入sqlite以及从从网络下载下来的图片demo中都将其转成byte[]),同样我们使用
Bitmap originalImage = BitmapFactory.decodeByteArray(dishImages.get(i), 0, dishImages.get(i).length);

在这篇文章有较详细的说明

将byte[]类型的图片数据“还原”。byte[]类型的图片源数据保存在一个ArrayList<byte[]>当中。这样我们为动态的实现在gallery中添加图片提供数据来源。

在下面的activity中使用我们自定义的baseAdapter以及Gallery。实现上图显示的效果。

使用实例类
  1 package com.nate.wte2;
2 import java.io.IOException;
3 import java.util.ArrayList;
4 import nate.InfoService.DishInfo;
5 import nate.InfoService.StoreInfoService;
6 import nate.InfoService.WhichChoice;
7 import nate.NetConnection.GetConnectionSock;
8 import nate.android.Service.GalleryFlow;
9 import nate.android.Service.ImageAdapter;
10 import android.app.Activity;
11 import android.app.ProgressDialog;
12 import android.content.Intent;
13 import android.os.Bundle;
14 import android.os.Handler;
15 import android.os.Message;
16 import android.view.View;
17 import android.widget.AdapterView;
18 import android.widget.RatingBar;
19 import android.widget.TextView;
20 import android.widget.Toast;
21 import android.widget.AdapterView.OnItemClickListener;
22 import android.widget.AdapterView.OnItemSelectedListener;
23 import com.nate.wte.LocalSql.StoresInfoDB;
24 public class DishMenuActivity extends Activity {
25
26 private ArrayList<DishInfo> dishInfoList = new ArrayList<DishInfo>();
27 private TextView dishName;
28 private RatingBar dishScores;
29 private TextView dishPrice;
30 //3:send the dish's whole info to fill the activity(send the comments of the dish)
31 private int flag3 = 3;
32 WhichChoice choice3 = new WhichChoice(flag3);
33 private StoreInfoService storeInfo;
34 private ProgressDialog loadingDialog;
35
36 /**
37 * handler handle the dialog dismission
38 */
39 private Handler handler = new Handler(){
40
41 @Override
42 public void handleMessage(Message msg) {
43 loadingDialog.dismiss();
44 //other operation
45 super.handleMessage(msg);
46 }
47 };
48 /**
49 * thread to load the data from local database or from the server
50 * @author Administrator
51 *
52 */
53 class Loading implements Runnable{
54 @Override
55 public void run() {
56 try {
57 //这儿的sleep将换成一个循环,知道某个条件满足时候才结束循环,让dialog终止
58 Thread.sleep(1500);
59 handler.sendEmptyMessage(0);
60 } catch (InterruptedException e) {
61 e.printStackTrace();
62 }
63 }
64 }
65
66 /**
67 * loading the items,start the thread to load
68 */
69 public void loadingItems(){
70 loadingDialog = ProgressDialog.show(DishMenuActivity.this, "", "loading...");
71 Thread t = new Thread(new Loading());
72 t.start();
73 }
74
75
76 public void onCreate(Bundle savedInstanceState) {
77 super.onCreate(savedInstanceState);
78 setContentView(R.layout.dishmenu_gallery);
79
80 StoresInfoDB infoDB;
81 int dishInfoListLength;
82 ArrayList<byte[]> dishImages = new ArrayList<byte[]>();
83 byte[] dishImage;
84
85 dishName = (TextView)this.findViewById(R.id.dishName);
86 dishPrice = (TextView)this.findViewById(R.id.dishPrice);
87 dishScores = (RatingBar)this.findViewById(R.id.dishScores);
88
89 //得到intent中从Choices类中传过来的对象
90 Intent intent = getIntent();
91 Bundle bundle = intent.getBundleExtra("bundleData");
92 storeInfo = (StoreInfoService)bundle.getSerializable("storeInfo");
93 dishInfoList = (ArrayList<DishInfo>)bundle.getSerializable("dishInfoList");
94 System.out.println("look look the info received from Choices Activity");
95 for(int i = 0; i < dishInfoList.size(); i++){
96 System.out.println("--- " + i + dishInfoList.get(i).getDishImage().toString());
97 }
98 dishInfoListLength = dishInfoList.size();
99 //初始化 dishImages
100 for(int i = 0; i < dishInfoListLength; i++){
101 dishImages.add(dishInfoList.get(i).getDishImage());
102 }
103 System.out.println("the length of the dishImages ---- " + dishImages.size());
104 ////////////////////////////////
105 //注意这里一段
106 ////////////////////////////////
107 ImageAdapter adapter = new ImageAdapter(DishMenuActivity.this,dishImages);
108 adapter.createReflectedImages();
109 GalleryFlow galleryFlow = (GalleryFlow) findViewById(R.id.Gallery01);
110 galleryFlow.setOnItemSelectedListener(new OnItemSelectedListener(){
111 @Override
112 public void onItemSelected(AdapterView<?> arg0, View arg1,
113 int arg2, long arg3) {
114 String showName = "菜名 : " + dishInfoList.get((int)arg3).getDishName() + " ";
115 dishName.setText(showName);
116 dishScores.setRating(dishInfoList.get((int)arg3).getDishScores());
117 dishPrice.setText("价格 : " + dishInfoList.get((int)arg3).getPrice() + " 元\n\n\n");
118 }
119 @Override
120 public void onNothingSelected(AdapterView<?> arg0) {
121
122 }
123
124 });
125
126 galleryFlow.setOnItemClickListener(new OnItemClickListener(){
127 @Override
128 public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
129 long arg3) {
130
131 loadingItems();
132 DishInfo dishInfo = dishInfoList.get((int)arg3);
133 try {
134 GetConnectionSock.fromClient.writeObject(choice3);
135 System.out.println("send the flag 3 ");
136 GetConnectionSock.fromClient.writeObject(dishInfo);
137 System.out.println("send the name back to server");
138 DishInfo dishComments = (DishInfo)GetConnectionSock.fromServer.readObject();
139 System.out.println("recv the dish comments");
140 dishInfo.setDishName(dishInfoList.get((int)arg3).getDishName());
141 dishInfo.setDishComments(dishComments.getDishComments());
142 System.out.println("full the dish info");
143 } catch (IOException e) {
144 e.printStackTrace();
145 } catch (ClassNotFoundException e) {
146 e.printStackTrace();
147 }
148 Intent intent = new Intent();
149 Bundle bundle = new Bundle();
150 bundle.putSerializable("dishInfo",dishInfo);
151 bundle.putSerializable("storeInfo",storeInfo);
152 intent.putExtra("dishBundleData",bundle);
153 intent.setClass(DishMenuActivity.this,DishInfoDynamic.class);
154 Toast.makeText(DishMenuActivity.this, "进入评论此道菜",Toast.LENGTH_LONG).show();
155 DishMenuActivity.this.startActivity(intent);
156 }
157 });
158 galleryFlow.setAdapter(adapter); //注意这里
159 }
160 }

 

在这个activity中跟本文相关的,也就是在galley中添加图片功能,只需注意上面代码中标注出来的部分代码即可,至于数据来源得到的方式都不一样,这里只要知道数据是一个ArrayList<byte[]>就行了。重要的是利用上面的MyGallery以及ImageAdapter,当然,通过简单的理解,很轻松的这两个类就能够在其他的工程中重用的微笑

记录下自己的所学,虽然浅薄!!!如果我是一只蜗牛,只能慢慢向上爬!奋斗

 

posted on 2011-08-02 09:43  Pe.潘义  阅读(9081)  评论(6编辑  收藏  举报

导航