如何从Google的新材料设计指南中实现"加载图像"图案(不透明度,曝光度和饱和度)

Dav*_*ord 17 android material-design

有没有人考虑过从Google最新的Material Design指南中实现加载图像模式.

这是一种推荐的方式,"插图和照片可以在交错的持续时间内分三个阶段加载和过渡".那些是不透明度,曝光度和饱和度:

在此输入图像描述

我目前正在使用Volley NetworkImageView(实际上是一个派生类).

我敢肯定它必须是这个问题答案的一些变体.我只是不确定哪些类/代码用于描述的饱和度和动画曲线.

rnr*_*ies 10

感谢@mttmllns!上一个答案.

由于上一个答案显示了一个用C#编写的例子,我很好奇,我把它移植到java.完成GitHub示例

它概述了一个3个步骤的过程,其中不透明度,对比度/亮度和饱和度的组合被用于协调以帮助挽救我们的不良用户视力.

有关详细说明,请阅读本文.

编辑:

请参阅@DavidCrawford提供的优秀答案.

顺便说一句:我修复了链接的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;
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是如何设置它:

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();
Run Code Online (Sandbox Code Playgroud)

这是结果:

在此输入图像描述


Dav*_*ord 8

请注意,这个答案,仅适用于Lollipop.原因是因为colorMatrix属性不可用于ColorMatrixColorFilter类的动画(它不提供getColorMatrix和setColorMatrix方法).要查看此操作,请尝试使用logcat输出中的代码,您应该看到如下警告消息:

在目标类类android.graphics.ColorMatrixColorFilter上找不到类型类android.graphics.ColorMatrix的方法setColorMatrix()

话虽这么说,我能够通过创建以下类(不是最好的名字,我知道)让这个在旧的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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,设置代码将如下所示.请注意,我在ImageView的派生类中有这个"设置",所以我在覆盖方法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();
}
Run Code Online (Sandbox Code Playgroud)