Android仿海报工厂(完)

作者: MartinBZDQSM | 来源:发表于2016-08-26 22:31 被阅读1344次

    **0.0
    东西到这里差不多到一段落了,整体效果还算比较成功的,好像就焦点释放有些问题,当然还有很多瑕疵,这个完全可以根据自己需求去修改啦,我有空也会改改的。
    **
    先放图:

    pre.gif
    filter.gif switch.gif

    上篇文章投稿“程序员”的时候被驳回了,原因是因为图片不雅观,所以这次就换了几张图。····

    有点gay.jpg

    下面讲讲主要更新的几个地方:

    (一)图层的缩放?

    图层的缩放需要计算双指最开始Down下的距离与Move过程中的距离的比值。
    而所得出的scale比例都必须在上次scale的前提下进行,多指触控的代码我就不放出来了,大家可以去去看demo

    图片缩放的代码如下,这里采用的是Matrix的缩放:

    /**
         * 缩放图层
         *
         * @param toSacle
         */
        protected void scaleLayer(float toSacle) {
            scale = scale * toSacle;
            if (scale >= max_scale)
                scale = max_scale;
            if (scale <= min_scale)
                scale = min_scale;
            Bitmap scaleLayer;
            if (filterLayer != null) {
                scaleLayer = BitmapUtils.scaleBitmap(filterLayer, scale);
            } else {
                scaleLayer = BitmapUtils.scaleBitmap(layer, scale);
            }
            BitmapUtils.destroyBitmap(drawLayer);
            drawLayer = scaleLayer;
            // 更新Layer的坐标
            setLayerX(x - (drawLayer.getWidth() - width) / 2);
            setLayerY(y - (drawLayer.getHeight() - height) / 2);
            width = drawLayer.getWidth();
            height = drawLayer.getHeight();
        }
    

    (二)如何替换图片顺序?

    先来分析下替换图层顺序的是一个什么样情景:
    1.手指选中一张图层进行拖拽
    2.拖拽过程中,坐标超出图层范围(这里并不只针对layer的范围,还有一个平移的最大边境)
    3.拖拽至其他非选中layer范围当中,在松手的同时,切换相对应的图层。

    这里感觉困难的地方主要还是在情景状态的判断,与ui变化,真要文字描述起来还挺烦人的,所以小伙伴们还是去看代码吧,这里就不写啦···

    (三)如何设置图片滤镜?

    滤镜使用的是之前在Matrix(三)自己封装的ColorFilter类。
    在绘制的时候新增了一个的图片对象,当判断滤镜图片不为空的时候,所进行的图片缩放使用不在是原图,而是滤镜图片,代码如下:

      /**
         * 设置滤镜图片
         *
         * @param filterLayer
         */
        public void setFilterLayer(Bitmap filterLayer) {
            this.filterLayer = filterLayer;
            //因为当前绘制的图片使用的是原图(或者滤镜图)缩放过后的图,
            //所以当有滤镜图存在的同时需要将滤镜图进行缩放
            scaleLayer(1);
        }
    
        /**
         * 去除滤镜图
    ![Upload filter.gif failed. Please try again.]
         */
        public void clearFilter() {
            BitmapUtils.destroyBitmap(filterLayer);//方法里有致空操作
            filterLayer = null;
            scaleLayer(1);
        }
    

    这个挺简单的,如果当你们的滤镜比较耗时时,处理完成之后将图片设置回来即可,当然我还没有做图层内部的刷新,所以在设置完图片滤镜之后需要刷新modelview。

    (四)如何在图层上面进行弹窗?

    我将重新封装了一层PosterView继承RelativeLayout,将modelview和菜单的view都添加在里面,主要代码:

      private void viewInit() {
            modelView = new ModelView(getContext());
            modelParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
            addView(modelView, modelParams);
        }
    
        /**
         * 滤镜菜单初始化,并设置宽高
         *
         * @param menu
         * @param menuWidth
         */
        public void addMenuInit(View menu, int menuWidth, int menuHeight) {
            this.menu = menu;
            menuParams = new LayoutParams(menuWidth, menuHeight);
            addView(menu, menuParams);
            menu.setVisibility(GONE);
        }
    
        public void dissMenu() {
            if (null != menu)
                menu.setVisibility(GONE);
        }
    
        public void showMenu(Layer layer) {
            Layer.MenuPoint menuPoint = layer.getFrontMenuPoint(getHeight(), menuParams.height);
            PointF pointf = menuPoint.point;
            if (pointf.x + menuParams.width >= width) {
                pointf.x = width - menuParams.width;
            }
            if (menuPoint.direction == 1) {
                pointf.y = pointf.y - menuParams.height;
            }
            menuParams.setMargins((int) pointf.x, (int) pointf.y, 0, 0);
            menu.setLayoutParams(menuParams);
            if (null != menu)
                menu.setVisibility(VISIBLE);
    
        }
    

    上面代码中的 Layer.MenuPoint 乃是我在layer中计算出合适的菜单弹出的位置

      /**
         * 计算出菜单弹出的最优点
         *
         * @return
         */
        public MenuPoint getFrontMenuPoint(int height, int menuHeight) {
            PointF point = new PointF();
            MenuPoint menuPoint = null;
            if (height - MaxMenuPadding < layerRectF.bottom + menuHeight) {
                point.set(layerRectF.left, layerRectF.top);
                menuPoint = new MenuPoint(1, point);
            } else {
                point.set(layerRectF.left, layerRectF.bottom);
                menuPoint = new MenuPoint(0, point);
            }
            return menuPoint;
        }
    
        /**
         * 定义菜单坐标对象,
         * direction对应方向,0代表上,1代表下
         */
        public static class MenuPoint {
            int direction;
            PointF point;
    
            public MenuPoint(int direction, PointF point) {
                this.direction = direction;
                this.point = point;
            }
        }
    

    (五)如何保存结果?

    要想获取结果Bitmap的写法有很多,我这里生成了一张Bitmap,再获取它的Canvas对象重新进行绘制。如下:

        public Bitmap getResult() {
            model.releaseAllFocus();//去除所有焦点,并刷新视图
            this.invalidate();
            result = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(result);
            this.draw(canvas);
            return result;
        }
    

    你也可以直接在FirstDraw的时候生成一张等高宽的图片,使用图片的canva进行绘图,再绘制bitmap。
    你更可以直接使用view截图的方式进行获取,但是需要注意的就是,在生成图片之前必须释放所有焦点,并刷新组件,不然 结果中会绘制边框或者其他的东西。

    项目地址

    最新修改:解决旋转180度平移反向的问题。

    相关文章

      网友评论

      本文标题:Android仿海报工厂(完)

      本文链接:https://www.haomeiwen.com/subject/kvyosttx.html