Я создаю различные пользовательские представления с двумя разными цветами. Согласно моим функциям приложения пользователь будет перетаскивать эти объекты на экране, когда перетаскивание объектов будет перекрывать друг друга. Я хочу дифференцировать перекрываемую область, как установить комбинированный цвет для перекрываемой области. Посмотрите на изображение ниже. Здесь я использую холст для создания этих пользовательских представлений. Два круга – это два разных вида.
EDIT: Если я использую opacity 128, я могу видеть цвет фона, но мне нужен цвет комбинации совпадающих объектов.
Смешивание цветов, которое вы ищете, иногда называют интуитивно понятным смешиванием цветов или цветовой системой RYB :
RYB :
Лицензия CC
В цитате из этой статьи Натана Госсетта и Баокуана Чена по алгоритмам интуитивного смешения цветов обобщается, как работает интуитивно понятная система окраски:
«В этой модели красные, желтые и синие используются в качестве чистых основных цветов. Красное и желтое смешивание для формирования оранжевого, желтого и синего смесей с образованием зеленого, синего и красного смешивания для формирования фиолетового […]. Цвета, которые нетренированный зритель ожидал бы получить с помощью детской краски […]. Кроме того, многие люди не думают о Белом как о смеси всех цветов, а вместо этого о том, как отсутствие цвета (пустой холст). Предположение заключалось бы в том, что смешивание многих цветов вместе приведет к мутному темно-коричневому цвету ».
RYB не реализован в режимах смешивания Android и не может быть имитирован путем смешивания альфа / разных режимов смешивания.
Большинство приложений компьютерной графики используют цветовые пространства RGB или CMYK :
CMYK :
Лицензия CC
CMY основан на субтрактивном цвете. Субтрактивное смешивание цветов означает, что, начиная с белого цвета, при добавлении цвета результат становится темнее. CMYK используется для смешивания цветов в изображениях, предназначенных для печати, например, Photoshop и Illustrator.
RGB :
Лицензия CC
RGB основан на добавочном цвете. Цвета на экране компьютера создаются с помощью света с использованием метода добавочного цвета. Смешивание добавочного цвета начинается с черного цвета и при добавлении большего количества цвета результат становится светлее и заканчивается белым.
На этом сайте более подробно рассматриваются CMYK и RGB.
Ни RGB, ни CMYK не смешивают синие и желтые зеленые или, вообще говоря, интуитивные цветовые смеси. Для внедрения цветовой системы RYB на Android было бы очень сложно. В статье Натана Госсетта и Баокуана Чена, приведенных выше, предлагается решение с алгоритмом, реализованным на C в самом конце статьи. Этот алгоритм может быть реализован в пользовательской смеси на Android. Drawable.setColorFilter()
использует PorterDuffColorfilter
который расширяет ColorFilter
. Подклассификация ColorFilter
как обсуждалось в этом вопросе SO, должна быть выполнена в собственном коде с использованием NDK.
Смешивание CMYK
Если вы заинтересованы в использовании смешивания цветов CMYK в качестве обходного пути, я включил базовый пример того, как это можно сделать ниже. В этом примере круг с циановым цветом и круг желтого цвета будут смешаны для получения зеленого пересечения.
Начиная с этих .png файлов изображений, созданных в Adobe Illustrator:
С шестнадцатеричным значением цвета 0x00ffff (голубой) и 0xffff00 (желтый).
Добавьте их в свою папку с именами cyancircle.png и yellowcircle.png.
Настройте свой макет 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); } }
Вывод:
Ограничение этого метода заключается в том, что альфа альфа-формы должна быть установлена равной 50% («88» в «0x88ffff00»). Для желтого это работает разумно, но для других цветов альфа-эффект может быть неприемлем (цвет может выглядеть другим цветом, например, красный становится розовым с низкими значениями альфа на белом фоне). Какой режим смешивания в конечном счете приемлем для вас, зависит от набора цветов, которые вы собираетесь использовать, и предпримет некоторые эксперименты. Также обратите внимание, что цвет фона может влиять на цвета кругов в режиме наложения. В этом примере фон установлен на белый.
Я сделал еще один пример для 6 объектов.
Ключевые моменты:
Метод onDraw не будет переопределяться для представлений объектов, а фон также будет установлен на прозрачность
setBackgroundColor (Color.TRANSPARENT);
Но метод onDraw будет переименован в onDrawEx, который вызывается из Overlay View.
Public void onDrawEx (холст холста) {
Наложение будет передавать пользовательский холст для рисования. Перед тем, как перейти к просмотру объекта, он сделает необходимый перевод.
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 (новый 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)); }
Здесь я изменил для поддержки версии 8
использование
mPaint.setXfermode(new PixelXorXfermode(0x00000000));
для
mPaint.setXfermode(new PorterDuffXfermode(Mode.ADD));
Я использовал параметр макета для перевода.
Самое простое решение, о котором я могу думать, это просто использовать альфа-канал, установив каждый на 0,5 прозрачности, либо в код, либо в xml. Затем цвета должны исчезать друг в друга, когда они перекрываются. Это означает, что цвета в неперекрывающихся разделах будут немного поблекшими, и в зависимости от того, какой фон у вас за фигурами, может показаться не очень хорошим, чтобы они были абсолютно прозрачными.
Я создал образец 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; }
Я думаю, вы можете смотреть в режиме наложения. Android позволит вам сделать это, просто взгляните на эту первую ссылку. Композитные операции в Android Canvas
Вот все варианты компоновки http://developer.android.com/reference/android/graphics/PorterDuffXfermode.html
И их объяснения из Mozilla https://developer.mozilla.org/en/Canvas_tutorial/Compositing
Вы можете воспользоваться этим –
http://www.learnopengles.com/android-lesson-five-an-introduction-to-blending/
а также