问题
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