Intereting Posts

Как реализовать шаблон «Загрузка изображений» (непрозрачность, экспозиция и насыщенность) из новых руководств по дизайну материалов

Кто-нибудь задумался о реализации шаблона « Загрузка изображений» из последнего руководства по дизайну материалов.

Рекомендуется, чтобы «иллюстрации и фотографии могли загружаться и переходить в три этапа с шагом в шахматном порядке». Это непрозрачность, экспозиция и насыщенность:

Введите описание изображения здесь

В настоящее время я использую Volley NetworkImageView (фактически это производный класс).

Я уверен, что это должен быть какой-то вариант ответа на этот вопрос . Я просто не знаю, какие классы / код использовать для кривых насыщения и анимации, которые описаны.

Solutions Collecting From Web of "Как реализовать шаблон «Загрузка изображений» (непрозрачность, экспозиция и насыщенность) из новых руководств по дизайну материалов"

Благодаря @mttmllns! Предыдущий ответ.

Поскольку предыдущий ответ показывает пример, написанный на C #, и мне было любопытно, я поместил его в java. Полный пример GitHub

В нем описывается трехэтапный процесс, в котором сочетание непрозрачности, контрастности, яркости и насыщенности используется совместно, чтобы помочь спасти наших бедных пользователей.

Подробное объяснение читайте в этой статье .

РЕДАКТИРОВАТЬ:

Смотрите, отличный ответ, предоставленный @DavidCrawford.

BTW: Я установил связанный GitHubProject для поддержки устройств с предварительным Lollipop. (Начиная с уровня API 11)

Код

AlphaSatColorMatrixEvaluator.java

 import android.animation.TypeEvaluator; import android.graphics.ColorMatrix; public class AlphaSatColorMatrixEvaluator implements TypeEvaluator { private ColorMatrix colorMatrix; float[] elements = new float[20]; public AlphaSatColorMatrixEvaluator() { colorMatrix = new ColorMatrix (); } public ColorMatrix getColorMatrix() { return colorMatrix; } @Override public Object evaluate(float fraction, Object startValue, Object endValue) { // There are 3 phases so we multiply fraction by that amount float phase = fraction * 3; // Compute the alpha change over period [0, 2] float alpha = Math.min(phase, 2f) / 2f; // elements [19] = (float)Math.round(alpha * 255); elements [18] = alpha; // We substract to make the picture look darker, it will automatically clamp // This is spread over period [0, 2.5] final int MaxBlacker = 100; float blackening = (float)Math.round((1 - Math.min(phase, 2.5f) / 2.5f) * MaxBlacker); elements [4] = elements [9] = elements [14] = -blackening; // Finally we desaturate over [0, 3], taken from ColorMatrix.SetSaturation float invSat = 1 - Math.max(0.2f, fraction); float R = 0.213f * invSat; float G = 0.715f * invSat; float B = 0.072f * invSat; elements[0] = R + fraction; elements[1] = G; elements[2] = B; elements[5] = R; elements[6] = G + fraction; elements[7] = B; elements[10] = R; elements[11] = G; elements[12] = B + fraction; colorMatrix.set(elements); return colorMatrix; } } 

Вот как вы можете настроить его:

 ImageView imageView = (ImageView)findViewById(R.id.imageView); final BitmapDrawable drawable = (BitmapDrawable) getResources().getDrawable(R.drawable.image); imageView.setImageDrawable(drawable); AlphaSatColorMatrixEvaluator evaluator = new AlphaSatColorMatrixEvaluator (); final ColorMatrixColorFilter filter = new ColorMatrixColorFilter(evaluator.getColorMatrix()); drawable.setColorFilter(filter); ObjectAnimator animator = ObjectAnimator.ofObject(filter, "colorMatrix", evaluator, evaluator.getColorMatrix()); animator.addUpdateListener( new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { drawable.setColorFilter (filter); } }); animator.setDuration(1500); animator.start(); 

И вот результат:

Введите описание изображения здесь

Обратите внимание, что этот ответ , как он есть, работает только для Lollipop. Причина этого заключается в том, что свойство colorMatrix недоступно для анимации в классе ColorMatrixColorFilter (он не предоставляет методы getColorMatrix и setColorMatrix). Чтобы увидеть это в действии, попробуйте код, в выводе logcat вы увидите предупреждающее сообщение, подобное этому:

Метод setColorMatrix () с типом класса android.graphics.ColorMatrix не найден в целевом классе класса android.graphics.ColorMatrixColorFilter

При этом мне удалось заставить это работать над более старыми версиями Android (pre-Lollipop), создав следующий класс (не лучшее имя, я знаю)

 private class AnimateColorMatrixColorFilter { private ColorMatrixColorFilter mFilter; private ColorMatrix mMatrix; public AnimateColorMatrixColorFilter(ColorMatrix matrix) { setColorMatrix(matrix); } public ColorMatrixColorFilter getColorFilter() { return mFilter; } public void setColorMatrix(ColorMatrix matrix) { mMatrix = matrix; mFilter = new ColorMatrixColorFilter(matrix); } public ColorMatrix getColorMatrix() { return mMatrix; } } 

Затем установочный код будет выглядеть примерно так: Обратите внимание, что у меня есть эта «настройка» в производном классе из ImageView, и поэтому я делаю это в методе overriden setImageBitmap.

 @Override public void setImageBitmap(Bitmap bm) { final Drawable drawable = new BitmapDrawable(getContext().getResources(), bm); setImageDrawable(drawable); AlphaSatColorMatrixEvaluator evaluator = new AlphaSatColorMatrixEvaluator(); final AnimateColorMatrixColorFilter filter = new AnimateColorMatrixColorFilter(evaluator.getColorMatrix()); drawable.setColorFilter(filter.getColorFilter()); ObjectAnimator animator = ObjectAnimator.ofObject(filter, "colorMatrix", evaluator, evaluator.getColorMatrix()); animator.addUpdateListener( new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { drawable.setColorFilter(filter.getColorFilter()); } }); animator.setDuration(1500); animator.start(); } 

Следуя превосходному ответу rnrneverdies , я хотел бы предложить небольшое исправление для этой анимационной логики.

Моя проблема с этой реализацией заключается в том, когда речь идет о png-изображениях с прозрачностью (например, круговые изображения или пользовательские формы). Для этих изображений цветовой фильтр сделает прозрачность изображения черным, а не просто прозрачным.

Проблема в этой строке:

 elements [19] = (float)Math.round(alpha * 255); 

Что здесь происходит, так это то, что цветовая матрица сообщает растровому изображению, что значение альфа каждого пикселя равно текущей фазе альфы. Это, очевидно, не идеально, поскольку пиксели, которые были уже прозрачными, потеряют свою прозрачность и станут черными.

Чтобы исправить это, вместо применения альфы «аддитивного» альфа-поля в цветовой матрице примените ее в поле «multipicative»:

 Rm | 0 | 0 | 0 | Ra 0 | Gm | 0 | 0 | Ga 0 | 0 | Bm | 0 | Ba 0 | 0 | 0 | Am | Aa Xm = multiplicative field Xa = additive field 

Поэтому вместо применения альфа-значения в поле « Aa » ( elements[19] ) примените его в поле « Am » ( elements[18] ) и используйте значение 0-1, а не значение 0-255:

 //elements [19] = (float)Math.round(alpha * 255); elements [18] = alpha; 

Теперь переход будет умножать исходное альфа-значение растрового изображения с альфа-фазой анимации и не заставлять альфа-значение, когда его не должно быть.

Надеюсь это поможет

Просто интересно было то же самое. Я нашел сообщение в блоге с подробным описанием того, как это сделать с примером, написанным на Xamarin:

http://blog.neteril.org/blog/2014/11/23/android-material-image-loading/

Суть в том, что кто-то пишет на Java: используйте ColorMatrix и ColorMatrixColorFilter .

В сообщении также упоминается важная оптимизация: использование скрытого API setColorMatrix () Lollipop для предотвращения оттока GC и GPU.

Вы уже видели его в каких-либо приложениях Google? Если вы в конечном итоге реализуете это, я бы хотел увидеть ваш источник.