【问题标题】:How to add entry chips in android dynamically along with icon如何在android中动态添加入口芯片和图标
【发布时间】:2019-12-24 13:30:04
【问题描述】:

我需要使用材料设计库动态添加入口芯片以及将通过 API 调用检索的图标。 如何使用 Glide 库设置芯片图标?

注意:我之前没有在可绘制文件夹中保存任何图像。正在通过 API 调用检索所有数据。

【问题讨论】:

  • bumptech.github.io/glide/doc/getting-started.html。非视图目标。只需使用可绘制资源调用 setChipIcon。
  • @Raghunandan - 我熟悉使用 Glide。但就我而言 - 我没有任何特定的 UI 元素,如 ImageView。我希望它在chipIcon中。正如我们所知 - setChipIcon() 只接受我们之前保存在文件夹中的图像。
  • 不,您可以设置从 url 下载的 drawable。github.com/material-components/material-components-android/blob/… 第 1456 行,您可以从 glide 获得 public void onResourceReady(Drawable resource, Transition<Drawable> transition) { drawable
  • 但是,那些保存在drawable中的图像在使用后会被删除吗?我不需要任何东西来保存。如果你不介意 - 你能用 codeSnippet 解释一下吗?
  • 只需遵循非视图目标中的滑翔文档即可。如果您不想缓存bumptech.github.io/glide/doc/caching.html,请检查跳过缓存部分

标签: java android android-studio material-design android-chips


【解决方案1】:

例如,您可以使用此解决方法。定制芯片:

public class GlideChip extends Chip {

    public GlideChip(Context context) {
        super(context);
    }

    public GlideChip(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    /**
     * Set an image from an URL for the {@link Chip} using {@link com.bumptech.glide.Glide}
     * @param url icon URL
     * @param errDrawable error icon if Glide return failed response
     */
    public GlideChip setIconUrl(String url, Drawable errDrawable) {
        Glide.with(this)
                .load(url)
                .listener(new RequestListener<Drawable>() {
                    @Override
                    public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                        setChipIcon(errDrawable);
                        return false;
                    }

                    @Override
                    public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
                        setChipIcon(resource);
                        return false;
                    }
                }).preload();
        return this;
    }

}

创建GlideChip,加入芯片组并启动项目:

public class ChipFragment extends Fragment {

    private ChipGroup chipGroup;

    public ChipFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_chip, container, false);
        chipGroup = view.findViewById(R.id.chipGroup);
        Chip chip = createChip("John Doe", "https://i1.sndcdn.com/avatars-000197335271-mztyvq-t500x500.jpg");
        chipGroup.addView(chip);
        return view;
    }

    private Chip createChip(String name, String avatarUrl) {
        GlideChip chip = new GlideChip(getContext());
        chip.setText(name);
        chip.setIconUrl(avatarUrl, getResources().getDrawable(R.drawable.err_avatar));
        chip.setClickable(true);
        chip.setFocusable(true);
        return chip;
    }

}

P/S...不要忘记将 Glide 添加到 build.gradle。见here

【讨论】:

    【解决方案2】:

    提供的answer偶尔会导致崩溃:

    java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.graphics.Bitmap.isRecycled()' on a null object reference
    at android.graphics.Canvas.throwIfCannotDraw(Canvas.java:1270)
    at android.view.DisplayListCanvas.throwIfCannotDraw(DisplayListCanvas.java:257)
    at android.graphics.Canvas.drawBitmap(Canvas.java:1415)
    at com.bumptech.glide.load.resource.gif.GifDrawable.draw(SourceFile:291)
    at com.google.android.material.chip.ChipDrawable.drawChipIcon(SourceFile:652)
    at com.google.android.material.chip.ChipDrawable.draw(SourceFile:568)
    at android.graphics.drawable.DrawableWrapper.draw(DrawableWrapper.java:228)
    ...
    

    这是因为 drawable 没有被正确清除。正确的实现是(示例在 Kotlin 中):

        Glide.with(this)
                    .load(url)
                    .into(object : CustomTarget<Drawable>(200, 200) { //size might be omitted
    
                override fun onLoadFailed(errorDrawable: Drawable?) {
                    chipIcon = errDrawable
                }
    
                override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
                    chipIcon = resource
                }
    
                override fun onLoadCleared(placeholder: Drawable?) {
                    chipIcon = placeholder
                }
    
            })
    

    【讨论】:

      【解决方案3】:

      对于 Coil 和 Kotlin 爱好者,我根据 @Javisanswer 制作了一个 CoilChip。 (向贾维斯致敬!)

      class CoilChip(context: Context?) : Chip(context) {
          /**
           * @param url icon URL
           * @param errDrawable set error icon in onError callback
           */
          fun setIconUrl(url: String, placeholderDrawable: Drawable?, errDrawable: Drawable?) {
              chipDrawable?.let {
                  val request = ImageRequest.Builder(context)
                      .data(url)
                      .target(
                          onStart = { placeholder ->
                              chipIcon = placeholderDrawable
                          },
                          onSuccess = { result ->
                              chipIcon = result
                          },
                          onError = { error ->
                              chipIcon = errDrawable
                          })
      //              .memoryCachePolicy(CachePolicy.DISABLED) // caching strategy             
                      .build()
      
                  val imageLoader = ImageLoader.Builder(context)
                      .build()
                  imageLoader.enqueue(request)
              }
          }
      }
      

      如果遇到异常Software rendering doesn't support hardware bitmaps,请将以下内容添加到您的图像请求中。

      .bitmapConfig(Bitmap.Config.ARGB_8888)
      

      干杯!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-09-02
        • 2019-12-22
        • 1970-01-01
        • 2018-12-18
        • 2021-11-07
        • 2019-10-22
        • 1970-01-01
        • 2018-10-26
        相关资源
        最近更新 更多