編輯:Android開發實例
在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 }
在布局文件中
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。
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,當然,通過簡單的理解,很輕松的這兩個類就能夠在其他的工程中重用的。
JSON代表JavaScript對象符號。它是一個獨立的數據交換格式,是XML的最佳替代品。本章介紹了如何解析JSON文件,並從中提取所需的信息。Android提供了四個
Android提供了許多方法來控制播放的音頻/視頻文件和流。其中該方法是通過一類稱為MediaPlayer。Android是提供MediaPlayer類訪問內置的媒體播放
上一個項目已經做完了,這周基本上沒事,所以整理了下以前的項目,想把一些通用的部分封裝起來,這樣以後遇到相似的項目就不用重復發明輪子了,也節省了開發效率。今天把de
不知道大家是否用過天天動聽,對於它界面上的半透明Menu效果,筆者感覺非常漂亮