Как применить цветной фильтр к представлению со всеми детьми
Как мне серым из вида, который содержит много разных элементов - 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);