Android仿海报工厂(完)

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

《Android仿海报工厂(完)》 pre.gif

《Android仿海报工厂(完)》 filter.gif
《Android仿海报工厂(完)》 switch.gif

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

《Android仿海报工厂(完)》 有点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度平移反向的问题。

    原文作者:MartinBZDQSM
    原文地址: https://www.jianshu.com/p/7ec2d62ae9f8
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞