相册这玩意儿用AS写过几个,这回用android写,目前对于java的理解完全是根据as来的,对于android几乎是一窍不通,从没做过这方面的项目,公司有个后台同事稍微懂点,本打算跟着他学学的,在他刚教会我安装android开发环境后,他就辞职闪人了。好吧,买书自学。找到了当初在西安一个人拿着殿堂之路死磕的感觉。

 

  技术要点:

  1,如何创建一个android项目;

  2,如何创建一个可见的显示对象类;

  3,如何让显示对象从A点移动到B点,且可控制速度;

  4,如何访问本地文件,包括手机存储空间和SD卡存储空间;

  5,如何把本地路径的图片加载到自己应用的内存空间里;

  6,如何把图片添加到显示对象作为其子对象;

    7,如果通过网络加载服务器里存储的图片。

 

==================================================================

1,eclipse安装好ADT和Android SDK后,就可创建android项目,Ctrl+N ,选择"Android"目录,第一个是"Android Icon Set",这个东西貌似是专门给自己的应用创建logo Icon的,不管他,点第二个,新建“Android Project”,这里用的android版本是2.3.3。

 

项目目录下默认有src,gen,android2.3.3,assets,bin,res这六个目录,和AndroidManifest.xml ,proguard.cfg, progect.properties这三个文件。

(1)src:

项目里所有代码都在这里,由于创建项目时勾选了”Create Activity“,会自动创建一个继承自Activity的类,这里叫    PhotoAlbumActivity.java。

   Activity:

   An Activity is an application component that provides a screen with which users can interact in order to do something, such as dial the phone, take a photo, send an email, or view a map. An activity can start other activities, including activities that live in separate applications.

   官方文档里的原话,大意是Activity是一个供用户交互的应用组件,一个用户界面。比如用户拨号,拍照,发送邮件或者查看地图。可以通过一个activity对象启动其他的activiety对象,甚至是存在与其他独立的应用里的activity对象。

(2)gen:

  项目一旦编译之后就会在gen目录里创建一个类R.java,此类对应的是res目录里所有的资源文件,项目中新添加一张图放到了res-drawable目录后就会在R.java里自动生成一个新的对应索引。项目中使用资源的地方可便捷地通过R.java使用。

 

(3)Android 2.2.3

   android库目录,android.jar文件指向Android SDK,所有官方API

(4)assets

  存放外部资源,和同样是存放资源的res目录的区别就在于res里的资源文件会自动在R.java里生成对应资源ID,asset则不会。

(5)bin

  项目编译成功后会在bin里面存放用到了的资源,以及生成一个apk文件。

(6)res

  res,用来存放项目中用到的资源文件,有5个子目录:

  drawable_hdpi,存放高分辨的图片,WVGA(480*800),FWVGA(480*854)

  drawable_ldpi,存放中等分辨率的图片,HVGA(320*480)

  drawable_mdpi,存放低分辨率的图片,QVGA(240*320)

  layout,存放布局文件

  values,放置项目需要显示的各种文字,颜色等文字信息。

(7)AndroidManifest.xml

  当前项目的配置文件,包含有项目中用到的Activity,如果新添加了一个Activity,需要在这个进行相应的配置才能被调用。

(8)proguard.cfg

  貌似是一个用与混淆代码放置反编译的东西

(9)project.properies

  貌似是跟android版本信息有关。

 =================================================================

2,要想创建一个显示对象,就不得不说说三种常用视图类,View,surfaceView,GLSurfaceView

view,内置画布canvas,提供图形绘制函数,触屏事件,按键事件函数等;

surfaceView,继承自view.

 

====================================

 2012年,1月24日大年初二晚,继续写这篇文章。之前写的技术要点有些了解了有些还没了解。

之前偶尔抽时间在网上找了些资料,目前算是可以复制网上的代码搞个根据设定的线程数来加载图片,代码还真是好多地方都没看懂。这算是之前的测试结果把。

Android新建一个相册_Android新建一个相册

DrawableLoader

1 package com.jd.net;
 2 
 3 import java.lang.ref.SoftReference;
 4 import java.net.URL;
 5 import java.util.HashMap;
 6 import java.util.Map;
 7 import java.util.concurrent.ExecutorService;
 8 import java.util.concurrent.Executors;
 9 
10 import android.graphics.drawable.Drawable;
11 import android.os.Handler;
12 
13 public class DrawableLoader 
14 {
15     public Map<String, SoftReference<Drawable>> imageCache = 
16             new HashMap<String, SoftReference<Drawable>>();
17     
18     private ExecutorService executorService = Executors.newFixedThreadPool(2);
19     
20     private final Handler handler = new Handler();
21     
22     
23     public DrawableLoader()
24     {
25         
26     }
27     
28     public Drawable loadDrawable(final String imageUrl,
29             final ImageCallback callback)
30     {
31         if(imageCache.containsKey(imageUrl))
32         {
33             SoftReference<Drawable>  softReference = imageCache.get(imageUrl);
34             if(softReference.get() != null)
35             {
36                 return softReference.get();
37             }
38         }
39         
40         executorService.submit(new Runnable() {
41             
42             public void run() {
43                 // TODO Auto-generated method stub
44                 try
45                 {
46                     final Drawable drawable = loadImageFromUrl(imageUrl);
47                     imageCache.put(imageUrl, new SoftReference<Drawable>(drawable));
48                     handler.post(new Runnable() {
49                         
50                         public void run() {
51                             // TODO Auto-generated method stub
52                             callback.imageLoaded(drawable);
53                         }
54                     });
55                 }
56                 catch(Exception e)
57                 {
58                     throw new RuntimeException(e);
59                 }
60             }
61         });
62         return null;
63     }
64     
65     protected Drawable loadImageFromUrl(String imageUrl)
66     {
67         try
68         {
69 //            SystemClock.sleep(3000);
70             return Drawable.createFromStream(new URL(imageUrl).openStream(),"image.png");
71         }
72         catch(Exception e)
73         {
74             throw new RuntimeException(e);
75         }
76     }
77     
78     public interface ImageCallback
79     {
80         public void imageLoaded(Drawable imageDrawable);
81     }
82 }


接下来的测试目标步骤:

    1,根据给定的url,加载一张图片到一个ImageView对象里,并且显示出来;

    2,让这个ImageView对象从一个点移动到另一个点;

  3,让这个ImageView对象在加载好后就显示为小图,点击后等比例放大

===========================================

昨天也就是1月23号在网上找了好久资料发现无法在不使用layout配置文件的情况下把一个ImageView对像添加到了View对象里。用位图Bitmap的话倒是可以通过android.graphics.Canvas的drawBitmap方法把一张bitmap添加到view, 然后发现之前利用线程加载图片是用的android.graphics.drawable.Drawable,而网上有提到Bitmap和Drawable这个抽象类的互相转换,那么就不用ImageView而改用Bitmap试试。

 

======================================

1月30号

到目前为止可以从网上加载一张位图显示到surfaceview里了。通过一个Thread可以让这张图片移动,每一帧都重绘canvas.drawBitmap()以达到移动的目的。

 

Android新建一个相册_Android新建一个相册

Android新建一个相册_System_03

MainSurfaceView

1 package com.jd.view;
  2 
  3 import android.content.Context;
  4 
  5 import android.graphics.Bitmap;
  6 import android.graphics.Canvas;
  7 import android.graphics.Color;
  8 import android.graphics.Paint;
  9 import android.graphics.drawable.Drawable;
 10 import android.view.MotionEvent;
 11 import android.view.SurfaceHolder;
 12 import android.view.SurfaceHolder.Callback;
 13 import android.view.SurfaceView;
 14 
 15 import com.jd.net.DrawableLoader;
 16 
 17 public class MainSurfaceView extends SurfaceView implements Callback,Runnable
 18 {
 19 
 20     private SurfaceHolder holder;
 21     private Paint paint;
 22     private DrawableLoader drawableLoader;
 23     private Bitmap bitmap;
 24     private int bitmapPosX;
 25     private int bitmapPosY;
 26     
 27     private boolean flag;
 28     private Thread th;
 29     
 30     public MainSurfaceView(Context context)
 31     {
 32         super(context);
 33         System.out.println("surfaceview new");
 34         holder = this.getHolder();
 35         holder.addCallback(this);
 36         paint = new Paint();
 37         paint.setColor(Color.WHITE);
 38         
 39         bitmapPosX = 10;
 40         bitmapPosY = 10;
 41     
 42     }
 43     
 44     @Override
 45     public boolean onTouchEvent(MotionEvent event)
 46     {
 47         // TODO Auto-generated method stub
 48 //        bitmapPosX = (int) event.getX();
 49 //        bitmapPosY = (int) event.getY();
 50         flag = true;
 51         th = new Thread(this);
 52         th.start();
 53 //        myDraw();
 54         return true;
 55     }
 56     
 57     @Override
 58     public void surfaceCreated(SurfaceHolder holder)
 59     {
 60         System.out.println("surfaceview created");
 61     
 62         loadImage();
 63     }
 64     
 65     @Override
 66     public void run()
 67     {
 68         // TODO Auto-generated method stub
 69         while(flag)
 70         {
 71             long start = System.currentTimeMillis();
 72             bitmapPosY++;
 73             
 74             myDraw();
 75             long end = System.currentTimeMillis();
 76             try {
 77                 if (end - start < 50) {
 78                     Thread.sleep(50 - (end - start));
 79                 }
 80             } catch (InterruptedException e) {
 81                 e.printStackTrace();
 82             }
 83         }
 84     }
 85     
 86     public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3)
 87     {
 88         System.out.println("surfaceview changed");
 89     }
 90     public void surfaceDestroyed(SurfaceHolder arg0)
 91     {
 92 
 93     }
 94     
 95     private void loadImage()
 96     {
 97         String imageUrl = "http://i1.sinaimg.cn/dy/FocusPic/124/2008-03-24/U4708P1T124D2F2633DT20120129110520.jpg";
 98         drawableLoader = new DrawableLoader();
 99         //如果内存中没有加载过这张图片,那么就开始用线程加载,通过回调拉倒加到的图片
100         Drawable cacheImage = drawableLoader.loadDrawable(imageUrl,
101                 new DrawableLoader.ImageCallback()
102                 {
103                     
104                     public void imageLoaded(Drawable imageDrawable)
105                     {
106                         int w = imageDrawable.getIntrinsicWidth();
107                         int h = imageDrawable.getIntrinsicHeight();
108                         String wStr = String.valueOf(w);
109                         String hStr = String.valueOf(h);
110                         
111                         System.out.println("image loaded success");
112                         System.out.println("图片宽为"+wStr);
113                         System.out.println("图片高为"+hStr);
114                         
115                         bitmap = BitmapTool.drawableToBitmap(imageDrawable);
116                         myDraw();
117                     }
118                 });
119                 
120         //如果内存中曾经加载过此图,就不会调用回调方法,而是把cacheImage给返回
121         if(cacheImage != null)
122         {
123             System.out.println("内存中存在此图");
124             int w = cacheImage.getIntrinsicWidth();
125             int h = cacheImage.getIntrinsicHeight();
126             String wStr = String.valueOf(w);
127             String hStr = String.valueOf(h);
128             
129             System.out.println("image loaded success");
130             System.out.println("图片宽为"+wStr);
131             System.out.println("图片高为"+hStr);
132             
133             bitmap = BitmapTool.drawableToBitmap(cacheImage);
134             myDraw();
135         }
136     }
137     
138     private void myDraw()
139     {
140         if(bitmap == null)
141         {
142             return;
143         }
144         
145         Canvas canvas = holder.lockCanvas();
146         canvas.drawColor(Color.BLACK);
147 //        canvas.save();
148 //        canvas.scale(0.5f, 0.5f,bitmap.getWidth() / 2,bitmap.getHeight() / 2);
149         canvas.drawBitmap(bitmap, bitmapPosX,bitmapPosY, paint);
150 //        canvas.restore();
151 //        canvas.drawBitmap(bitmap, 20,50, paint);
152         holder.unlockCanvasAndPost(canvas);
153     }
154 }

 

Android新建一个相册_Android新建一个相册

Android新建一个相册_System_03

BitmapTool

1 package com.jd.view;
 2 
 3 import android.graphics.Bitmap;
 4 
 5 import android.graphics.drawable.BitmapDrawable;
 6 import android.graphics.drawable.Drawable;
 7 
 8 public class BitmapTool
 9 {
10     public static Bitmap drawableToBitmap(Drawable drawable)
11     {
12         BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
13         return bitmapDrawable.getBitmap();
14     }
15 }

总结一下,根据这几天在网上和书上的有限的资料里了解到,要想改变位图的位置,大小,并不是像ActionScrtipt里bitmap.x,bitmap.y,bitmap.scaleX,bitmap.scaleY等等属性直接改变位图的显示属性,而是要通过代码反复重绘位图所在的view的画布canvas,官方文档没有怎么瞅,不知是否有更方便的方法。

 

哈,虽说AS把显示对象封装地比较好用,什么.addChild,.x,.y,.scale之类的,但底层我觉得也因该是一样的机制,重绘呗。

留下来两个问题:

1,AS里一张位图被添加到舞台上,若再添加一张位图并想让前者不可见,那么就要把前者removeChild掉,而android里重绘时直接给canvas绘制一下颜色就貌似移除之前的位图了,然后再绘制新图。前面的位图不可见了,那么这时前一张位图所占的内存是否可以被自动回收了呢,是否要通过代码做些销毁处理?

2,Canvas,一个SurfaceView是否就只有一张画图?如果要在一个Activity里显示多张位图,那么这些位图是必须在同一个canvas里?还是可以被绘制在不同的canvas里?canvas是否有x,y,width,height等属性呢?