我正在使用两种不同的颜色创建不同的自定义视图。根据我的应用功能,当拖动对象相互重叠时,用户将在屏幕上拖动这些对象。我想区分重叠区域,如何设置重叠区域的组合颜色。 请看下面的图片。在这里,我使用画布创建这些自定义视图,两个圆圈是两个不同的视图。
编辑:如果我使用不透明度128,我可以看到背景颜色,但我想要重叠对象颜色的组合颜色。
答案 0 :(得分:21)
您正在寻找的颜色混合有时称为直观的颜色混合,或RYB颜色系统:
<强> RYB 强>:
<子> <子> CC license 子> 子>
Nathan Gossett和Baoquan Chen撰写的关于直观颜色混合算法的this论文引用了直观颜色系统的工作原理:
“在这个模型中,红色,黄色和蓝色用作纯原色。红色和黄色混合形成橙色,黄色和蓝色混合形成绿色,蓝色和红色混合形成紫色[...]。这些是未经训练的观察者期望使用儿童油漆获得的颜色[...]。此外,许多人并不认为白色是所有颜色的混合物,而是缺少颜色(空白画布)。一个更常见的假设是将多种颜色混合在一起会产生泥泞的深棕色。“
RYB未在Android的混合模式中实现,并且无法通过混合alpha /不同混合模式来真正模拟。
大多数计算机图形应用程序都使用 RGB 或 CMYK 颜色空间:
<强> CMYK 强>:
<子> <子> CC license 子> 子>
CMY基于减色。减色混合意味着,从白色开始,当我们添加颜色时,结果会变暗。 CMYK用于混合用于打印的图像中的颜色。 Photoshop和Illustrator。
<强> RGB 强>:
RGB基于添加颜色。使用加色方法用光创建计算机屏幕上的颜色。添加剂颜色混合从黑色开始,添加更多颜色,结果变浅,并以白色结束。
This网站更详细地讨论了CMYK和RGB。
在RGB和CMYK中,混合蓝色和黄色都会产生绿色,或者一般来说,直观的颜色混合。在Android上实现RYB颜色系统将非常复杂。上面引用的Nathan Gossett和Baoquan Chen的论文提出了一种解决方案,其最后用C语言实现了算法。此算法可以在Android上的自定义混合中实现。 Drawable.setColorFilter()
使用扩展PorterDuffColorfilter
的ColorFilter
。 ColorFilter
中讨论的子this子类化问题必须使用NDK在本机代码中完成。
CMYK颜色混合解决方法
如果您对使用CMYK颜色混合作为解决方法感兴趣,我已经包含了一个如何在下面完成它的基本示例。在此示例中,将混合青色圆圈和黄色圆圈以产生绿色交叉点。
从Adobe Illustrator中创建的这些.png图像文件开始:
十六进制颜色值0x00ffff(青色)和0xffff00(黄色)。
将它们添加到名为cyancircle.png和yellowcircle.png的drawable文件夹中。
按如下方式配置main.xml布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#ffffff"
android:padding="30dp">
<ImageView
android:id="@+id/bluecircle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/cyancircle">
</ImageView>
<ImageView
android:id="@+id/yellowcircle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/yellowcircle"
android:layout_marginTop="30dp">
</ImageView>
</RelativeLayout>
创建您的活动:
import android.app.Activity;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.widget.ImageView;
public class PorterDuffTestActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageView yellowCircle = (ImageView)findViewById(R.id.yellowcircle);
yellowCircle.getDrawable().setColorFilter(0x88ffff00, PorterDuff.Mode.MULTIPLY);
}
}
输出:
此方法的限制是顶部形状的alpha必须设置为50%(“0x88ffff00”中的“88”)。对于黄色,这可以很好地工作但是对于其他颜色,α效果可能是不可接受的(颜色可能看起来是另一种颜色,例如红色变成粉红色,白色背景上具有低α值)。哪种混合模式最终可以接受取决于您将要使用的颜色集,并将进行一些实验。另请注意,背景颜色可能会影响混合模式下的圆圈颜色。在此示例中,背景设置为白色。
答案 1 :(得分:5)
我为6个对象做了另一个example。
要点:
onDraw方法不会覆盖对象视图,后台也会设置为透明
setBackgroundColor(Color.TRANSPARENT);
但是,onDraw方法将被重命名为onDrawEx将从Overlay View调用。
public void onDrawEx(Canvas canvas){
叠加视图将传递自定义画布以进行绘制。在传递给对象视图之前,它将做必要的翻译。
mOverlayView = new View(this){
@Override
protected void onDraw(Canvas canvas) {
Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888);
Canvas canvasBitmap = new Canvas(bitmap);
ViewGroup viewGroup = (ViewGroup)getParent();
for(int i = 0 ; i < viewGroup.getChildCount()-1;i++){
ObjectView objectView = (ObjectView) viewGroup.getChildAt(i);
canvasBitmap.save();
canvasBitmap.translate(objectView.getTranslationX(), objectView.getTranslationY());
objectView.onDrawEx(canvasBitmap);
canvasBitmap.restore();
}
canvas.drawBitmap(bitmap, 0, 0, new Paint());
}
};
使用mPaint.setXfermode(new PorterDuffXfermode(Mode.ADD));添加颜色。但是所有对象都应该使用像0xFF000030,0xFF0000C0,0xFF003000,0xFF00C000,0xFF300000,0xC00000这样的颜色,然后只对所有可能的重叠我们可以得到不同的颜色。这取决于你的最大物体数量。
int k = 0 ;
for(int i = 0 ; i < 2;i++,k++){
int color = 0xFF000000|(0x000030<<i*2);
frameLayout.addView(new ObjectView(this,color,k*50,k*50,k), new FrameLayout.LayoutParams(50, 50));
}
for(int i = 0 ; i < 2;i++,k++){
int color = 0xFF000000|(0x003000<<i*2);
frameLayout.addView(new ObjectView(this,color,k*50,k*50,k), new FrameLayout.LayoutParams(50, 50));
}
for(int i = 0 ; i < 2;i++,k++){
int color = 0xFF000000|(0x300000<<i*2);
frameLayout.addView(new ObjectView(this,color,k*50,k*50,k), new FrameLayout.LayoutParams(50, 50));
}
我在modified支持版本8
使用
mPaint.setXfermode(new PixelXorXfermode(0x00000000));
代表
mPaint.setXfermode(new PorterDuffXfermode(Mode.ADD));
我使用layout参数进行翻译。
答案 2 :(得分:3)
我能想到的最简单的解决方案是简单地使用alpha通道,将每个通道设置为0.5不透明度,无论是代码还是xml。然后,当它们重叠时,颜色应该相互淡化。这意味着非重叠部分的颜色会有点褪色,并且根据形状背后的背景,使它们完全透明可能看起来不太好。
答案 3 :(得分:3)
我创建了一个包含两个视图的示例Activity DemoDrawShapeActivity在view2中我使用canvas.clipPath和canvas.translate
为此工作我设置了最低sdk版本4
protected void onDraw(Canvas canvas) {
Paint paint = new Paint();
paint.setColor(Color.RED);
path2.addCircle(getWidth()/2, getHeight()/2, getWidth()/2, Direction.CCW);
canvas.drawPath(path2, paint);
canvas.clipPath(path2);
canvas.save();
canvas.translate(-getTranslationX()+view1.getTranslationX(), -getTranslationY()+view1.getTranslationY());
paint.setColor(Color.BLUE|Color.RED);
canvas.drawPath(path1, paint);
canvas.restore();
}
你可以编辑paint.setColor(Color.BLUE | Color.RED);根据你的逻辑得到必要的颜色。
我正在使用setTranslationX setTranslationY来移动视图。
public boolean onTouchEvent(MotionEvent event) {
switch(event.getActionMasked()){
case MotionEvent.ACTION_UP:
touched[0]=touched[1]=false;
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
if(touched[1]){
view2.setTranslationX(event.getX()-view2.getWidth()/2);
view2.setTranslationY(event.getY()-view2.getHeight()/2);
}else if(touched[0]){
view1.setTranslationX(event.getX()-view1.getWidth()/2);
view1.setTranslationY(event.getY()-view1.getHeight()/2);
view2.invalidate();
}
}
return true;
}
答案 4 :(得分:2)
我认为您可能希望以混合模式进行绘制。 Android会让你这样做,只需看看这个第一个链接。 Composite operations in Android Canvas
以下是所有合成选项 http://developer.android.com/reference/android/graphics/PorterDuffXfermode.html
他们对Mozilla的解释 https://developer.mozilla.org/en/Canvas_tutorial/Compositing
答案 5 :(得分:-1)
你可以从这里得到帮助 -
http://www.learnopengles.com/android-lesson-five-an-introduction-to-blending/
和
www.pushing-pixels.org/category/android/page/6