¿Cómo establecer el color combinado para el área superpuesta de dos objetos de color diferentes?

Estoy creando diferentes vistas personalizadas con dos colores diferentes. De acuerdo con las características de mi aplicación, el usuario arrastrará esos objetos en la pantalla, cuando arrastrar objetos se superponen entre sí. Quiero diferenciar el área superpuesta, cómo establecer el color combinado para el área superpuesta. Mira la imagen de abajo. Aquí estoy usando la lona para crear esas vistas de encargo dos círculos son dos diversas vistas.

Introduzca aquí la descripción de la imagen

EDIT: Si utilizo la opacidad 128 puedo ver el color de fondo, pero quiero el color de la combinación de colores de objetos superpuestos.

La mezcla de color que está buscando se denomina a veces mezcla de color intuitiva o el sistema de color RYB :

RYB :

Introduzca aquí la descripción de la imagen Licencia CC

Una cita de este artículo de Nathan Gossett y Baoquan Chen sobre algoritmos para la mezcla intuitiva de colores resume cómo funciona el sistema de color intuitivo:

"En este modelo, Rojo, Amarillo y Azul se usan como colores primarios puros, mezclando Rojo y Amarillo para formar la mezcla de Naranja, Amarillo y Azul para formar Verde y Azul y Rojo para formar Púrpura. Colores que un espectador sin entrenamiento esperaría obtener con la pintura de los niños […] Además, muchas personas no piensan en el blanco como la mezcla de todos los colores, sino como la ausencia de color (un lienzo en blanco). Suposición sería que la mezcla de muchos colores juntos resultaría en un color marrón oscuro fangoso. "

RYB no está implementado en los modos de mezcla de Android y no se puede simular mediante la mezcla de alpha / diferentes modos de mezcla.

La mayoría de las aplicaciones de gráficos por ordenador utilizan los espacios de color RGB o CMYK :

CMYK :

Introduzca aquí la descripción de la imagen Licencia CC

CMY se basa en el color sustractivo. La mezcla de color sustractiva significa que, a partir de blanco, a medida que añadimos color, el resultado se vuelve más oscuro. CMYK se utiliza para mezclar colores en las imágenes destinadas a la impresión, por ejemplo, en Photoshop e Illustrator.

RGB :

Introduzca aquí la descripción de la imagen Licencia CC

RGB se basa en el color aditivo. Los colores de una pantalla de ordenador se crean con luz utilizando el método de color aditivo. La mezcla aditiva de color comienza con negro ya medida que se añade más color, el resultado se hace más claro y termina en blanco.

Este sitio discute CMYK y RGB con más detalle.

Ni en RGB ni en CMYK, la mezcla azul y amarillo produce mezclas de colores verdes o, en general, intuitivas. Para implementar un sistema de color RYB en Android estaría muy involucrado. El trabajo de Nathan Gossett y Baoquan Chen citado anteriormente propone una solución con un algoritmo implementado en C al final del artículo. Este algoritmo podría ser implementado en una mezcla personalizada en Android. Drawable.setColorFilter() utiliza PorterDuffColorfilter que extiende ColorFilter . La subclasificación de ColorFilter como se discutió en esta pregunta SO tendría que hacerse en código nativo usando el NDK.

Mezcla de colores CMYK

En caso de que esté interesado en utilizar una mezcla de colores CMYK como solución, he incluido un ejemplo básico de cómo se puede hacer a continuación. En este ejemplo, un círculo de color cian y un círculo de color amarillo se mezclarán para producir una intersección verde.

Comenzando con estos archivos de imagen .png creados en Adobe Illustrator:

Introduzca aquí la descripción de la imagen

Introduzca aquí la descripción de la imagen

Con valor de color hexadecimal 0x00ffff (cian) y 0xffff00 (amarillo).

Añádalos a su carpeta de dibujo con los nombres cyancircle.png y yellowcircle.png.

Configure su distribución main.xml de la siguiente manera:

 <?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> 

Crea tu Actividad:

 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); } } 

Salida:

Introduzca aquí la descripción de la imagen

La limitación a este método es que el alfa de la forma superior tiene que establecerse en 50% (el "88" en "0x88ffff00"). Para el amarillo esto funciona razonablemente bien, pero para otros colores el efecto alfa puede no ser aceptable (el color puede parecer otro color, por ejemplo, el rojo se vuelve rosa con valores alfa bajos en el fondo blanco). El modo de mezcla que es en última instancia aceptable para usted depende del conjunto de colores que va a utilizar y tomará algunos experimentos. Observe también que el color de fondo puede afectar los colores de los círculos en el modo de mezcla. En este ejemplo, el fondo se establece en blanco.

He hecho otro ejemplo para 6 objetos.

Introduzca aquí la descripción de la imagen

Puntos clave:

  1. El método onDraw no será reemplazado por las vistas de objetos y el fondo también se ajustará a la transparencia

    SetBackgroundColor (Color.TRANSPARENT);

  2. Sin embargo, el método onDraw se renombrará como onDrawEx se llamará desde Vista de superposición.

    Public void onDrawEx (Lienzo lienzo) {

  3. La vista superpuesta pasará un lienzo personalizado para dibujar. Antes de pasar a la vista de objeto hará necesario traducir.

      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()); } }; 
  4. Utilice el mPaint.setXfermode (nuevo PorterDuffXfermode (Mode.ADD)); Para agregar colores. Pero todos los objetos deben usar colores como 0xFF000030,0xFF0000C0,0xFF003000,0xFF00C000,0xFF300000,0xC00000 entonces solamente para toda la superposición posible podemos conseguir diversos colores. Esto es depende de usted número máximo de objeto.

      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)); } 

Aquí he modificado para apoyar la versión 8

utilizar

 mPaint.setXfermode(new PixelXorXfermode(0x00000000)); 

para

 mPaint.setXfermode(new PorterDuffXfermode(Mode.ADD)); 

Utilicé el parámetro de diseño para la traducción.

La solución más simple que puedo pensar sería simplemente utilizar el canal alfa mediante la configuración de cada 0,5 opacidad, ya sea en código o xml. Entonces los colores deben fundirse el uno al otro cuando se solapan. Esto significa que los colores en las secciones que no se superponen será un poco descolorido, sin embargo, y dependiendo de lo que el fondo que tiene detrás de las formas que no puede verse bien para que sean transparentes en absoluto.

He creado una muestra Actividad con dos vistas DemoDrawShapeActivity donde en la view2 utilizo canvas.clipPath y canvas.translate

Para trabajar esto i set mínimo sdk versión 4

Introduzca aquí la descripción de la imagen

 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(); } 

Puede editar paint.setColor (Color.BLUE | Color.RED); Para obtener el color necesario de acuerdo con su lógica.

Estoy utilizando setTranslationX setTranslationY para mover las vistas.

  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; } 

Creo que puede estar buscando para dibujar en un modo de mezcla. Android te permitirá hacer esto, solo mira este primer enlace. Operaciones compuestas en Android Canvas

Aquí están todas las opciones de composición http://developer.android.com/reference/android/graphics/PorterDuffXfermode.html

Y sus explicaciones de Mozilla https://developer.mozilla.org/en/Canvas_tutorial/Compositing

  • Los datos del adaptador RecycleView aparecen erróneos al desplazarse demasiado rápido
  • Dibujo de Android en superficie y lienzo
  • Android TextureView / Dibujo / Rendimiento de la pintura
  • Cómo dibujar figuras sin llenar en Android?
  • No se puede dibujar en un lienzo HTML5 con Phonegap 2.7
  • Comportamiento extraño al dibujar un anillo usando Path.arcTo () en Android
  • Android OpenGL ES - Cómo dibujar un polígono cóncavo lleno?
  • Android dibuja texto en rectángulo en el centro y recórtalo si es necesario
  • ¿Cómo dibujar una línea entre puntos y tirar de esos puntos?
  • El método getDrawingCache () de Android 2.1 View devuelve siempre null
  • Cambiar dinámicamente el color del divisor de barra de acción (android: bottom para ShapeDrawable generado por programa)?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.