IndoorAtlas SDK 2.0: Using Picasso with custom ImageView

倖福魔咒の 提交于 2019-12-12 02:24:31

问题


So...., I want to use Picasso image loader library with an existing custom imageview class to load,resize,and rotate my image. The problem is I am unsuccessful with it as if I use this code: "Picasso.with(this).load(url).into(custom ImageView)",it gives me an error and suggests "cast parameter to target". After casting the parameter "custom imageview" to target, when I test the application it gives me error saying "custom imageview cannot be cast to target" in the Logcat. After this problem, I am using a different piece of code which contains "onBitmapLoaded" method which corresponds to the Picasso library's Target interface and I am successfully able to load,resize, and rotate the image,but as I am working on the development of an Indoor Positioning System, the blue dot is being displayed out of sight. The reason why it is being displayed out of sight/incorrectly is because the custom imageview is not being used with picasso to load and display the image. And here is the bit of code containing "onBitmapLoaded" method where I am not getting the result I want and it is also not correct, as after some moment the app crashes with this error "java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@1d21751f" and it refers to the line of code "super.onDraw(canvas)" in the custom ImageView class:

private IAFloorPlan mFloorPlan;
private BlueDotView mImageView;
private Target      mLoadTarget;

 private void showFloorPlanImage(String filePath) {
        final String url = mFloorPlan.getUrl();

        if (mLoadTarget == null) {
            mLoadTarget = new Target() {

                @Override
                public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                    Log.d(TAG, "onBitmap loaded with dimensions: " + bitmap.getWidth() + "x"
                            + bitmap.getHeight());
                    mImageView.setImage(ImageSource.bitmap(bitmap));
                    mImageView.setRadius(mFloorPlan.getMetersToPixels() * dotRadius);
                    //mImageView.setRotation(90);
                    //setupGroundOverlay(floorPlan, bitmap);
                }

                @Override
                public void onPrepareLoad(Drawable placeHolderDrawable) {
                    // N/A
                }

                @Override
                public void onBitmapFailed(Drawable placeHolderDraweble) {
                    Toast.makeText(AutomaticFloorPlanLoader.this, "Failed to load bitmap",
                            Toast.LENGTH_SHORT).show();
                }
            };
        }

        RequestCreator request = Picasso.with(this).load(url).rotate(90).resize(500,500);

        final int bitmapWidth = mFloorPlan.getBitmapWidth();
        final int bitmapHeight = mFloorPlan.getBitmapHeight();

        if (bitmapHeight > MAX_DIMENSION) {
            request.resize(0, MAX_DIMENSION);
        } else if (bitmapWidth > MAX_DIMENSION) {
            request.resize(MAX_DIMENSION, 0);
        }

        request.into(mLoadTarget);
        /*DisplayMetrics displaymetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
        int screenWidth = displaymetrics.widthPixels;
        int screenHeight = displaymetrics.heightPixels;
        LinearLayout.LayoutParams parms = new LinearLayout.LayoutParams(screenWidth,screenHeight);
        mImageView.setLayoutParams(parms);*/
        //Picasso.with(this).load(Uri.parse(mFloorPlan.getUrl())).into((Target) mImageView);
        Log.w(TAG, "showFloorPlanImage: " + filePath);
       /* mImageView.setRadius(mFloorPlan.getMetersToPixels() * dotRadius);
        mImageView.setImage(ImageSource.uri(filePath));
        mImageView.setRotation(90);*/
    }

Here is the result of the above code in my application: "http://i.imgur.com/kcSa2x1.png"

And here is the custom ImageView class:

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.util.AttributeSet;

import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;

public class BlueDotView extends SubsamplingScaleImageView {

    //private static final float RATIO = 4f / 3f;
    private float radius = 1.0f;
    private PointF dotCenter = null;

    public void setRadius(float radius) {
        this.radius = radius;
    }

    public void setDotCenter(PointF dotCenter) {
        this.dotCenter = dotCenter;
    }

    public BlueDotView(Context context) {
        this(context, null);
    }

    public BlueDotView(Context context, AttributeSet attr) {
        super(context, attr);
        initialise();
    }

    private void initialise() {
        setWillNotDraw(false);
        setPanLimit(SubsamplingScaleImageView.PAN_LIMIT_CENTER);
    }

    /*public BlueDotView(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
    }*/

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (!isReady()) {
            return;
        }

        if (dotCenter != null) {
            PointF vPoint = sourceToViewCoord(dotCenter);
            //float scaledRadius = getScale() * radius;
            Paint paint = new Paint();
            paint.setAntiAlias(true);
            paint.setStyle(Paint.Style.FILL);
            paint.setColor(Color.BLUE);
            canvas.drawCircle(vPoint.x, vPoint.y, 10, paint);
        }
    }
}

I have tried setLinearLayout,displayMetrics, and the onMeasure method and failed to resize the image with all of them.

So,overall my question is: how can I use Picasso with the custom ImageView class/the imageView itself to load,resize, and rotate the image and also displaying the blue dot correctly in this particular example?

Many thanks in advance if you can help me solve this problem.


回答1:


The BlueDotView (here: https://github.com/IndoorAtlas/android-sdk-examples/blob/master/Basic/src/main/java/com/indooratlas/android/sdk/examples/imageview/BlueDotView.java) in IndoorAtlas's example extends SubsamplingScaleImageView by Dave Morissey (here: https://github.com/davemorrissey/subsampling-scale-image-view). SubsamplingScaleImageView does not extend android.widget.ImageView and hence you cannot use it directly as load target: Picasso.with(this).load(url).into(mImageView) but you need to use Target just as you did.

What comes to java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@1d21751f this is because SubsamplingScaleImageView does not work out-of-the-box with most image loading libraries. Read more here: https://github.com/davemorrissey/subsampling-scale-image-view/wiki/X.-Using-with-Picasso. That link also explains the proper way of mixing SubsamplingScaleImageView with Picasso. The quick hack is to pass a copy of the Bitmap to image view:

@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
     mImageView.setImage(ImageSource.bitmap(bitmap.copy(bitmap.getConfig(), true));
}

This may be ok for small bitmaps that don't change often but is waste of resources for large bitmaps and can cause OOM exceptions.

It looks like your are resizing your bitmap to 500x500 pixels. If your original floor plan bitmap was not square (?) you are changing aspect ratio and positioning blue dot correctly will fail. To set e.g. width of your bitmap to 500px and still maintain aspect ratio, use: resize(500, 0).



来源:https://stackoverflow.com/questions/33708350/indooratlas-sdk-2-0-using-picasso-with-custom-imageview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!