Reputation: 489
I have an activity that has an ImageView defined inside a HorizontalScrollView. The image source is a 9-patch file that is constrained to stretch only the right edge to fill the screen. I have implemented a simple zoom feature which allows the user to double tap to zoom in and out, by resizing the bitmap and assigning the new bitmap to the view. My current problem is that when doubling tapping to zoom back out, the 9-patch is not applied when I assign the new resized bitmap to the view. In other words, instead of stretching just the right edge as defined in the 9-patch file, it stretched the entire image.
Here is my XML:
<HorizontalScrollView
android:id="@+id/hScroll"
android:fillViewport="true"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fadingEdge="none" >
<RelativeLayout
android:id="@+id/rlayoutScrollMap"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ImageView
android:id="@+id/imgResultMap"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="fitXY"
android:src="@drawable/map_base"/>
</RelativeLayout>
</horizontalScrollView>
Here is the relevant portion of my code, inside the onDoubleTap() call :
public boolean onDoubleTap(MotionEvent e)
{
if (zoom == 1) {
zoom = 2; // zoom out
} else {
zoom = 1; // zoom in
}
Bitmap image = BitmapFactory.decodeResource(getResources(),R.drawable.map_base);
Bitmap bmp = Bitmap.createScaledBitmap(image, image.getWidth() * zoom, image.getHeight() * zoom, false);
ImageView imgResultMap = (ImageView)findViewById(R.id.imgResultMap);
imgResultMap.setImageBitmap(bmp);
return false;
}
EDIT: After doing some research, I have it figured out. Instead of just manipulating the bitmap, I need to also include the 9-patch chunk, which is not part of the bitmap image, to re-construct a new 9-patch drawable. See sample code below:
...
else {
// Zoom out
zoom = 1;
Bitmap mapBitmapScaled = mapBitmap;
// Load the 9-patch data chunk and apply to the view
byte[] chunk = mapBitmap.getNinePatchChunk();
NinePatchDrawable mapNinePatch = new NinePatchDrawable(getResources(),
mapBitmapScaled, chunk, new Rect(), null);
imgResultMap.setImageDrawable(mapNinePatch);
}
....
Upvotes: 5
Views: 9714
Reputation: 98
Also another solution is to set image programmatically as ImageResource and set scaleType
imageView.setImageResource(R.drawable.favorite_driver_icon);
imageView.setScaleType(ScaleType.FIT_XY);
Upvotes: 0
Reputation: 1718
9-patch images seem to only work when they're set as a View
's background image. So:
android:src
, set android:background
in your layout XML, andsetBackgroundResource()
when you want to change the image.You can also use a plain View
instead of an ImageView
if you want; it doesn't really matter much.
Upvotes: 0
Reputation: 489
EDIT: After doing some research, I have it figured out. Instead of just manipulating the bitmap, I need to also include the 9-patch chunk, which is not part of the bitmap image, to re-construct a new 9-patch drawable. See sample code below:
...
else {
// Zoom out
zoom = 1;
Bitmap mapBitmapScaled = mapBitmap;
// Load the 9-patch data chunk and apply to the view
byte[] chunk = mapBitmap.getNinePatchChunk();
NinePatchDrawable mapNinePatch = new NinePatchDrawable(getResources(),
mapBitmapScaled, chunk, new Rect(), null);
imgResultMap.setImageDrawable(mapNinePatch);
}
....
EDIT #2: For those who looks at my solution here, also take a look at Kai's suggestions below regarding memory management. Very useful information.
Upvotes: 10
Reputation: 15476
Why don't you just include two different scaled images and switch between them using imgResultMap.setImageResource(resId)
when zooming? Also note that you are loading & creating Bitmaps in UIThread which is not a good way to provide smooth user experience, at least preload the bitmap only once during onCreate() and cache that.
Upvotes: 1
Reputation: 3550
Move this:
ImageView imgResultMap = (ImageView)findViewById(R.id.imgResultMap);
to a global intialized in the onCreate method. Otherwise the device has to search for the view and find it every time it is tapped.
and try calling imgResultMap.invalidate();
before you return from the onDoubleTap method
(http://developer.android.com/reference/android/view/View.html#invalidate())
Upvotes: 0