最近半年一直在忙公司的GIS SDK,底层是公司的C++大佬来实现,我负责实现framework层,这不,大佬觉得C++实现的放大镜控件扩展性太差,就让我用Android自定义一个放大镜控件,方便后期扩展,要求嘛,和C++实现的要一模一样,手指触摸地图,放大触摸点的图像。 需求:手指拖拽节点的时候,放大镜出现,放大触摸点的图像,放大镜可以随着手指移动,放大镜不允许出现移出屏幕外的操作,放大镜需要有拟物效果。 实现方案:去网上找了一下,大致为:加载整个界面的Bitmap,然后手指移动,然后裁剪手指的这个范围的画布,然后再放大绘制出来,问题来了,我的需求是在地图上实现放大镜,地图是可以拖动的,不可能地图随便拖动一点,就更新一个新的Bitmap,那得卡死,最好是只获取手指触摸点的那块的小范围的Bitmap,去看了一下地图控件,是一个SurfaceView,那是不是可以用OPENGL 来获取; 图: 1.获取手指触摸范围的Bitmap对象,看是否可行,不就就白搭: 代码如下: 2.测试了一下,Bitmap拿到了,那就很香了,剩下的一步就是把放大镜绘制出来,先不考虑放大镜随手指移动的情况,先实现放大镜效果: 3.因为不是需要放大镜跟随手指,是需要放大镜跟随我的控件的拖拽节点,所以我去拖拽的监听方法里面去实时获取x,y,并拿到Bitmap(可以根据需求的不同,去对应的地方获取,比如OnTouch) 4.功能基本就实现了,也没什么,最后处理一下,手指在上下左右四个边界和几个角度的特殊情况,避免出现手指挡出放大镜之类的影响用户看的情况: 总结:因为这个放大镜不是固定位置,也不是写在xml中,我也就不考虑onMeasure了,直接只使用了onDraw绘制,如果遇到了需要去放大地图的情况,可以参考,就这样,,, 1.需求分析
2.开始着手分析绘制过程:
/** * @param x 手指的位置 * @param y 手指的位置 * @param width 放大镜的大小 * @param height 放大镜的大小 * @return */ private android.graphics.Bitmap readBufferPixelToBitmap(int x, int y, int width, int height) { ByteBuffer buf = ByteBuffer.allocateDirect(width * height * 4); buf.order(ByteOrder.LITTLE_ENDIAN); GLES20.glReadPixels(x, y, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buf); buf.rewind(); android.graphics.Bitmap bmp = android.graphics.Bitmap.createBitmap(width, height, android.graphics.Bitmap.Config.ARGB_8888); bmp.copyPixelsFromBuffer(buf); Matrix m = new Matrix(); // 水平翻转 m.setScale(1, -1); int w = bmp.getWidth(); int h = bmp.getHeight(); // 生成的翻转后的bitmap bmp = android.graphics.Bitmap.createBitmap(bmp, 0, 0, w, h, m, true); return bmp; }
@Override protected void onDraw(Canvas canvas) { if (bm != null) { //背景防止加载自带透明的图片时,放大图片后面能看到原来的图片 Paint paintBg = new Paint(); //抗锯齿 paintBg.setAntiAlias(true); paintBg.setColor(Color.parseColor("#ffffff")); canvas.drawCircle(magnifierLen / 2, magnifierLen / 2, magnifierLen / 2, paintBg); Paint paint = new Paint(); paint.setFlags(Paint.ANTI_ALIAS_FLAG); //抗锯齿 paint.setAntiAlias(true); //bitmapShader画圆形图片,也就是获取到的bitmap paint.setShader(bitmapShader); //创建矩阵,缩放平移图片 Matrix matrix = new Matrix(); matrix.setScale(scaleX, scaleY); //将获取到的图片平移到图片的正中心 matrix.postTranslate(-magnifierLen/2, -magnifierLen/2); //利用bitmapShader画圆形图片 bitmapShader.setLocalMatrix(matrix); canvas.drawCircle(magnifierLen / 2, magnifierLen / 2, magnifierLen / 2, paint); //设置一个蒙层效果,让效果看起来更好 Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.magnifierdest); // 获得图片的宽高 int width = bitmap.getWidth(); int height = bitmap.getHeight(); // 设置想要的大小 int newWidth = (int) magnifierLen; int newHeight = (int) magnifierLen; // 计算缩放比例 float scaleWidth = ((float) newWidth) / width; float scaleHeight = ((float) newHeight) / height; // 取得想要缩放的matrix参数 Matrix matrix1 = new Matrix(); matrix1.postScale(scaleWidth, scaleHeight); // 得到新的图片 Bitmap newbm = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix1, true); //创建一个画笔 Paint paintShade = new Paint(Paint.ANTI_ALIAS_FLAG); paintShade.setAlpha(magnifierAlpha); //重置画笔 paintShade.reset(); //调用截图图层的方法 paintShade.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER)); //画图片 canvas.drawBitmap(newbm, 0, 0, paintShade); } }
Bitmap bm = readBufferPixelToBitmap(x, y, viewW, viewH); //利用BitmapShader画圆,模式可以查询用法 BitmapShader bitmapShader = new BitmapShader(bm, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); activityWeakReference.get().runOnUiThread(new Runnable() { @Override public void run() { //去从新绘制放大镜 invalidate(); } });
x = (int) (dragInfo.getScreenPos().getX() - magnifierLen / 2);//dragInfo为拖拽点信息 y = (int) (height - dragInfo.getScreenPos().getY() - magnifierLen / 2); float x = dragInfo.getScreenPos().getX() - viewW; float y = dragInfo.getScreenPos().getY() - viewH; if (x>0&&y>0){ //正常情况放在手指头的左上角 setX(x); setY(y); }else if (x>0&&y<0){ //放在最顶上 setX(x); setY(0); }else if (x<0&&y>0){ //放在最左边 setX(0); setY(y); }else if (x<0&&y<0){ //在最顶上,向右平移一个单位 setY(0); setX(viewW); }
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算