I've got a bunch of tiles that make up a single image, that are rendered on request (by what's portion of the total image is visible on screen). The composite image is significantly larger than the screen. Each tile is positioned tightly next to its neighbors to create the illusion of a single image (the single image, if not tiled, would be too large and have OOM errors).
These are ImageViews inside a FrameLayout, positioned with top/leftMargin.
Targetting API 2.2 / SDK 8
I'm trying to scale the total image in response to user events (button presses, pinch, etc).
Apparently setScale isn't available until API 11. I tried using canvas.scale in onDraw of the FrameLayout with setWillNotDraw(false), and onDraw is being called, but no scaling is being applied (I assume because the layout itself doesn't have any graphic information? I had assumed it'd render it's children as well, but I guess not unless I'm doing something wrong here also).
I guess I could iterate through each tile and scale it independently, but would need to reposition each one as well, each time.
I have to think there's a way to scale a parent View (ViewGroup?) so that all of its children are also scaled (like every other language responsible for managing a GUI). What am I missing?
Thanks
For reference, the approach mentioned above (using onDraw of a parent ViewGroup) does in fact work. I had been using canvas.save() before the transformation and canvas.restore() after (based on some examples), which was incorrect.
The following is a generic subclass of FrameLayout that will scale it's children
package com.whatever.layouts;
import android.content.Context;
import android.graphics.Canvas;
import android.widget.FrameLayout;
public class ScalingFrameLayout extends FrameLayout {
private float scale = 1;
public ScalingFrameLayout(Context context) {
super(context);
setWillNotDraw(false);
}
public void setScale(float factor){
scale = factor;
invalidate();
}
public float getScale(){
return scale;
}
#Override
public void onDraw(Canvas canvas){
canvas.scale(scale, scale);
super.onDraw(canvas);
}
}
Related
I have reviewed many posts about determining size of images loaded with Glide into an Android ImageView, but they all seem to either refer to the ImageView size, or the original size of the source image. I need to be able to find out what the resulting BOUNDS is of the drawable INSIDE the ImageView.
I am using Glide 4.11.0 with Android targeting API21+. My layout is quite simple:
<ImageView
android:id="#+id/media_image_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
app:srcCompat="#drawable/grandparents_grandchildren_translucent" />
The app:srcCompat value is defined in the layout as a sample, at runtime this ImageView has different images chosen by the user to display. The code to do this is also straight-forward:
GlideApp.with(context)
.load(Uri.parse(path))
.apply(RequestOptions.fitCenterTransform())
.error(R.drawable.ic_image_error)
.into(imageView);
I don't have the option to specify a "hard-coded" height/width, as this app runs on many different devices and densities. I am counting on the combination of the ImageView/Glide to size the image appropriately to fit.
Loading and viewing all works fine - but I need to know the actual bounds in pixels on the screen of the device running this app of just the drawable. It is a similar ask to this question from many years ago.
I had this working fine in a small test app (not using Glide). In that code, I just used the image associated with the layout to do my testing of deriving the drawable bounds. I had been doing the following (after layout was complete and the ImageView loaded the image):
RectF bounds = new RectF();
Drawable drawable = mediaImageView.getDrawable();
mediaImageView.getImageMatrix().mapRect(bounds, new RectF(drawable.getBounds()));
Here is a screenshot, with the onDraw() method of our custom drawing surface view which overlays the ImageView adjusted to paint the rectangle it "thinks" represents the bounds of the viewable image:
As you can see the mediaImageView.getImageMatrix().mapRect() method has properly derived the rectangle which represents the bounds of the drawable as visible within the ImageView, as shown by the green rectangle.
When I moved over to the "real" app which uses Glide, the value derived by the mapRect() approach is no longer correct. I suspect that this is because the transform magic that Glide does under the covers and how it communicates with the ImageView are somehow at odds with the above technique for deriving the bounds of the final drawable:
I have also checked via the debugger what the drawable bounds rect is when it comes into the code at this juncture PRIOR to the mapRect() call. In the non-Glide test version the bounds rect matches the original size of the image (4032 pixels high by 3024 wide).
In the Glide version the drawable rect has already been adjusted (presumably by Glide) to be 1332 pixels high and 2000 pixels wide. I presume this is some sort of optimization thing that Glide is doing under the covers. However it does seem odd on the surface because that height/width is A) definitely not how it shows on the mobile device (it is taller than it is wide, as you can see in the screenshot), and B) doesn't match scale wise with the requested transform (fitCenterTransform). However, since it is displaying correctly there must either be some other step involved, or the drawable bounds data is simply not being referenced or used at this point.
How can I get the BOUNDS (not just width/height) of the drawable as viewed?
I have found a work-around thanks to this post.
The key is to intercept the Glide flow prior to it doing any operations on the drawable, but after it has snagged it from the network, and using its intrinsic width/height as the source for calculating the bounds as transformed.
I ended up changing the code that initializes our "DrawView" with the bounds of the drawable. The change involved these steps:
Get the correct width/height of the drawable prior to Glide doing any transformations.
Calculate the drawable bounds manually using a matrix conversion that takes into account the width/height of the ImageView and its scale type (ours is always FitCenter, so the code used is fixed to using that).
Use the resulting bounds to initialize our custom "drawView" view.
Fortunately, I can use a RequestListener within Glide to snag the size after Glide grabs it from the URL but before it performs the "into" the ImageView. Within this listener I can perform the matrix operations that match the transformation approach I have requested in order to get the correct bounds. Then I can call the method that initializes our DrawView custom view object appropriately:
GlideApp.with(this)
.load(Uri.parse(currentMedia.getUriPathToMedia()))
.listener(new RequestListener<Drawable>() {
#Override
public boolean onLoadFailed(#Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
return false;
}
#Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
RectF visualizedDrawableRect = new RectF(); // left, top, right, bottom
Matrix m = new Matrix();
RectF srcDrawableRect = new RectF(0, 0, resource.getIntrinsicWidth(), resource.getIntrinsicHeight());
RectF imageViewRect = new RectF(0, 0, mediaImageView.getWidth(), mediaImageView.getHeight());
if ( m.setRectToRect(srcDrawableRect, imageViewRect, Matrix.ScaleToFit.CENTER) ) {
m.mapRect(visualizedDrawableRect,srcDrawableRect);
// INITIALIZE OUR DRAWVIEW HERE
initializeDrawView(visualizedDrawableRect);
}
return false;
}
})
.apply(RequestOptions.fitCenterTransform())
.error(R.drawable.ic_image_error)
.into(mediaImageView);
One remaining question is whether I have to be concerned about using an anonymous listener in this way? Am I incurring a memory leak?
I've an large image in my android app, which represents a real pictured device.
Now I would like to know, whats the best way to do the following:
Mark some specific image sectors as clickable
Visual preview the click event (like a normal android button)
I've thought about something like the "imagemap" similar solution of
http://catchthecows.com/?p=113.
But it doesn't highlight the clicked section (neccessary for me).
It's not possible, or lets say very complicated, to create "n" different pictures which handle the highlighting effect (for example: section 1 clicked - so highlighting it, section 2 clicked - so higlighting it ....).
Any suggestions would be great.
Thanks a lot.
Btw:
My image looks like the following (the red sections should be clickable).
I had quick look at the ImageMap source you provided.
Here's the onDraw() method for ImageMap:
/**
* Paint the view
* image first, location decorations next, bubbles on top
*/
#Override
protected void onDraw(Canvas canvas) {
drawMap(canvas);
drawLocations(canvas);
drawBubbles(canvas);
}
So, as the comment states, the full image is drawn first, followed by the 'location decorations' (which would seem to be an area of particular interest), and finally the area 'bubbles', which basically seem to be tooltips for the selectable areas and might not be applicable to you.
Taking a look at the drawing method for the 'location decorations':
protected void drawLocations(Canvas canvas) {
for (Area a : mAreaList) {
a.onDraw(canvas);
}
}
And finally the draw method for the Area objects (which are the definable, selectable image areas):
// an onDraw is set up to provide an extensible way to
// decorate an area. When drawing remember to take the
// scaling and translation into account
public void onDraw(Canvas canvas) {
if (_decoration != null) {
float x = (getOriginX() * mResizeFactorX) + mScrollLeft - 17;
float y = (getOriginY() * mResizeFactorY) + mScrollTop - 17;
canvas.drawBitmap(_decoration, x, y, null);
}
}
I would say your best bet would be to use the ImageMap class to take care of most of the required functionality. You can use the supplied Area.onDraw() method to take care of the area 'highlighting'. Instead of drawing a 'decoration bitmap', use the shape information defined in the Area class or subclasses and use Canvas methods to draw a transparent highlight mask over the selected areas.
EDIT: You would need a seperate onDraw() implementation for each of the Area subclasses, as the area bounds information is stored in the subclasses.
I've removed my old code now as it wasn't working as I intended. I was trying to use the onDraw canvas feature within a certain portion of the screen so that I could still have buttons and other text around my drawing.
***EDIT***
I've managed to fix this issue now. A lot of what was suggested was helpful but I just couldn't get it to work with what I wanted. That's probably more my fault than anything else so thanks to all those who offered advice. Here's how I solved the issue.
*1. First Define a View in the Layout File.
<view
class="com.project.MainActivity.Drawing"
android:id="#+id/drawing_area"
android:layout_width="700dp"
android:layout_height="900dp"
android:layout_centerInParent="true"/>
*2. Then create a separate java class file with the following code:
public class Drawing extends View {
Paint paint = new Paint();
public Drawing(Context context) {
super(context);
}
public Drawing(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//Draw Image Here//
}
*3. Then call the Drawing from the main activity:
public class MainActivity extends Activity {
private Drawing mDrawingArea;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.percentage_count_layout);
mDrawingArea = (Drawing)findViewById(R.id.drawing_area);
}
In your View class you need to override the onMeasure() method. This is where you ask for a specific View size. There are some official Android tutorials on this subject and I will edit this post once I'm at my computer with the links.
EDIT:
Take a look at this Android article about creating custom components.. Specifically take a look at the section titled 'Extend onDraw() and onMeasure()'. Quoting:
onMeasure() is a little more involved. onMeasure() is a critical
piece of the rendering contract between your component and its
container. onMeasure() should be overridden to efficiently and
accurately report the measurements of its contained parts. This is
made slightly more complex by the requirements of limits from the
parent (which are passed in to the onMeasure() method) and by the
requirement to call the setMeasuredDimension() method with the
measured width and height once they have been calculated. If you fail
to call this method from an overridden onMeasure() method, the
result will be an exception at measurement time.
Further on in the article:
Your component's onMeasure() method should calculate a measurement width and height which will be required to render the component. It
should try to stay within the specifications passed in, although it
can choose to exceed them (in this case, the parent can choose what to
do, including clipping, scrolling, throwing an exception, or asking
the onMeasure() to try again, perhaps with different measurement
specifications).
There is an CustomView example available as a demo but unfortunately the developer website has changed (for the worse!) so that it's not available except through download by the SDK Manager. See the page here for more instructions.
For example, 200 width, 150 height. Override onMeasure method in the View.
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(200, 150);
}
From your description, it seems the issue is that you aren't specifying the size of your DemoView, you are just setting it as the ContentView, which will fill the parent by default.
Specify some LayoutParams when you create your DemoView, or create a ViewGroup to give it a size.
You could also define the layout / sizing via XML, and inflate that. (You should either make it a separate class, or make it public in this case.)
Eg.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
...
Specify container measurements
...
>
<com.yourpackagename.MainActivity.DemoView
...
Specify layout height / width, etc.
...
/>
</LinearLayout>
In Android, layout stuff like what you're trying to do is usually specified in xml. The idea is that you set up your layout in xml (there should be a layout directory in the res/ directory in your project) and then connect your code to that layout.
Take a look at this page. If you scroll down there's a section on layout position, size, and padding.
This is a method you can override in view to get the screen devices information, goes once per device
#Override
public void onSizeChanged (int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
screenW = w;
screenH = h;
scaledCardW = (int) (screenW/8); //or whatever scale you need for bitmaps
scaledCardH = (int) (scaledCardW*1.28);
bitmap = // load your bitmaps
}
You are using setContentView() which in itself means that the whole view is full screen. if you want the image to be set only a certain size you need to draw it that way.
onDraw(Canvas canvas)
{
super.onDraw(canvas)
//This code is for straight centering
//Also please do math outside of onDraw
//also below math is pseudocode not actual android code
canvas.drawBitmap(yourImageBitmap,
(screenSize.width / 2) - yourImageBitmap.width/2,
(screenSize.height / 2) - yourImageBitmap.height / 2),
yourPaintObject)
//The above code should draw your bitmap image in the center of the canvas
}
Also like answers above and below me say, if you wish to change canvas size then you need to use onMeasure and set those properly. Your best bet would be to look at the source code of the ImageView class http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/1.5_r4/android/widget/ImageView.java
and see how they do it
I've seen a few people ask how to zoom an entire ViewGroup (such as a RelativeLayout) in one go. At the moment this is something I need to achieve. The most obvious approach, to me, would be to hold the zoom scale factor as a single variable somewhere; and in each of the child Views' onDraw() methods, that scale factor would be applied to the Canvas prior to graphics being drawn.
However, before doing that, I have tried to be clever (ha - usually a bad idea) and extend RelativeLayout, into a class called ZoomableRelativeLayout. My idea is that any scale transformation could be applied just once to the Canvas in the overridden dispatchDraw() function, so that there would be absolutely no need to separately apply the zoom in any of the child views.
Here's what I did in my ZoomableRelativeLayout. It's just a simple extension of RelativeLayout, with dispatchDraw() being overridden:
protected void dispatchDraw(Canvas canvas){
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.scale(mScaleFactor, mScaleFactor);
super.dispatchDraw(canvas);
canvas.restore();
}
The mScaleFactor is manipulated by a ScaleListener in the same class.
It does actually work. I can pinch to zoom the ZoomableRelativeLayout, and all of the views held within properly rescale together.
Except there's a problem. Some of those child views are animated, and hence I periodically call invalidate() on them. When the scale is 1, those child views are seen to redraw periodically perfectly fine. When the scale is other than 1, those animated child views are only seen to update in a portion of their viewing area - or not at all - depending on the zoom scale.
My initial thinking was that when an individual child view's invalidate() is being called, then it's possibly being redrawn individually by the system, rather than being passed a Canvas from the parent RelativeLayout's dispatchDraw(), meaning that the child view ends up refreshing itself without the zoom scale applied. But oddly, the elements of the child views that are redrawn on the screen are to the correct zoom scale. It's almost as if the area that the system decides to actually update in the backing bitmap remains unscaled - if that makes sense. To put it another way, if I have a single animated child View and I gradually zoom in further and further from an initial scale of 1, and if we place an imaginary box on the area where that child view is when the zoom scale is 1, then the calls to invalidate() only cause a refresh of the graphics in that imaginary box. But the graphics that are seen to update are being done to the right scale. If you zoom in so far that the child view has now moved completely away from where it was with a scale of 1, then no part of it at all is seen to refresh. I'll give another example: imagine my child view is a ball that animates by switching between yellow and red. If I zoom in a little bit such that the ball moves to the right and down, at a certain point you'll just see the top-left quarter of the ball animate colours.
If I continuously zoom in and out, I see the child views animate properly and entirely. This is because the entire ViewGroup is being redrawn.
I hope this makes sense; I've tried to explain as best as I can. Am I on a bit of a loser with my zoomable ViewGroup strategy? Is there another way?
Thanks,
Trev
If you are applying a scale factor to the drawing of your children, you also need to apply the appropriate scale factor to all of the other interactions with them -- dispatching touch events, invalidates, etc.
So in addition to dispatchDraw(), you will need to override and appropriate adjust the behavior of at least these other methods. To take care of invalidates, you will need to override this method to adjust the child coordinates appropriately:
http://developer.android.com/reference/android/view/ViewGroup.html#invalidateChildInParent(int[], android.graphics.Rect)
If you want the user to be able to interact with the child views you will also need to override this to adjust touch coordinates appropriately before they are dispatched to the children:
http://developer.android.com/reference/android/view/ViewGroup.html#dispatchTouchEvent(android.view.MotionEvent)
Also I would strongly recommend you implement this all inside of a simple ViewGroup subclass that has a single child view it manages. This will get rid of any complexity of behavior that RelativeLayout is introducing in its own ViewGroup, simplifying what you need to deal with and debug in your own code. Put the RelativeLayout as a child of your special zooming ViewGroup.
Finally, one improvement to your code -- in dispatchDraw() you want to save the canvas state after applying the scaling factor. This ensures that the child can't modify the transformation you have set.
The excellent answer from hackbod has reminded me that I need to post up the solution that I eventually came to. Please note that this solution, which worked for me for the application I was doing at the time, could be further improved with hackbod's suggestions. In particular I didn't need to handle touch events, and until reading hackbod's post it did not occur to me that if I did then I would need to scale those as well.
To recap, for my application I what I needed to achieve was to have a large diagram (specifically, the floor layout of a building) with other small "marker" symbols superimposed upon it. The background diagram and foreground symbols are all drawn using vector graphics (that is, Path() and Paint() objects applied to Canvas in the onDraw() method). The reason for wanting to create all the graphics this way, as opposed to just using bitmap resources, is because the graphics are converted at run-time using my SVG image converter.
The requirement was that the diagram and associated marker symbols would all be children of a ViewGroup, and could all be pinch-zoomed together.
A lot of the code looks messy (it was a rush job for a demonstration) so rather than just copying it all in, instead I'll try to just explain how I did it with the relevant bits of code quoted.
First of all, I have a ZoomableRelativeLayout.
public class ZoomableRelativeLayout extends RelativeLayout { ...
This class includes listener classes that extend ScaleGestureDetector and SimpleGestureListener so that the layout can be panned and zoomed. Of particular interest here is the scale gesture listener, which sets a scale factor variable and then calls invalidate() and requestLayout(). I'm not strictly certain at the moment if invalidate() is necessary, but anyway - here it is:
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector){
mScaleFactor *= detector.getScaleFactor();
// Apply limits to the zoom scale factor:
mScaleFactor = Math.max(0.6f, Math.min(mScaleFactor, 1.5f);
invalidate();
requestLayout();
return true;
}
}
The next thing I had to do in my ZoomableRelativeLayout was to override onLayout(). To do this I found it useful to look at other people's attempts at a zoomable layout, and also I found it very useful to look at the original Android source code for RelativeLayout. My overridden method copies much of what's in RelativeLayout's onLayout() but with some modifications.
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b)
{
int count = getChildCount();
for(int i=0;i<count;i++){
View child = getChildAt(i);
if(child.getVisibility()!=GONE){
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)child.getLayoutParams();
child.layout(
(int)(params.leftMargin * mScaleFactor),
(int)(params.topMargin * mScaleFactor),
(int)((params.leftMargin + child.getMeasuredWidth()) * mScaleFactor),
(int)((params.topMargin + child.getMeasuredHeight()) * mScaleFactor)
);
}
}
}
What's significant here is that when calling 'layout()' on all the children, I'm applying the scale factor to the layout parameters as well for those children. This is one step towards solving the clipping problem, and also it importantly correctly sets the x,y position of the children relative to each other for different scale factors.
A further key thing is that I am no longer attempting to scale the Canvas in dispatchDraw(). Instead each child View scales its Canvas after obtaining the scale factor from the parent ZoomableRelativeLayout via a getter method.
Next, I shall move onto what I had to do within the child Views of my ZoomableRelativeLayout. There's only one type of View I contain as children in my ZoomableRelativeLayout; it's a View for drawing SVG graphics that I call SVGView. Of course the SVG stuff is not relevant here. Here's its onMeasure() method:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
float parentScale = ((FloorPlanLayout)getParent()).getScaleFactor();
int chosenWidth, chosenHeight;
if( parentScale > 1.0f){
chosenWidth = (int) ( parentScale * (float)svgImage.getDocumentWidth() );
chosenHeight = (int) ( parentScale * (float)svgImage.getDocumentHeight() );
}
else{
chosenWidth = (int) ( (float)svgImage.getDocumentWidth() );
chosenHeight = (int) ( (float)svgImage.getDocumentHeight() );
}
setMeasuredDimension(chosenWidth, chosenHeight);
}
And the onDraw():
#Override
protected void onDraw(Canvas canvas){
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.scale(((FloorPlanLayout)getParent()).getScaleFactor(),
((FloorPlanLayout)getParent()).getScaleFactor());
if( null==bm || bm.isRecycled() ){
bm = Bitmap.createBitmap(
getMeasuredWidth(),
getMeasuredHeight(),
Bitmap.Config.ARGB_8888);
... Canvas draw operations go here ...
}
Paint drawPaint = new Paint();
drawPaint.setAntiAlias(true);
drawPaint.setFilterBitmap(true);
// Check again that bm isn't null, because sometimes we seem to get
// android.graphics.Canvas.throwIfRecycled exception sometimes even though bitmap should
// have been drawn above. I'm guessing at the moment that this *might* happen when zooming into
// the house layout quite far and the system decides not to draw anything to the bitmap because
// a particular child View is out of viewing / clipping bounds - not sure.
if( bm != null){
canvas.drawBitmap(bm, 0f, 0f, drawPaint );
}
canvas.restore();
}
Again - as a disclaimer, there are probably some warts in what I have posted there and I am yet to carefully go through hackbod's suggestions and incorporate them. I intend to come back and edit this further. In the meantime, I hope it can start to provide useful pointers to others on how to implement a zoomable ViewGroup.
Hi friends
I am creating one app where i put two views. first is imageview and the other one is my customeview.
i am drawing image on my custom view. my custom view code is as follow
public class DrawView extends ImageView{
#SuppressWarnings("unused")
private static final String TAG = "DrawView";
Painter painter = new Painter();
PathStack pathStack;
private DrawApplication drawApplication;
public DrawView(Context context, AttributeSet attr) {
super(context,attr);
setFocusable(true);
setFocusableInTouchMode(true);
drawApplication=(DrawApplication)context.getApplicationContext();
pathStack=drawApplication.getPainter().getPathStack();
painter=drawApplication.getPainter();
setScaleType(ScaleType.MATRIX);
}
#Override
public void onDraw(Canvas canvas) {
float scaleFactor=drawApplication.getScaleFactor();
canvas.scale(scaleFactor, scaleFactor,(float)getWidth()/2,(float)getHeight()/2);
List<DrawingPath> currentStack=pathStack.getCurrentStack();
for (DrawingPath drawPath : currentStack) {
drawPath.draw(canvas, painter);
}
}
}
many things clear from code like storing path on drawapplication etc.
now we have decided to provide zooming and panning to this view. and my drawing should also be zoomed accordingly along with imageview which in back.
also i should be able to draw correctly.
I tried canvas scaling but that is worst, because after scaling i am not able to draw to the touched point and also less drawing to the screen resulting in more drawing to the view.
drawing on widget is also very lengthy task results in performance slow down.
plz provide any way.
and also i am using api level 10.
Edit1
Well friends. i got one idea.
i have to draw path on different zoom level. so if we can calculate path ratio in different zoom level than it will solve my problem. plz provide help accordingly
Edit2
if we will be able to scale path then it can solve my problem
Edit3
i think if we draw it on bitmap than i can achieve my goal, but my problem is resizing bitmap and providing scrolling to bitmap on different zoom level
Similar questions on SO:
android pinch zoom
Pinch zoom for custom view
Can be done on Honeycomb (API lvl 11) but not properly before.
I don't think a normal view can be zoomed. You could capture the touch events and scale the view widgets correspondingly.