Comment mettre en œuvre le modèle "Chargement des images" (Opacité, Exposition et Saturation) des nouvelles directives de conception de matériaux de Google

Est-ce que quelqu'un a cherché à mettre en œuvre le modèle de Chargement des images à partir du dernier guide de conception de matériaux de Google.

C'est une façon recommandée que «les illustrations et les photographies peuvent se charger et se transmettre en trois phases à des durées décalées». Opacité, exposition et saturation:

  • MapFragment ou MapView getMap () renvoie null sur Lollipop
  • Comment inclure une configuration Proguard dans ma bibliothèque Android (AAR)
  • Fragment saveInstanceState devient nul après changement d'orientation
  • Streaming de vidéos en direct depuis la caméra Android vers le serveur
  • Android NSD ne découvre pas tous les services
  • Comment faire un sélecteur dans le studio android
  • Entrez la description de l'image ici

    J'utilise actuellement Volley NetworkImageView (en fait, une classe dérivée à partir de ceci).

    Je suis sûr que cela doit être une variante de la réponse à cette question . Je ne suis tout simplement pas sur les classes / codes à utiliser pour les courbes de saturation et d'animation décrites.

  • Comment obtenir le jour du mois?
  • Android VM se bloque sur le lancement de Mac
  • Pilote de périphérique USB pour HTC OneVX (Débogage USB)
  • Comment placer une icône dans le titre d'un dialogue personnalisé
  • Android: texte central dans EditText par programmation
  • Action Bar Fragment Activité
  • 4 Solutions collect form web for “Comment mettre en œuvre le modèle "Chargement des images" (Opacité, Exposition et Saturation) des nouvelles directives de conception de matériaux de Google”

    Merci à @mttmllns! Réponse précédente.

    Puisque la réponse précédente montre un exemple écrit en C # et j'ai été curieux, je l'ai porté à java. Exemple GitHub complet

    Il décrit un processus en 3 étapes où une combinaison d'opacité, de contraste / luminosité et de saturation est utilisée de concert pour aider à sauver notre vision des utilisateurs pauvres.

    Pour une explication détaillée, lisez cet article .

    MODIFIER:

    Voyez, l'excellente réponse fournie par @DavidCrawford.

    BTW: J'ai réparé le GitHubProject lié pour prendre en charge les périphériques pré-Lollipop. (Depuis API Niveau 11)

    Le code

    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; } } 

    Voici comment vous pouvez le configurer:

     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(); 

    Et voici le résultat:

    Entrez la description de l'image ici

    Veuillez noter que cette réponse ne fonctionne que pour Lollipop. La raison en est parce que la propriété ColorMatrix n'est pas disponible pour animer sur la classe ColorMatrixColorFilter (elle ne fournit pas les méthodes getColorMatrix et setColorMatrix). Pour voir cela en action, essayez le code, dans la sortie logcat vous devriez voir un message d'avertissement comme celui-ci:

    Méthode setColorMatrix () avec classe de type android.graphics.ColorMatrix introuvable sur la classe de classe cible android.graphics.ColorMatrixColorFilter

    Cela étant dit, j'ai pu travailler sur d'anciennes versions Android (pré-Lollipop) en créant la classe suivante (pas le meilleur nom, je sais)

     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; } } 

    Ensuite, le code d'installation ressemblerait à ce qui suit. Notez que j'ai cette "configuration" dans une classe dérivée à partir d'ImageView et donc je le fais dans la méthode 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(); } 

    Suite à l' excellente réponse de rnrneverdies , j'aimerais offrir un petit correctif à cette logique d'animation.

    Mon problème avec cette implémentation est celui des images png avec transparence (par exemple, des images circulaires ou des formes personnalisées). Pour ces images, le filtre de couleur dessine la transparence de l'image en noir, plutôt que de les laisser transparentes.

    Le problème est avec cette ligne:

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

    Ce qui se passe ici, c'est que la matrice de couleurs indique au bitmap que la valeur alpha de chaque pixel est égale à la phase actuelle de l'alpha. Ce n'est évidemment pas parfait, car les pixels déjà transparents perdront leur transparence et apparaîtront comme des noirs.

    Pour résoudre ce problème, au lieu d'appliquer l'alpha du champ alpha "additif" dans la matrice de couleurs, appliquez-le sur le champ "multiplicatif":

     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 

    Donc, au lieu d'appliquer la valeur alpha sur le champ " Aa " ( elements[19] ), appliquez-le sur le champ " Am " ( elements[18] ) et utilisez la valeur 0-1 plutôt que la valeur 0-255:

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

    Maintenant, la transition multipliera la valeur alpha originale du bitmap par la phase alpha de l'animation et ne forcera pas une valeur alpha s'il n'y en a pas.

    J'espère que cela t'aides

    Je me demandais tout de même. J'ai trouvé un article de blog détaillant comment y faire un exemple écrit dans Xamarin:

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

    L'essentiel pour quelqu'un qui écrit en Java: utilisez ColorMatrix et ColorMatrixColorFilter .

    Le post mentionne également une optimisation importante: en utilisant l'API cachée Lollipop setColorMatrix () pour éviter la rotation du GC et du GPU.

    L'avez-vous déjà vu dans toutes les applications Google? Si vous finissez par l'implémenter, j'aimerais voir votre source.

    coAndroid est un fan Android de Google, tout sur les téléphones Android, Android Wear, Android Dev et Android Games Apps.