Search code examples
androidimagetokenautocomplete

Image loading failed in TokenAutoComplete library


Im using TokenAutoComplete to create recipients, so i created custom view with image, but when i'm trying to load image into it, it doesn't work. I tried with Picasso and Glide with remote and local image url's. It doesn't gives any error, just loads the placeholder and thats it.

This is the relevant code :

the xml :

<data>
    <import type="android.text.TextUtils" />
    <import type="android.view.View" />
    <import type="android.graphics.Typeface" />

    <variable name="drawCircle" type="boolean" />

    <variable name="imageUrl" type="String" />
</data>

<LinearLayout
    android:id="@id/layout_content_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/bg_chip_token"
    android:orientation="horizontal"
    android:gravity="center_vertical"
    android:paddingRight="@dimen/view_padding"
    android:paddingEnd="@dimen/view_padding">

    <ImageView
        style="@style/AppStyle.Widget.ListItem.Image"
        android:id="@+id/image_user" />


    <TextView
        android:id="@+id/text_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:layout_marginLeft="@dimen/view_margin"
        android:layout_marginStart="@dimen/view_margin"
        android:ellipsize="middle"
        android:maxLines="1"
        android:textColor="@android:color/white"
        android:textAppearance="?android:attr/textAppearanceSmall" />

    <ImageView
        android:id="@+id/image_dismiss"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="@dimen/view_margin"
        android:layout_marginStart="@dimen/view_margin"
        android:src="@drawable/ic_clear_white_24dp"
        android:visibility="gone"/>

</LinearLayout>

styles :

<style name="AppStyle.Widget.ListItem.Image" parent="AppStyle.Widget.ImageView">
    <item name="android:layout_width">@dimen/list_item_icon_size</item>
    <item name="android:layout_height">@dimen/list_item_icon_size</item>
</style>

ContactsCompletionView:

public class ContactsCompletionView extends TokenCompleteTextView {

private ChipTokenBinding mBinding;


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

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

public ContactsCompletionView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);

}

@Override
protected View getViewForObject(final Recipient recipient) {
    LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
    mBinding = DataBindingUtil.inflate(inflater, R.layout.chip_token, (ViewGroup) getParent(), false);
    mBinding.textName.setText(recipient.getLabel());
    ImageViewBindingAdapter.loadImage(mBinding.imageUser, recipient.getImageUrl(), true,
            Drawables.getDrawable(getContext(), R.drawable.ic_account_circle_white_36dp));

    return mBinding.getRoot();
}

@Override
protected Recipient defaultObject(String completionText) {
    return null;
}

ImageViewBindingAdapter:

@BindingAdapter({"imageUrl", "circle", "error"})
    public static void loadImage(ImageView view, String imageUrl, boolean circle, Drawable error) {
        if (TextUtils.isEmpty(imageUrl) && error == null)
            return;

        Picasso.with(view.getContext())
               .load(imageUrl)
               .fit()
               .transform(circle ? new CircleTransformation() : new NullTransformation())
               .error(error)
               .placeholder(error)
               .into(view);
    }

Solution

  • Solved !

    problem was that this library doesn't resize the image so its get image in 0 size and doesn't show it. so there is need to use Picasso resize method :

    solution :

     @Override
        protected View getViewForObject(final Recipient recipient) {
            final LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
            final View rootView = inflater.inflate(R.layout.chip_token, (ViewGroup) getParent(), false);
    
            final TextView nameText = (TextView) rootView.findViewById(R.id.text_name);
            final ImageView userImage = (ImageView) rootView.findViewById(R.id.image_user);
    
            final int imageSize = getResources().getDimensionPixelSize(R.dimen.list_item_icon_size);
    
            nameText.setText(recipient.getLabel());
    
            Picasso.with(userImage.getContext())
                    .load(recipient.getImageUrl())
                    .resize(imageSize, imageSize)
                    .transform(new CircleTransformation())
                    .error(R.drawable.ic_account_circle_white_36dp)
                    .placeholder(R.drawable.ic_account_circle_white_36dp)
                    .into(new Target() {
                        @Override
                        public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                            userImage.setImageDrawable(new BitmapDrawable(bitmap));
                            invalidate();
                        }
    
                        @Override
                        public void onBitmapFailed(Drawable errorDrawable) {
                            userImage.setImageDrawable(errorDrawable);
                            invalidate();
                        }
    
                        @Override
                        public void onPrepareLoad(Drawable placeHolderDrawable) {
                            userImage.setImageDrawable(placeHolderDrawable);
                            invalidate();
                        }
                    });
    
            return rootView;
        }
    
    
    /**
     * {@link Picasso} transformation which makes the images shaped as circle.
     */
    public class CircleTransformation implements Transformation {
    
        private static final String TAG = "circle_transformation";
    
        @Override
        public Bitmap transform(Bitmap source) {
            int size = Math.min(source.getWidth(), source.getHeight());
    
            int x = (source.getWidth() - size) / 2;
            int y = (source.getHeight() - size) / 2;
    
            Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);
            if (squaredBitmap != source) {
                source.recycle();
            }
    
            Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig());
    
            Canvas canvas = new Canvas(bitmap);
            Paint paint = new Paint();
            BitmapShader shader = new BitmapShader(squaredBitmap,
                    BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
            paint.setShader(shader);
            paint.setAntiAlias(true);
    
            float r = size / 2f;
            canvas.drawCircle(r, r, r, paint);
    
            squaredBitmap.recycle();
            return bitmap;
        }
    
        @Override
        public String key() {
            return TAG;
        }
    }