如何将 2 个 imageViews 放在另一个之上,将它们混合在一起?
How to put 2 imageViews, one on top of another, that will blend them both?
背景
我有 2 个 imageView,一个在另一个之上,它们一起有一个动画。在这个动画过程中,我需要它们相互融合,使用 "Multiply" 效果。
类似于 this question 的东西,它是关于颜色的,但带有图像(在我的例子中是 VectorDrawable,但如果需要我可以使用 PNG 代替)。
这里有一个草图来演示我想做什么:
请注意,重叠的图像部分比箭头的原始颜色更暗。
问题
目前我还没有找到办法。我当然知道如何将一个视图放在另一个视图之上,但是我找不到根据另一个更改位图的一部分颜色的方法。
我发现了什么
我尝试使用:
imageView.getDrawable().setColorFilter(..., PorterDuff.Mode.MULTIPLY)
对于两个 ImageView,但它似乎不起作用。它所做的实际上是改变 imageView 的整个颜色,与我作为参数提供的颜色合并。
有道理,因为它只是一个colorFilter,类似于tint。
我也为每个 ImageView 尝试了 alpha,但这也意味着 ImageView 的一部分(不重叠的部分)将具有半透明颜色。
理论上我可以得到它们每个的位图,然后对结果进行过滤,但这不切实际,因为我需要在两者之间的动画中显示它。
问题
如何混合 2 个图像视图?
由于您使用的是 VectorDrawable,您是否考虑过为可绘制对象而不是视图设置动画?
https://developer.android.com/reference/android/graphics/drawable/AnimatedVectorDrawable.html
试试这个:
public Bitmap combineImages(Bitmap frame, Bitmap image) {
Bitmap cs = null;
Bitmap rs = null;
rs = Bitmap.createScaledBitmap(frame, image.getWidth(),
image.getHeight(), true);
cs = Bitmap.createBitmap(rs.getWidth(), rs.getHeight(),
Bitmap.Config.RGB_565);
Canvas comboImage = new Canvas(cs);
comboImage.drawBitmap(image, 0, 0, null);
comboImage.drawBitmap(rs, 0, 0, null);
if (rs != null) {
rs.recycle();
rs = null;
}
Runtime.getRuntime().gc();
return cs;
}
好的,由于它们在 Android 上的工作方式,使用 2 个视图似乎是不可能的,因此,我想展示如何使用 LayerDrawable 来代替:
public class LD extends LayerDrawable {
private Paint p = new Paint();
public LD(Drawable[] layers) {
super(layers);
p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
int count = canvas.saveLayer(null, null, Canvas.ALL_SAVE_FLAG);
for (int i = 0, numberOfLayers = getNumberOfLayers(); i < numberOfLayers; ++i) {
this.getDrawable(i).draw(canvas);
canvas.saveLayer(null, p, Canvas.ALL_SAVE_FLAG);
}
canvas.restoreToCount(count);
//original code:
//int count = canvas.saveLayer(null, null, Canvas.ALL_SAVE_FLAG);
//this.getDrawable(0).draw(canvas);
//canvas.saveLayer(null, p, Canvas.ALL_SAVE_FLAG);
//this.getDrawable(1).draw(canvas);
//canvas.restoreToCount(count);
}
}
用法:
ImageView imageView = (ImageView) findViewById(R.id.imageView);
Drawable drawable1 = AppCompatResources.getDrawable(this, R.drawable....);
Drawable drawable2 = AppCompatResources.getDrawable(this, R.drawable....);
Drawable drawable3 = AppCompatResources.getDrawable(this, R.drawable....);
LD layerDrawable = new LD(new Drawable[]{
drawable1,
drawable2,
drawable3
});
imageView.setImageDrawable(layerDrawable);
背景
我有 2 个 imageView,一个在另一个之上,它们一起有一个动画。在这个动画过程中,我需要它们相互融合,使用 "Multiply" 效果。
类似于 this question 的东西,它是关于颜色的,但带有图像(在我的例子中是 VectorDrawable,但如果需要我可以使用 PNG 代替)。
这里有一个草图来演示我想做什么:
请注意,重叠的图像部分比箭头的原始颜色更暗。
问题
目前我还没有找到办法。我当然知道如何将一个视图放在另一个视图之上,但是我找不到根据另一个更改位图的一部分颜色的方法。
我发现了什么
我尝试使用:
imageView.getDrawable().setColorFilter(..., PorterDuff.Mode.MULTIPLY)
对于两个 ImageView,但它似乎不起作用。它所做的实际上是改变 imageView 的整个颜色,与我作为参数提供的颜色合并。
有道理,因为它只是一个colorFilter,类似于tint。
我也为每个 ImageView 尝试了 alpha,但这也意味着 ImageView 的一部分(不重叠的部分)将具有半透明颜色。
理论上我可以得到它们每个的位图,然后对结果进行过滤,但这不切实际,因为我需要在两者之间的动画中显示它。
问题
如何混合 2 个图像视图?
由于您使用的是 VectorDrawable,您是否考虑过为可绘制对象而不是视图设置动画?
https://developer.android.com/reference/android/graphics/drawable/AnimatedVectorDrawable.html
试试这个:
public Bitmap combineImages(Bitmap frame, Bitmap image) {
Bitmap cs = null;
Bitmap rs = null;
rs = Bitmap.createScaledBitmap(frame, image.getWidth(),
image.getHeight(), true);
cs = Bitmap.createBitmap(rs.getWidth(), rs.getHeight(),
Bitmap.Config.RGB_565);
Canvas comboImage = new Canvas(cs);
comboImage.drawBitmap(image, 0, 0, null);
comboImage.drawBitmap(rs, 0, 0, null);
if (rs != null) {
rs.recycle();
rs = null;
}
Runtime.getRuntime().gc();
return cs;
}
好的,由于它们在 Android 上的工作方式,使用 2 个视图似乎是不可能的,因此,我想展示如何使用 LayerDrawable 来代替:
public class LD extends LayerDrawable {
private Paint p = new Paint();
public LD(Drawable[] layers) {
super(layers);
p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
int count = canvas.saveLayer(null, null, Canvas.ALL_SAVE_FLAG);
for (int i = 0, numberOfLayers = getNumberOfLayers(); i < numberOfLayers; ++i) {
this.getDrawable(i).draw(canvas);
canvas.saveLayer(null, p, Canvas.ALL_SAVE_FLAG);
}
canvas.restoreToCount(count);
//original code:
//int count = canvas.saveLayer(null, null, Canvas.ALL_SAVE_FLAG);
//this.getDrawable(0).draw(canvas);
//canvas.saveLayer(null, p, Canvas.ALL_SAVE_FLAG);
//this.getDrawable(1).draw(canvas);
//canvas.restoreToCount(count);
}
}
用法:
ImageView imageView = (ImageView) findViewById(R.id.imageView);
Drawable drawable1 = AppCompatResources.getDrawable(this, R.drawable....);
Drawable drawable2 = AppCompatResources.getDrawable(this, R.drawable....);
Drawable drawable3 = AppCompatResources.getDrawable(this, R.drawable....);
LD layerDrawable = new LD(new Drawable[]{
drawable1,
drawable2,
drawable3
});
imageView.setImageDrawable(layerDrawable);