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

   今天才刚考完试,终于有时间整理下之前写的一个小程序了,代码放在三维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;
    }





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值