(Android学习笔记四)立体Gallery和多点触控浏览图片

来源:互联网 发布:如何删除数据执行保护 编辑:程序博客网 时间:2024/04/29 12:26

   今天才刚考完试,终于有时间整理下之前写的一个小程序了,代码放在三维Gallery这里,有兴趣的可以下载。
   实现效果如图,从系统的MediaStore数据库读取图片,组成稍带立体感的Gallery。点击图片跳到另一个页面浏览,可以用一根手指拖动或者两根手指一起来放大缩小。

     
    程序包含5个JAVA文件。
    1 ThreeDimensionalGalleryActivity是主Activity,主界面main.xml只有一个元素---自写的GalleryFlow。这类遍历MediaStore数据库读取图片的URI,将URI数组传给ImageAdapter处理照片,同时设置ImageAdapter为GalleryFlow的适配器。添加图片的单击响应事件,单击图片将跳转至ImageDetailActivity。
    2 ImageAdapter继承自BaseAdapter,实现了常见的getView、getCount等接口。根据传进来的URI数组,读取图片并用Matrix倒转图像,用Canvas和Paint重新画出一个完整的Bitmap(包含原图、有阴影效果的倒影图像)。
   3 GalleryFlow继承自Gallery类,重写了getChildStaticTransformation方法,使得传统Gallery两边的图片稍微旋转倾斜,中间不变,产生立体效果。
   4 MultiPointTouchListener实现了OnTouchListener的接口,修改了onTouch方法,重新解析手指的触屏操作(平移、特别是缩放利用到多点触摸),并根据操作用Matrix处理传进来的ImageView。
   5 ImageDetailActivity仅展示用户点击的那张图片,设置OnTouchListener为MultiPointTouchListener。

  部分代码:

public class MultiPointTouchListener implements OnTouchListener {        // 利用Matrix来移动和缩放图片        Matrix matrix = new Matrix();        Matrix savedMatrix = new Matrix();        // 三种状态        static final int NONE = 0;        static final int DRAG = 1;        static final int ZOOM = 2;        int mode = NONE;        // 缩放用到的点,记录下来        PointF start = new PointF();        PointF mid = new PointF();        float oldDist = 1f;        @Override        public boolean onTouch(View v, MotionEvent event) {                ImageView view = (ImageView) v;                // 这里处理触屏事件                switch (event.getAction() & MotionEvent.ACTION_MASK) {                case MotionEvent.ACTION_DOWN://第一根手指按下                        matrix.set(view.getImageMatrix());                        savedMatrix.set(matrix);                        start.set(event.getX(), event.getY());                        mode = DRAG;                        break;                case MotionEvent.ACTION_POINTER_DOWN://第二根手指按下                        oldDist = spacing(event);                        if (oldDist > 10f) {                                savedMatrix.set(matrix);                                midPoint(mid, event);                                mode = ZOOM;                        }                        break;                case MotionEvent.ACTION_UP:                case MotionEvent.ACTION_POINTER_UP:                        mode = NONE;                        break;                case MotionEvent.ACTION_MOVE:                        if (mode == DRAG) {                                matrix.set(savedMatrix);                                //M' = T(dx, dy) * M,平移操作                                matrix.postTranslate(event.getX() - start.x, event.getY()                                                - start.y);                        } else if (mode == ZOOM) {                                float newDist = spacing(event);                                if (newDist > 10f) {                                        matrix.set(savedMatrix);                                        float scale = newDist / oldDist;                                        matrix.postScale(scale, scale, mid.x, mid.y);                                }                        }                        break;                }                view.setImageMatrix(matrix);                return true; // 表明事件已被处理        }                private float spacing(MotionEvent event) {                float x = event.getX(0) - event.getX(1);                float y = event.getY(0) - event.getY(1);                return FloatMath.sqrt(x * x + y * y);        }               private void midPoint(PointF point, MotionEvent event) {                float x = event.getX(0) + event.getX(1);                float y = event.getY(0) + event.getY(1);                point.set(x / 2, y / 2);         }}
读取MediaStore数据库,读到的URI写进数组。
 public boolean getPhotoURIs()    {        Uri uri=null;        String projection[]={MediaStore.Images.Media._ID};        try{        ContentResolver cr=this.getContentResolver();        Cursor cursor = cr.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,projection, null, null, null);        if(null==cursor)        return false;        if(cursor.getCount()==0){        cursor.close();        return false;        }        uriArray=new Uri[cursor.getCount()];        int i=0;        while(cursor.moveToNext()&&i<cursor.getCount()){        cursor.moveToPosition(i);        uri=Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails._ID))+"");        uriArray[i]=uri;        i++;                }        cursor.close();        }        catch(Exception ex){        ex.printStackTrace();        }        return true;    }
ImageAdapter里读取Bitmap,创建新位图:

   public boolean createReflectedImages() {     final int reflectionGap = 4;//倒影图和原图之间的距离     int index = 0;     for (Uri uri : mURIs)      {try {BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();        bitmapOptions.inSampleSize = 4;Bitmap originalImage = BitmapFactory.decodeStream(mContext.getContentResolver().openInputStream(uri),null,bitmapOptions);if(originalImage==null)continue;int width = originalImage.getWidth();    int height = originalImage.getHeight();    if(height<=0||width<=0)     continue;     //利用Matrix来创建倒影图,倒影高度为原图1/2      Matrix matrix = new Matrix();      matrix.preScale(1, -1);      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.drawBitmap(reflectionImage, 0, height + reflectionGap, null);      Paint paint = new Paint();      paint.setAntiAlias(false);      //给倒影设置阴影      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(300, 400));      mImages[index++] = imageView;//有占用内存过多的风险!} catch (FileNotFoundException e) {e.printStackTrace();}     }     return true;    }