Android自定义控件-地图之放大镜的实现

Android自定义控件-地图之放大镜的实现,第1张

概述最近半年一直在忙公司的GIS SDK,底层是公司的C++大佬来实现,我负责实现framework层,这不,大佬觉得C++实现的放大镜控件扩展性太差,就让我用Android自定义一个放大镜控件,方便后期扩展,要求嘛,和C++实现的要一模一样,手指触摸地图,放大触摸点的图像。 1.需求分析需求:手指拖拽节点的时

最近半年一直在忙公司的GIS SDK,底层是公司的C++大佬来实现,我负责实现framework层,这不,大佬觉得C++实现的放大镜控件扩展性太差,就让我用AndroID自定义一个放大镜控件,方便后期扩展,要求嘛,和C++实现的要一模一样,手指触摸地图,放大触摸点的图像。

 1.需求分析

需求:手指拖拽节点的时候,放大镜出现,放大触摸点的图像,放大镜可以随着手指移动,放大镜不允许出现移出屏幕外的 *** 作,放大镜需要有拟物效果。

实现方案:去网上找了一下,大致为:加载整个界面的Bitmap,然后手指移动,然后裁剪手指的这个范围的画布,然后再放大绘制出来,问题来了,我的需求是在地图上实现放大镜,地图是可以拖动的,不可能地图随便拖动一点,就更新一个新的Bitmap,那得卡死,最好是只获取手指触摸点的那块的小范围的Bitmap,去看了一下地图控件,是一个SurfaceVIEw,那是不是可以用OPENGL 来获取;

图:

2.开始着手分析绘制过程:

1.获取手指触摸范围的Bitmap对象,看是否可行,不就就白搭:

代码如下:

 /**     * @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;    }

 

2.测试了一下,Bitmap拿到了,那就很香了,剩下的一步就是把放大镜绘制出来,先不考虑放大镜随手指移动的情况,先实现放大镜效果:

 @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);        }    }

3.因为不是需要放大镜跟随手指,是需要放大镜跟随我的控件的拖拽节点,所以我去拖拽的监听方法里面去实时获取x,y,并拿到Bitmap(可以根据需求的不同,去对应的地方获取,比如Ontouch)

       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();            }        });

4.功能基本就实现了,也没什么,最后处理一下,手指在上下左右四个边界和几个角度的特殊情况,避免出现手指挡出放大镜之类的影响用户看的情况:

      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);        }

总结:因为这个放大镜不是固定位置,也不是写在xml中,我也就不考虑onMeasure了,直接只使用了onDraw绘制,如果遇到了需要去放大地图的情况,可以参考,就这样,,,

总结

以上是内存溢出为你收集整理的Android自定义控件-地图之放大镜的实现全部内容,希望文章能够帮你解决Android自定义控件-地图之放大镜的实现所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1058632.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存