利用Glide加载位图到ImageView的 [英] Using Glide to load bitmap into ImageView

查看:216
本文介绍了利用Glide加载位图到ImageView的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我该如何使用滑翔库加载位图到我的ImageView? 我想创建一个自定义文本 图片,并使用滑翔加载到ImageView的。

这是我的方法来创建自定义位图文本

 公共位图imageWithText(字符串文本){
    TextView的电视=新的TextView(上下文);
    tv.setText(文本);
    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);
    位图TESTB = Bitmap.createBitmap(100,100,Bitmap.Config.ARGB_8888);
    帆布C =新的Canvas(TESTB);
    tv.layout(0,0,100,100);
    tv.draw(C);
    返回TESTB;
}
 

但是,当我尝试使用滑翔我收到提示加载该位图

  Glide.with(的getContext())负载(imageWithText(任意文本))到(holder.imgPhoto)。
 

解决方案

@rookiedev是正确的,没有负载(位图)在滑翔,是有原因的:获得位图通常需要的时间,有时甚至阻塞I / O。因此,这不是很好的做法,叫 imageWithText 在UI线程上。 更新:话虽这么说,我就提出此功能而回;和而黑客更容易做到,你可以找到下面的滑翔路,这是我极力推荐。

滑翔的设计是灵活的,但此问题表明性状非常好。下面的实现可能看起来很长,但所有的作品都有其存在的理由。由于性能提升,这一数额code,以适应您的发电机到滑翔的世界并不多。我试图格式化要短,倒塌无关的部分,并使用静态进口短(参见年底进口)。

在code还包括编程生成的界面,因此你可以复制粘贴所有低于code到 GlideGeneratedImageListFragment.java 并运行它;唯一的对外依存度是支持LIB的 RecyclerView

 类GeneratingAdapter扩展RecyclerView.Adapter< RecyclerView.ViewHolder> {
    //见https://docs.google.com/drawings/d/1KyOJkNd5Dlm8_awZpftzW7KtqgNR6GURvuF6RfB210g/edit?usp=sharing
    // ModelType / A,数据类型/ T,的ResourceType / Z,跨codeTYPE / R
    私人最终GenericRequestBuilder< GenerateParams,GenerateParams,位图,GlideDrawable>发电机;

    公共GeneratingAdapter(最终上下文的背景下){
        发电机=滑翔//这部分应该是在滑翔4.0清洁剂,但是这尚未发布
        。随着(上下文)
        。采用(新GenerateParamsPassthroughModelLoader(),GenerateParams.class)//自定义类
        。从(GenerateParams.class)
        。至于(Bitmap.class)
        .trans code(新BitmapToGlideDrawableTrans codeR(上下文),GlideDrawable.class)//内置
        .DE codeR(新GenerateParamsBitma presourceDe codeR(上下文))//自定义类
        .EN codeR(新BitmapEn codeR(Bitmap.Com pressFormat.PNG,0 / *忽略无损* /))//内置
        .cacheDe codeR(新FileToStreamDe $ C $为CR位图>(新StreamBitmapDe codeR(上下文)))//内置
        //.placeholder(new ColorDrawable(Color.YELLOW))//你可以pre-设置占位符和错误
        .error(新ColorDrawable(Color.RED))//所以它绑定时更容易
        //.di​​skCacheStrategy(DiskCacheStrategy.NONE)//只用于调试总是再生
        //.skipMemoryCache(true)//只用于调试总是再生
        ;
    }
    @覆盖公众诠释getItemCount(){返回1000; }

    私人最终浮动[] colorCache =新的浮动[] {0,1.0F,0.5F};
    私人最终浮动[] bgCache =新的浮动[] {0,0.5F,1.0F};
    @覆盖公共无效onBindViewHolder(RecyclerView.ViewHolder持有人,INT位置){
        colorCache [0] = bgCache [0] =(位* 15)%360; //只是为了有一个奇特的例子:)
        GenerateParams PARAMS =新GenerateParams(
                //省略位置,看看在行动滑翔缓存(每进行24项/ 12行是一样的)
                机器人文本/ * +#+位置* /,
                Color.HSVToColor(colorCache)
                Color.HSVToColor(bgCache)
        );
        。发生器/ *的情况下的clone()你看到怪异的行为* /负载(PARAMS)。走进((ImageView的)holder.itemView)。
    }

    @覆盖公共RecyclerView.ViewHolder onCreateViewHolder(ViewGroup中父,诠释viewType){
        INT高= parent.getContext()getResources()getDisplayMetrics()heightPixels / 3。;
        ImageView的观点=新ImageView的(parent.getContext());
        view.setLayoutParams(新RecyclerView.LayoutParams(MATCH_PARENT,高度));
        view.setScaleType(ImageView.ScaleType.FIT_CENTER);
        返回新RecyclerView.ViewHolder(视图){}; //匿名类为简便起见,
    }
}

公共类GlideGeneratedImageListFragment扩展片段{
    @覆盖公共@Nullable查看onCreateView(LayoutInflater充气,容器的ViewGroup,捆绑savedInstanceState){
        RecyclerView视图=新RecyclerView(container.getContext());
        view.setLayoutParams(新MarginLayoutParams(MATCH_PARENT,MATCH_PARENT));
        view.setLayoutManager(新GridLayoutManager(container.getContext(),2 / *列* /));
        view.setAdapter(新GeneratingAdapter(view.getContext()));
        返回查看;
    }
}

/ **摘自imageWithText PARAMS,但留下了一些很难codeD值就像在{@link发电机} 20SP /加粗/中心。 * /
类GenerateParams {
    最后文本字符串;
    最终诠释色彩;
    最终诠释背景;

    公共GenerateParams(字符串文本,诠释色彩,诠释BG){
        this.text =文本;
        this.color =颜色;
        this.background = BG;
    }

    公共字符串的getId(){
        // TODO确保它是唯一的GenerateParams的每一个可能的情况下
        //因为这会影响生成位图是如何缓存
        //下面是正确正确的流场,如果这些改变这一现状必须改变
        返回的String.Format(Locale.ROOT,%S-%08x-%08X,文字,颜色,背景);
    }
}

/ **样板因为变性ModelType ==数据类型的,但是对于高速缓存的重要。
 * @see GeneratingAdapter#发电机* /
类GenerateParamsPassthroughModelLoader实现ModelLoader< GenerateParams,GenerateParams> {
    @覆盖公共DataFetcher< GenerateParams> getResourceFetcher(最终GenerateParams模型,诠释的宽度,高度INT){
        返回新DataFetcher< GenerateParams>(){
            @覆盖公共GenerateParams loadData(优先级优先级)抛出异常{回归模型; }
            @覆盖公共无效清除(){}
            @覆盖公共字符串的getId(){返回model.getId(); }
            @覆盖公共无效取消(){}
        };
    }
}

/ **把手池,以减少/ prevent GC的太多{@link位图#createBitmap} S *滞后/
类GenerateParamsBitma presourceDe codeR实现ResourceDe $ C $为CR GenerateParams,位图> {
    私人最终上下文的背景下;
    公共GenerateParamsBitma presourceDe codeR(上下文的背景下){this.context =环境; }
    @覆盖公共资源<位图>德code(GenerateParams源,诠释的宽度,高度INT)抛出IOException异常{
        BitmapPool池= Glide.get(上下文).getBitmapPool();
        点阵位图= pool.getDirty(宽度,高度,Bitmap.Config.ARGB_8888);
        如果(位图== NULL){
            位图= Bitmap.createBitmap(宽度,高度,Bitmap.Config.ARGB_8888);
        }
        Generators.imageWithTextNoLayout(上下文,位图,源);
        返回Bitma presource.obtain(位图,池);
    }
    @覆盖公共字符串的getId(){
        如果你改变发电机实施//要小心,你必须改变这种
        //否则用户可能会看到一个缓存的图像;在应用程序更新,或者清除缓存
        返回com.example.MyImageGenerator;
    }
}

一流的发电机{
    / ** OP的原始实​​现固定真正居中* /
    公共静态位图imageWithText(上下文的背景下,位图位图,GenerateParams PARAMS){
        TextView的视图=新的TextView(上下文);
        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(位);
        view.measure(makeMeasureSpec(canvas.getWidth(),完全一致),makeMeasureSpec(canvas.getHeight(),完全一致));
        view.layout(0,0,canvas.getWidth(),canvas.getHeight());
        view.draw(画布);
        返回的位图;
    }

    / **,而无需创建一个视图,更轻便的生成居中的文本。
     *考虑http://stackoverflow.com/a/8369690/253468为多行支持。 * /
    公共静态位图imageWithTextNoLayout(上下文的背景下,位图位图,GenerateParams PARAMS){
        涂料粉刷=新的油漆();
        paint.setColor(params.color);
        paint.setTextAlign(Paint.Align.CENTER); //文字的锚在给定的drawText在x
        paint.setTextSize(applyDimension(COMPLEX_UNIT_SP,20,context.getResources()getDisplayMetrics())。);
        paint.setTypeface(Typeface.DEFAULT_BOLD);

        帆布油画=新的Canvas(位);
        canvas.drawColor(params.background);
        canvas.drawText(params.text,canvas.getWidth()/ 2,canvas.getHeight()/ 2,油漆);
        返回的位图;
    }
}

//这里是如果你需要它的进口;
//不想把它在一开始就保持相关code第一。

进口java.io.IOException异常;
进口java.util.Locale中;

进口android.content.Context;
进口android.graphics *。
进口android.graphics.drawable.ColorDrawable;
进口android.os.Bundle;
进口android.support.annotation.Nullable;
进口android.support.v4.app.Fragment;
进口android.support.v7.widget *。
进口android.view *。
进口android.view.ViewGroup.MarginLayoutParams;
进口android.widget *。

进口静态android.util.TypedValue *。
引入静态android.view.View.MeasureSpec *。
引入静态android.view.ViewGroup.LayoutParams *。

进口com.bumptech.glide *。
进口com.bumptech.glide.load.ResourceDe codeR;
进口com.bumptech.glide.load.data.DataFetcher;
进口com.bumptech.glide.load.engine.Resource;
进口com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
进口com.bumptech.glide.load.model.ModelLoader;
进口com.bumptech.glide.load.resource.bitmap *。
进口com.bumptech.glide.load.resource.drawable.GlideDrawable;
进口com.bumptech.glide.load.resource.file.FileToStreamDe codeR;
进口com.bumptech.glide.load.resource.trans code.BitmapToGlideDrawableTrans codeR;
 

下面是它的样子(真正的滚动更加顺畅,GIF是非常低的FPS):

输入图像的描述在这里

注意它是如何加载的前几个项目,然后逐步加载休息。这需要一点点的内存高速缓存和池升温,但你可以使用preloader如果你想更平滑的显示。之后它的回暖它滚动很好。在操作栏调用的删除按钮 Glide.clearDiskCache() Glide.clearMemory()所以它开始regenating的项目了。

How can i use Glide library to load Bitmap into my ImageView? I want to create a custom image with text and load it into imageview using Glide.

This is my method to create custom bitmap with 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;
}

But when i try to load this bitmap using glide i'm getting error

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

解决方案

@rookiedev is right, there's no load(Bitmap) in Glide, for a reason: acquiring a Bitmap usually takes time and sometimes blocking I/O. So it's not good practice to call imageWithText on the UI thread. Update: That being said I proposed this feature a while back; and while the hacks are easier to do you can find the "Glide way" below, which I highly recommend.

Glide is designed to be flexible and this problem demonstrates that trait extremely well. The following implementation may seem long, but all pieces have their reason for existence. Given the performance gain, this amount of code to fit your generator into Glide's world is not much. I tried to format it to be short, collapsing irrelevant parts and using static imports to be shorter (see the end for imports).

The code also includes programmatically generated UI so you can just copy-paste all the below code into GlideGeneratedImageListFragment.java and run it; the only external dependency is support lib's RecyclerView.

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 http://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;

Here's how it looks like (real scrolling is much smoother, GIF is really low FPS):

Notice how it loads the first few items and then gradually loads the rest. It takes a little that the memory cache and pool warms up, but you can use a preloader if you want even smoother display. After it's warmed up it scrolls nicely. The delete button on the action bar calls Glide.clearDiskCache() and Glide.clearMemory() so it starts regenating the items again.

这篇关于利用Glide加载位图到ImageView的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆