beraybentesen / glide-xamarin-android

Glide Xamarin Binding
https://www.nuget.org/packages/Glide.Xamarin/
61 stars 14 forks source link

Subclass ViewTarget #3

Open thaindq opened 7 years ago

thaindq commented 7 years ago

I'm trying to port this code to C# and this is what I've got so far

public class GlideImageGetter : Java.Lang.Object, Html.IImageGetter, Drawable.ICallback
{
    private Context mContext;
    private TextView mTextView;
    private HashSet<ImageGetterViewTarget> mTargets;

    public static GlideImageGetter Get(View view)
    {
        return (GlideImageGetter)view.GetTag(Resource.Id.drawable_callback_tag);
    }

    public void Clear()
    {
        GlideImageGetter prev = Get(mTextView);
        if (prev == null)
            return;

        foreach (var target in prev.mTargets)
        {
            Glide.Clear(target);
        }
    }

    public GlideImageGetter(Context context, TextView textView)
    {
        mContext = context;
        mTextView = textView;
        Clear();
        mTargets = new HashSet<ImageGetterViewTarget>();
        mTextView.SetTag(Resource.Id.drawable_callback_tag, this);
    }

    public Drawable GetDrawable(string source)
    {
        UrlDrawable urlDrawable = new UrlDrawable();

        Glide.With(mContext)
            .Load(source)
            .DiskCacheStrategy(DiskCacheStrategy.All)
            .Into(new ImageGetterViewTarget(mTextView, urlDrawable, mTargets));

        return urlDrawable;
    }

    public void InvalidateDrawable(Drawable who)
    {
        mTextView.Invalidate();
    }

    public void ScheduleDrawable(Drawable who, IRunnable what, long when) { }

    public void UnscheduleDrawable(Drawable who, IRunnable what) { }

    private class ImageGetterViewTarget : ViewTarget
    {
        private UrlDrawable mDrawable;

        public ImageGetterViewTarget(TextView view, UrlDrawable drawable, HashSet<ImageGetterViewTarget> mTargets) : base(view)
        {
            mTargets.Add(this);
            mDrawable = drawable;
        }

        public void OnResourceReady(Java.Lang.Object resource, IGlideAnimation glideAnimation)
        {
            Rect rect;
            TextView view = (TextView)View;
            GlideDrawable drawable = (GlideDrawable)resource;

            if (drawable.IntrinsicWidth > 100)
            {
                float width;
                float height;

                if (drawable.IntrinsicWidth >= view.Width)
                {
                    float downScale = (float)drawable.IntrinsicWidth / view.Width;
                    width = drawable.IntrinsicWidth / downScale;
                    height = drawable.IntrinsicHeight / downScale;
                }
                else
                {
                    float multiplier = (float)view.Width / drawable.IntrinsicWidth;
                    width = drawable.IntrinsicWidth * multiplier;
                    height = drawable.IntrinsicHeight * multiplier;
                }

                rect = new Rect(0, 0, Java.Lang.Math.Round(width), Java.Lang.Math.Round(height));
            }
            else
            {
                rect = new Rect(0, 0, drawable.IntrinsicWidth * 2, drawable.IntrinsicHeight * 2);
            }

            drawable.Bounds = rect;

            mDrawable.Bounds = rect;
            mDrawable.SetDrawable(drawable);

            if (drawable.IsAnimated)
            {
                mDrawable.SetCallback(Get(view));
                drawable.SetLoopCount(GlideDrawable.LoopForever);
                drawable.Start();
            }

            view.Text = view.Text;
            view.Invalidate();
        }        
    }
}

When I build the project, this error pops up

GlideImageGetter_ImageGetterViewTarget is not abstract and does not override abstract method onResourceReady(Object,GlideAnimation) in Target

I looked into binding interface Com.Bumptech.Glide.Request.Target.ITarget and couldn't find that abstract method but it does exist in java code. I guess the generic type Transition<? super R> transition is the cause. If so, is there any solution to this?

Eplebit commented 7 years ago

Similar problem. Trying to extend SimpleTarget so I can save the image to disk, but can't override OnResourceReady and get the same error as OP when compiling.

beraybentesen commented 7 years ago

Thanks, I will look into that and will notify you.

invertedrider commented 7 years ago

Same here... Would be great to derive from BasicTarget and override onResourceReady

Unless you tell me there's a better way to use Glide to set the background of a Layout

Thanks in advance!

digitaldjango commented 7 years ago

It seems that SimpleTarget and BaseTarget are abstract classes. The Xamarin binding has problems with abstract classes and methods with abstract input types. In theory it should generate something with a Java.Lang.Object as type but appearantly it doesn't. Not sure how to fix. Any suggestions?

beraybentesen commented 7 years ago

As @Speedrockracer said, I had to disable a few methods in Transforms file. Glide is quite complicated library compared to Picasso so I will ask to someone from Xamarin team and maybe they will recommend an intuitive idea.

digitaldjango commented 7 years ago

I tried to fix the binding but didn't have any success there. It is indeed very complicated. Also tried the following workaround. Very hacky and it didn't work. Wont even go into the SetResource method.. but crashes with a ClassCastException. Maybe someone here gets inspired and can make it work?

I'm trying to load the resulting bitmap in a SubsampelingScaleImageView for zooming. If someone knows a better way without using glide feel free to drop me a line.

void LoadImage() {
                Glide.With(this).Load(url).Into(new ImageLoadTarget(_postImageView, _dummyImageView));
        }

        private class ImageLoadTarget: BitmapImageViewTarget {

            SubsamplingScaleImageView _imageView;

            public ImageLoadTarget(SubsamplingScaleImageView imageView, ImageView realImageView) : base(realImageView) {
                _imageView = imageView;
            }

            protected override void SetResource(Bitmap bitmap)
            {
                _imageView.SetImage(ImageSource.InvokeBitmap(bitmap));
            }
        }
beraybentesen commented 7 years ago

I've updated to 3.8.0 and haven't tested yet. Could you give a chance to see that helps ?