Как применить цветной фильтр к представлению со всеми детьми

Как мне серым из вида, который содержит много разных элементов - ImageViews, TextViews, фоновое изображение. Нужно ли мне седировать каждую вещь индивидуально? Или есть способ применить один и тот же цветовой фильтр ко всем?

Ответы

Ответ 1

Если кто-то другой не имеет лучшего ответа, мой текущий метод выделяет каждый элемент отдельно.

PorterDuffColorFilter greyFilter = new PorterDuffColorFilter(Color.GRAY, PorterDuff.Mode.MULTIPLY);
myLayout.getBackground().setColorFilter(greyFilter);
myImageView.setColorFilter(greyFilter);
myTextView.setTextColor(0xff777777);

Для более или вложенных детей возможно, что цикл с instanceof будет подходящим, но мне он не нужен.

Изменить: этот фильтр на самом деле не серый, лучший фильтр здесь: Drawable = > полутоновой Который может использоваться таким же образом.

Ответ 2

Легко это сделать, определяя настраиваемую группу представлений следующим образом:

public class MyViewContainer extends XXXLayout {
    //XXLayout could be LinearLayout, RelativeLayout or others
    private Paint m_paint;

    //define constructors here and call _Init() at the end of constructor function

    private void
    _Init()
    {
        ColorMatrix cm = new ColorMatrix();
        cm.setSaturation(0);
        m_paint = new Paint();
        m_paint.setColorFilter(new ColorMatrixColorFilter(cm));
    }

    @Override protected void 
    dispatchDraw(Canvas canvas)
    {
        canvas.saveLayer(null, m_paint, Canvas.ALL_SAVE_FLAG);
        super.dispatchDraw(canvas);
        canvas.restore();
    }
}

Все представления детей MyViewContainer будут показаны серым цветом.:-)

Ответ 3

Ответ Сэма Лу - хороший старт, но у меня были проблемы с производительностью, и я решил переключиться на аппаратные уровни. С помощью аппаратных уровней вы можете сделать это следующим образом:

private final Paint grayscalePaint = new Paint();

ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);        
grayscalePaint.setColorFilter(new ColorMatrixColorFilter(cm));

public void setGrayedOut(boolean grayedOut) {       
    if (grayedOut) {
        setLayerType(View.LAYER_TYPE_HARDWARE, grayscalePaint);
    } else {
        setLayerType(View.LAYER_TYPE_NONE, null);       
    }       
}

Будьте осторожны, чтобы не выполнять слои в dispatchDraw(), так как это приведет к сбою приложения.

Ответ 4

Это полностью зависит от метода, который вы используете для "серого" элемента. Если вы делаете это, вызывая setEnabled(false) в родительском ViewGroup, по умолчанию флаги состояния (например, отключенные) не стекаются к дочерним представлениям. Однако есть два простых способа настроить это:

Один параметр - добавить атрибут android:duplicateParentState="true" к каждому дочернему виду в вашем XML. Это позволит детям получить свои флаги состояния от родителя. Это отразит все флаги ALL, включая нажатие, проверку и т.д., А не только.

Другим вариантом является создать пользовательский подкласс вашего ViewGroup и переопределить setEnabled(), чтобы вызвать все дочерние представления, т.е.

@Override
public void setEnabled(boolean enabled) {
    super.setEnabled(enabled);

    for(int i=0; i < getChildCount(); i++) {
        getChildAt(i).setEnabled(enabled);
    }
}

Ответ 5

Мне нравится делать вид, который перекрывает вид, который вы пытаетесь настроить, и установите его фон в прозрачный цвет. Затем вы можете включить и выключить оттенок, установив видимость просмотров

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ViewYouWantToTint
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <View
        android:id="@+id/disabled_tint_overlay"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/darkTint"
        android:visibility="invisible"/>

</FrameLayout>

Затем в вашем контроллере:

m_DisabledBlackTintOverlay = (View) view.findViewById(R.id.login_disabled_black_tint_overlay);

m_DisabledBlackTintOverlay.setVisibility(View.VISIBLE);