wake-up-neo.net

Mit Glide Bitmap in ImageView laden

Wie kann ich die Glide-Bibliothek verwenden, um Bitmap in mein ImageView zu laden? Ich möchte ein benutzerdefiniertes image mit Text erstellen und es mit Glide in das Imageview laden.

Dies ist meine Methode zum Erstellen von benutzerdefinierten Bitmaps mit Text

public Bitmap imageWithText(String text) {
    TextView tv = new TextView(context);
    tv.setText(text);
    tv.setTextColor(Color.WHITE);
    tv.setBackgroundColor(Color.BLACK);
    tv.setTypeface(null, Typeface.BOLD);
    tv.setGravity(Gravity.CENTER);
    tv.setTextSize(20);
    tv.setPadding(0, 25, 0, 0);
    Bitmap testB = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(testB);
    tv.layout(0, 0, 100, 100);
    tv.draw(c);
    return testB;
}

Aber wenn ich versuche, dieses Bitmap mit Glide zu laden, bekomme ich einen Fehler

Glide.with(getContext()).load(imageWithText("Random text")).into(holder.imgPhoto);
12
user3296088

@rookiedev ist richtig, es gibt keine load(Bitmap) in Glide , aus einem Grund: Die Anschaffung einer Bitmap nimmt normalerweise Zeit in Anspruch und blockiert manchmal E/A. Daher ist es nicht empfehlenswert, imageWithText im UI-Thread aufzurufen. Update: Davon abgesehen, schlug ich diese Funktion vor einiger Zeit vor; und während die Hacks einfacher zu machen sind, finden Sie unten den "Glide Way", den ich sehr empfehlen kann.

Glide wurde entwickelt, um flexibel zu sein, und dieses Problem demonstriert diese Eigenschaft sehr gut. Die folgende Implementierung mag lang erscheinen, aber alle Stücke haben ihren Existenzgrund. Angesichts des Leistungsgewinns ist diese Menge an Code, die Ihren Generator in die Welt von Glide einfügt, nicht viel. Ich habe versucht, es kurz zu formatieren, irrelevante Teile kollabieren zu lassen und statische Importe zu verwenden, um kürzer zu sein (siehe das Ende für Importe).

Der Code enthält auch eine programmgesteuert erstellte Benutzeroberfläche, sodass Sie einfach den folgenden Code in GlideGeneratedImageListFragment.Java kopieren und einfügen und ausführen können. Die einzige externe Abhängigkeit ist RecyclerView von support lib.

class GeneratingAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    // See https://docs.google.com/drawings/d/1KyOJkNd5Dlm8_awZpftzW7KtqgNR6GURvuF6RfB210g/edit?usp=sharing
    //                                  ModelType/A,    DataType/T,     ResourceType/Z, TranscodeType/R
    private final GenericRequestBuilder<GenerateParams, GenerateParams, Bitmap,         GlideDrawable> generator;

    public GeneratingAdapter(final Context context) {
        generator = Glide // this part should be cleaner in Glide 4.0, but that's not released yet
        .with(context)
        .using(new GenerateParamsPassthroughModelLoader(), GenerateParams.class)          // custom class
        .from(GenerateParams.class)
        .as(Bitmap.class)
        .transcode(new BitmapToGlideDrawableTranscoder(context), GlideDrawable.class)     // builtin
        .decoder(new GenerateParamsBitmapResourceDecoder(context))                        // custom class
        .encoder(new BitmapEncoder(Bitmap.CompressFormat.PNG, 0/*ignored for lossless*/)) // builtin
        .cacheDecoder(new FileToStreamDecoder<Bitmap>(new StreamBitmapDecoder(context)))  // builtin
        //.placeholder(new ColorDrawable(Color.YELLOW)) // you can pre-set placeholder and error
        .error(new ColorDrawable(Color.RED))            // so it's easier when binding
        //.diskCacheStrategy(DiskCacheStrategy.NONE)    // only for debugging to always regenerate
        //.skipMemoryCache(true)                        // only for debugging to always regenerate
        ;
    }
    @Override public int getItemCount() { return 1000; }

    private final float[] colorCache = new float[] {0, 1.0f, 0.5f};
    private final float[] bgCache = new float[] {0, 0.5f, 1.0f};
    @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        colorCache[0] = bgCache[0] = (position * 15) % 360; // just to have a fancy example :)
        GenerateParams params = new GenerateParams(
                // omit position to see Glide caching in action (every 24th item / 12th row is the same)
                "Android text"/* + " #" + position*/,
                Color.HSVToColor(colorCache),
                Color.HSVToColor(bgCache)
        );
        generator/*.clone() in case you see weird behavior*/.load(params).into((ImageView)holder.itemView);
    }

    @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        int height = parent.getContext().getResources().getDisplayMetrics().heightPixels / 3;
        ImageView view = new ImageView(parent.getContext());
        view.setLayoutParams(new RecyclerView.LayoutParams(MATCH_PARENT, height));
        view.setScaleType(ImageView.ScaleType.FIT_CENTER);
        return new RecyclerView.ViewHolder(view) {}; // anon class for brevity
    }
}

public class GlideGeneratedImageListFragment extends Fragment {
    @Override public @Nullable View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        RecyclerView view = new RecyclerView(container.getContext());
        view.setLayoutParams(new MarginLayoutParams(MATCH_PARENT, MATCH_PARENT));
        view.setLayoutManager(new GridLayoutManager(container.getContext(), 2 /*columns*/));
        view.setAdapter(new GeneratingAdapter(view.getContext()));
        return view;
    }
}

/** Extracted params from imageWithText, but left some hardcoded values like 20sp/bold/center in {@link Generators}. */
class GenerateParams {
    final String text;
    final int color;
    final int background;

    public GenerateParams(String text, int color, int bg) {
        this.text = text;
        this.color = color;
        this.background = bg;
    }

    public String getId() {
        // TODO make sure it's unique for every possible instance of GenerateParams
        // because it will affect how the resulting bitmap is cached
        // the below is correct correct for the current fields, if those change this has to change
        return String.format(Locale.ROOT, "%s-%08x-%08x", text, color, background);
    }
}

/** Boilerplate because of the degeneration in ModelType == DataType, but important for caching.
 *  @see GeneratingAdapter#generator */
class GenerateParamsPassthroughModelLoader implements ModelLoader<GenerateParams, GenerateParams> {
    @Override public DataFetcher<GenerateParams> getResourceFetcher(final GenerateParams model, int width, int height) {
        return new DataFetcher<GenerateParams>() {
            @Override public GenerateParams loadData(Priority priority) throws Exception { return model; }
            @Override public void cleanup() { }
            @Override public String getId() { return model.getId(); }
            @Override public void cancel() { }
        };
    }
}

/** Handles pooling to reduce/prevent GC lagging from too many {@link Bitmap#createBitmap}s */
class GenerateParamsBitmapResourceDecoder implements ResourceDecoder<GenerateParams, Bitmap> {
    private final Context context;
    public GenerateParamsBitmapResourceDecoder(Context context) { this.context = context; }
    @Override public Resource<Bitmap> decode(GenerateParams source, int width, int height) throws IOException {
        BitmapPool pool = Glide.get(context).getBitmapPool();
        Bitmap bitmap = pool.getDirty(width, height, Bitmap.Config.ARGB_8888);
        if (bitmap == null) {
            bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        }
        Generators.imageWithTextNoLayout(context, bitmap, source);
        return BitmapResource.obtain(bitmap, pool);
    }
    @Override public String getId() {
        // be careful if you change the Generator implementation you have to change this
        // otherwise the users may see a cached image; or clear cache on app update
        return "com.example.MyImageGenerator";
    }
}

class Generators {
    /** OP's original implementation fixed for real centering */
    public static Bitmap imageWithText(Context context, Bitmap bitmap, GenerateParams params) {
        TextView view = new TextView(context);
        view.setText(params.text);
        view.setTextColor(params.color);
        view.setBackgroundColor(params.background);
        view.setTypeface(null, Typeface.BOLD);
        view.setGravity(Gravity.CENTER);
        view.setTextSize(20 /*sp*/);
        Canvas canvas = new Canvas(bitmap);
        view.measure(makeMeasureSpec(canvas.getWidth(), EXACTLY), makeMeasureSpec(canvas.getHeight(), EXACTLY));
        view.layout(0, 0, canvas.getWidth(), canvas.getHeight());
        view.draw(canvas);
        return bitmap;
    }

    /** Generate centered text without creating a View, more lightweight.
     * Consider https://stackoverflow.com/a/8369690/253468 for multiline support. */
    public static Bitmap imageWithTextNoLayout(Context context, Bitmap bitmap, GenerateParams params) {
        Paint paint = new Paint();
        Paint.setColor(params.color);
        Paint.setTextAlign(Paint.Align.CENTER); // text's anchor for the x given in drawText
        Paint.setTextSize(applyDimension(COMPLEX_UNIT_SP, 20, context.getResources().getDisplayMetrics()));
        Paint.setTypeface(Typeface.DEFAULT_BOLD);

        Canvas canvas = new Canvas(bitmap);
        canvas.drawColor(params.background);
        canvas.drawText(params.text, canvas.getWidth() / 2, canvas.getHeight() / 2, Paint);
        return bitmap;
    }
}

// Here are the imports in case you need it;
// didn't want to put it in the beginning to keep the relevant code first.

import Java.io.IOException;
import Java.util.Locale;

import Android.content.Context;
import Android.graphics.*;
import Android.graphics.drawable.ColorDrawable;
import Android.os.Bundle;
import Android.support.annotation.Nullable;
import Android.support.v4.app.Fragment;
import Android.support.v7.widget.*;
import Android.view.*;
import Android.view.ViewGroup.MarginLayoutParams;
import Android.widget.*;

import static Android.util.TypedValue.*;
import static Android.view.View.MeasureSpec.*;
import static Android.view.ViewGroup.LayoutParams.*;

import com.bumptech.glide.*;
import com.bumptech.glide.load.ResourceDecoder;
import com.bumptech.glide.load.data.DataFetcher;
import com.bumptech.glide.load.engine.Resource;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.model.ModelLoader;
import com.bumptech.glide.load.resource.bitmap.*;
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
import com.bumptech.glide.load.resource.file.FileToStreamDecoder;
import com.bumptech.glide.load.resource.transcode.BitmapToGlideDrawableTranscoder;

So sieht es aus (echtes Scrollen ist viel ruhiger, GIF ist wirklich niedriger FPS):

enter image description here

Beachten Sie, wie die ersten Elemente geladen werden und der Rest allmählich geladen wird. Es dauert zwar ein wenig, dass der Speichercache und -pool aufgewärmt wird, Sie können jedoch einen Preloader verwenden, wenn Sie eine noch glattere Anzeige wünschen. Nachdem es aufgewärmt ist, rollt es schön. Die Schaltfläche "Löschen" in der Aktionsleiste ruft Glide.clearDiskCache() und Glide.clearMemory() auf, damit die Elemente erneut regeneriert werden.

22
TWiStErRob

Ich kenne die Leistung nicht, aber Sie können dies versuchen:

Zuerst wandeln Sie Ihre Bitmap als Byte [] - Array um:

private byte[] bitmapToByte(Bitmap bitmap){
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
    byte[] byteArray = stream.toByteArray();
    return byteArray;
}

Dann gleiten Sie auf diese Weise:

Glide.with(holder.imagePhoto.getContext()).load(bitmapToByte(yourBitmap)).asBitmap().override(300, 300).fitCenter().into(holder.imagePhoto);

In Ihrem Fall:

Glide.with(holder.imagePhoto.getContext()).load(bitmapToByte(yourBitmap)).asBitmap().into(holder.imagePhoto); //>>not tested
8

Nach der Dokumentation glaube ich nicht, dass die Methode load () eine Bitmap als Parameter verwenden kann. Die Bildquelle (d. H. Der Parameter) könnte eine URL, eine anzeigbare Ressource und eine Datei sein.

Wenn Sie jedoch eine Bitmap in eine ImageView laden möchten, müssen Sie die Glide-Bibliothek nicht verwenden. Verwenden Sie einfach die unten stehende Anweisung

holder.imgPhoto.setImageBitmap(imageWithText("Random text"));
1
rookiedev

Sie können versuchen, .__ Der folgende Code fügt ImageLayout und TextView zu FrameLayout hinzu:

FrameLayout frameLayout = new FrameLayout(mContext);
            TextView textView = new TextView(mContext);
            textView.setText("+" + (listImage.size() - countImage));
            textView.setBackground(
                    mContext.getResources().getDrawable(R.drawable.bg_border_tv));
            textView.setTextColor(Color.parseColor("#ffffffff"));
            textView.setGravity(Gravity.CENTER);
            textView.setTextSize(18);
            Glide.with(mContext)
                    .load(listImage.get(i))
                    .apply(new RequestOptions().override(size, size)
                            .transform(new RoundedCorners(20)))
                    .into(imageView);
            frameLayout.addView(imageView);
            frameLayout.addView(textView);
            holder.mItemListLnListImage.addView(frameLayout);

Das Ergebnis sieht wie folgt aus:  enter image description here

0
Doan Bui