android 自定义海报,Android仿海报工厂(完)

本文介绍了Android应用程序中实现图层缩放、图片顺序替换、滤镜设置、弹窗显示以及结果保存的方法。通过计算双指触摸的距离比例实现图层缩放,利用自定义的ColorFilter类应用滤镜效果,详细讲解了状态判断和UI更新的难点。此外,还展示了如何在图层上方弹出菜单,并讨论了保存最终结果的不同方式,包括处理旋转180度时平移反向问题的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

**0.0

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

**

先放图:

7ec2d62ae9f8?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

pre.gif

7ec2d62ae9f8?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

filter.gif

7ec2d62ae9f8?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

switch.gif

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

7ec2d62ae9f8?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

有点gay.jpg

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

(一)图层的缩放?

图层的缩放需要计算双指最开始Down下的距离与Move过程中的距离的比值。

而所得出的scale比例都必须在上次scale的前提下进行,多指触控的代码我就不放出来了,大家可以去去看

图片缩放的代码如下,这里采用的是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度平移反向的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值