From 8cfe1d3584662e63a4b60f95fc8d04138ddc6f71 Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Tue, 21 Mar 2017 12:49:22 +1100 Subject: [PATCH] Correctly populate FeatureImage with `app.featureGraphic`. Fall back to extracting the colour from the apps icon if that is all that is available. --- .../java/org/fdroid/fdroid/AppDetails2.java | 41 +------------ .../fdroid/views/apps/FeatureImage.java | 57 +++++++++++++++++++ .../views/categories/AppCardController.java | 22 +++++-- app/src/main/res/layout/app_card_featured.xml | 2 + 4 files changed, 80 insertions(+), 42 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/AppDetails2.java b/app/src/main/java/org/fdroid/fdroid/AppDetails2.java index 701bd932e..55c2ac73f 100644 --- a/app/src/main/java/org/fdroid/fdroid/AppDetails2.java +++ b/app/src/main/java/org/fdroid/fdroid/AppDetails2.java @@ -9,8 +9,6 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; -import android.graphics.Bitmap; -import android.graphics.Color; import android.net.Uri; import android.os.Bundle; import android.support.design.widget.AppBarLayout; @@ -18,7 +16,6 @@ import android.support.design.widget.CoordinatorLayout; import android.support.v4.content.LocalBroadcastManager; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; -import android.support.v7.graphics.Palette; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; @@ -26,13 +23,10 @@ import android.text.TextUtils; import android.util.Log; import android.view.Menu; import android.view.MenuItem; -import android.view.View; import android.widget.Toast; import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; -import com.nostra13.universalimageloader.core.assist.FailReason; -import com.nostra13.universalimageloader.core.listener.ImageLoadingListener; import org.fdroid.fdroid.data.Apk; import org.fdroid.fdroid.data.ApkProvider; @@ -136,39 +130,10 @@ public class AppDetails2 extends AppCompatActivity implements ShareChooserDialog recyclerView.setAdapter(adapter); // Load the feature graphic, if present + final FeatureImage featureImage = (FeatureImage) findViewById(R.id.feature_graphic); + DisplayImageOptions displayImageOptions = Utils.getImageLoadingOptions().build(); String featureGraphicUrl = app.getFeatureGraphicUrl(this); - if (!TextUtils.isEmpty(featureGraphicUrl)) { - final FeatureImage featureImage = (FeatureImage) findViewById(R.id.feature_graphic); - DisplayImageOptions displayImageOptions = Utils.getImageLoadingOptions().build(); - ImageLoader.getInstance().loadImage(featureGraphicUrl, displayImageOptions, new ImageLoadingListener() { - @Override - public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { - if (featureImage != null) { - new Palette.Builder(loadedImage).generate(new Palette.PaletteAsyncListener() { - @Override - public void onGenerated(Palette palette) { - featureImage.setColour(palette.getDominantColor(Color.LTGRAY)); - } - }); - } - } - - @Override - public void onLoadingStarted(String imageUri, View view) { - - } - - @Override - public void onLoadingFailed(String imageUri, View view, FailReason failReason) { - - } - - @Override - public void onLoadingCancelled(String imageUri, View view) { - - } - }); - } + featureImage.loadImageAndDisplay(ImageLoader.getInstance(), displayImageOptions, featureGraphicUrl, app.iconUrl); } private String getPackageNameFromIntent(Intent intent) { diff --git a/app/src/main/java/org/fdroid/fdroid/views/apps/FeatureImage.java b/app/src/main/java/org/fdroid/fdroid/views/apps/FeatureImage.java index 08dd3cdcd..7b728e3b4 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/apps/FeatureImage.java +++ b/app/src/main/java/org/fdroid/fdroid/views/apps/FeatureImage.java @@ -3,6 +3,7 @@ package org.fdroid.fdroid.views.apps; import android.animation.ValueAnimator; import android.annotation.TargetApi; import android.content.Context; +import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; @@ -11,10 +12,18 @@ import android.graphics.Point; import android.graphics.PorterDuff; import android.os.Build; import android.support.annotation.ColorInt; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.graphics.Palette; import android.support.v7.widget.AppCompatImageView; +import android.text.TextUtils; import android.util.AttributeSet; +import android.view.View; + +import com.nostra13.universalimageloader.core.DisplayImageOptions; +import com.nostra13.universalimageloader.core.ImageLoader; +import com.nostra13.universalimageloader.core.assist.FailReason; +import com.nostra13.universalimageloader.core.listener.ImageLoadingListener; import java.util.Random; @@ -225,4 +234,52 @@ public class FeatureImage extends AppCompatImageView { return path; } + + public void loadImageAndDisplay(@NonNull ImageLoader loader, @NonNull DisplayImageOptions imageOptions, @Nullable String featureImageToShow, @Nullable String fallbackImageToExtractColours) { + if (!TextUtils.isEmpty(featureImageToShow)) { + loadImageAndDisplay(loader, imageOptions, featureImageToShow); + } else if (!TextUtils.isEmpty(fallbackImageToExtractColours)) { + loadImageAndExtractColour(loader, imageOptions, fallbackImageToExtractColours); + } + } + + private void loadImageAndExtractColour(@NonNull ImageLoader loader, @NonNull DisplayImageOptions imageOptions, String url) { + loader.loadImage(url, imageOptions, new ImageLoadingAdapter() { + @Override + public void onLoadingComplete(String imageUri, View view, final Bitmap loadedImage) { + if (loadedImage != null) { + new Palette.Builder(loadedImage).generate(new Palette.PaletteAsyncListener() { + @Override + public void onGenerated(Palette palette) { + if (palette != null) { + setColour(palette.getDominantColor(Color.LTGRAY)); + } + } + }); + } + } + }); + } + + public void loadImageAndDisplay(@NonNull ImageLoader loader, @NonNull DisplayImageOptions imageOptions, String url) { + loader.loadImage(url, imageOptions, new ImageLoadingAdapter() { + @Override + public void onLoadingComplete(String imageUri, View view, final Bitmap loadedImage) { + if (loadedImage != null) { + setImageBitmap(loadedImage); + } + } + }); + } + + private abstract static class ImageLoadingAdapter implements ImageLoadingListener { + @Override + public void onLoadingStarted(String imageUri, View view) { } + + @Override + public void onLoadingFailed(String imageUri, View view, FailReason failReason) { } + + @Override + public void onLoadingCancelled(String imageUri, View view) { } + } } diff --git a/app/src/main/java/org/fdroid/fdroid/views/categories/AppCardController.java b/app/src/main/java/org/fdroid/fdroid/views/categories/AppCardController.java index ea6e8c67f..a979ae3f6 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/categories/AppCardController.java +++ b/app/src/main/java/org/fdroid/fdroid/views/categories/AppCardController.java @@ -13,6 +13,7 @@ import android.support.v4.app.ActivityOptionsCompat; import android.support.v4.util.Pair; import android.support.v7.graphics.Palette; import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; import android.view.View; import android.widget.ImageView; import android.widget.TextView; @@ -110,12 +111,23 @@ public class AppCardController extends RecyclerView.ViewHolder implements ImageL } } + ImageLoader.getInstance().displayImage(app.iconUrl, icon, displayImageOptions, this); + if (featuredImage != null) { featuredImage.setColour(0); featuredImage.setImageDrawable(null); - } - ImageLoader.getInstance().displayImage(app.iconUrl, icon, displayImageOptions, this); + // Note: We could call the convenience function loadImageAndDisplay(ImageLoader, DisplayImageOptions, String, String) + // which includes a fallback for when currentApp.featureGraphic is empty. However we need + // to take care of also loading the icon (regardless of whether there is a featureGraphic + // or not for this app) so that we can display the icon to the user. We will use the + // load complete listener for the icon to decide whether we need to extract the colour + // from that icon and assign to the `FeatureImage` (or whether we should wait for the + // feature image to be loaded). + if (!TextUtils.isEmpty(app.featureGraphic)) { + featuredImage.loadImageAndDisplay(ImageLoader.getInstance(), displayImageOptions, app.featureGraphic); + } + } } /** @@ -145,12 +157,14 @@ public class AppCardController extends RecyclerView.ViewHolder implements ImageL // Icon loader callbacks // // Most are unused, the main goal is to specify a background colour for the featured image if - // no featured image is specified in the apps metadata. + // no featured image is specified in the apps metadata. If an image is specified, then it will + // get loaded using the `FeatureImage.loadImageAndDisplay()` method and so we don't need to do + // anything special here. // ============================================================================================= @Override public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { - if (featuredImage != null && loadedImage != null) { + if (currentApp != null && TextUtils.isEmpty(currentApp.featureGraphic) && featuredImage != null && loadedImage != null) { new Palette.Builder(loadedImage).generate(new Palette.PaletteAsyncListener() { @Override public void onGenerated(Palette palette) { diff --git a/app/src/main/res/layout/app_card_featured.xml b/app/src/main/res/layout/app_card_featured.xml index d74565aac..a5d7b47e1 100644 --- a/app/src/main/res/layout/app_card_featured.xml +++ b/app/src/main/res/layout/app_card_featured.xml @@ -12,6 +12,8 @@ android:layout_width="0dp" android:layout_height="120dp" tools:src="@color/fdroid_green" + android:scaleType="centerCrop" + android:fitsSystemWindows="true" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" />