是否有人考虑过使用Google最新的Material Design指南实施Loading images模式。
这是一种推荐的方式,插图和照片可能会在交错的持续时间内分三个阶段加载和转换#34;那些是不透明度,曝光度和饱和度:
我目前正在使用Volley NetworkImageView(实际上是一个派生类)。
我确定它必须是the answer to this question的某种变体。我不确定哪些类/代码可用于描述的饱和度和动画曲线。
答案 0 :(得分:10)
感谢@mttmllns!上一个答案。
由于上一个答案显示了一个用C#编写的示例,我很好奇,我把它移植到java。 Complete GitHub Example
它概述了一个3个步骤的过程,其中不透明度,对比度/亮度和饱和度的组合一起用于帮助挽救我们的不良用户视力。
有关详细说明,请阅读this article。
请参阅@DavidCrawford提供的优秀answer。
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();
答案 1 :(得分:8)
请注意,this answer目前仅适用于棒棒糖。原因是因为colorMatrix属性不可用于ColorMatrixColorFilter类的动画(它没有提供getColorMatrix和setColorMatrix方法)。要查看此操作,请尝试代码,在logcat输出中,您应该看到如下警告消息:
方法setColorMatrix(),在目标类类android.graphics.ColorMatrixColorFilter
上找不到类型类android.graphics.ColorMatrix话虽如此,通过创建以下类(不是最好的名字,我知道),我能够让它在旧的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的派生类中,所以我在覆盖方法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();
}
答案 2 :(得分:2)
关注rnrneverdies的优秀答案,我想为此动画逻辑提供一个小修补程序。
这个实现的问题在于具有透明度的png图像(例如,圆形图像或自定义形状)。对于这些图像,滤色器会将图像的透明度绘制为黑色,而不是将它们保持透明。
问题在于这一行:
elements [19] = (float)Math.round(alpha * 255);
这里发生的是颜色矩阵告诉位图每个像素的alpha值等于alpha的当前相位。这显然不是完美的,因为已经透明的像素将失去透明度并显示为黑色。
要解决此问题,请不要应用"添加剂"的alpha。颜色矩阵中的alpha字段,将其应用于"乘法"字段:
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
"上应用alpha值。字段(elements[19]
),将其应用于" Am
"字段(elements[18]
),并使用0-1值而不是0-255值:
//elements [19] = (float)Math.round(alpha * 255);
elements [18] = alpha;
现在转换会将位图的原始alpha值与动画的alpha阶段相乘,并且在不应该为某个时不强制使用alpha值。
希望这有帮助
答案 3 :(得分:1)
只是想知道同样的事情。我发现了一篇博文,详细介绍了如何使用Xamarin编写的示例:
http://blog.neteril.org/blog/2014/11/23/android-material-image-loading/
使用Java编写的人的要点:使用ColorMatrix和ColorMatrixColorFilter。
该帖子还提到了一项重要的优化:使用Lollipop隐藏setColorMatrix() API来避免GC和GPU流失。
您是否在任何Google应用中看到过它?如果你最终实现它,我很乐意看到你的来源。