android 动态向Gallery中添加图片及倒影&&3D效果
2012-10-08 09:53
591 查看
在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,当然,通过简单的理解,很轻松的这两个类就能够在其他的工程中重用的
。
相关文章推荐
- android 动态向Gallery中添加图片及倒影&&3D效果
- Android实现动态向Gallery中添加图片及倒影与3D效果示例
- 我的Android进阶之旅------>android之向Gallery中添加倒影3D效果
- android Gallery 3D 倒影图片浏览 解决oom问题
- Android绘图实例(Bitmmap,Canvas,Pain的使用)&动态的在图片上添加文字(canvas.drawText)
- Android UI控件之Gallery --拖动、覆盖、循环、3D图片浏览 效果之一
- Android UI控件之Gallery --拖动、覆盖、循环、3D图片浏览 效果之一
- Android UI控件之Gallery --拖动、覆盖、循环、3D图片浏览 效果之二
- Android 2.3 Gallery3D添加gif支持——图片显示(二)
- Android UI控件之Gallery --拖动、覆盖、循环、3D图片浏览 效果之二
- Android实现图片倒影效果
- Android2.2 Luncher2扩展(仿Ipad DockBar、HTC预览图、批量添加快捷方式、启用3D效果等)
- Android控件Gallery3D效果
- Android自定义ImageView实现在图片上添加图层效果
- Android 实现View中添加子元素的动态效果
- Android控件Gallery3D效果
- Android控件Gallery3D效果
- Android实现图片的倒影效果分析
- 【Android Demo】图片之画廊效果(Gallery Switcher)
- Android gallery3d试用效果