Skip to content

Instantly share code, notes, and snippets.

@conceptdev
Created March 1, 2011 03:35
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save conceptdev/848571 to your computer and use it in GitHub Desktop.
Save conceptdev/848571 to your computer and use it in GitHub Desktop.
Custom Android View in MonoDroid: pan around an image larger than the screen
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Graphics;
using MagshopDemo;
using Android.Util;
/*
* Source:
* http://www.anddev.org/large_image_scrolling_using_low_level_touch_events-t11182.html
*
* Usage:
* <net.conceptdevelopment.monodroid.largeimagescroller
android:id="@+id/pageimageview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
*/
namespace net.conceptdevelopment.monodroid
{
public class largeimagescroller : View, IJavaObject
{
//HACK: hardcoded for Samsung Galaxy Tab
// Physical display width and height.
private int displayWidth = 600;
private int displayHeight = 1024;
private static Bitmap bmLargeImage; //bitmap large enough to be scrolled
private static Rect displayRect = null; //rect we display to
private Rect scrollRect = null; //rect we scroll over our bitmap with
private int scrollRectX = 0; //current left location of scroll rect
private int scrollRectY = 0; //current top location of scroll rect
private float scrollByX = 0; //x amount to scroll by
private float scrollByY = 0; //y amount to scroll by
private float startX = 0; //track x from one ACTION_MOVE to the next
private float startY = 0; //track y from one ACTION_MOVE to the next
// Not sure if all these ctor overloads are req'd in #MonoDroid...?
public largeimagescroller(IntPtr handle)
: base(handle)
{ constructor(); }
public largeimagescroller(Context context)
: base(context)
{ constructor(); }
public largeimagescroller(Context ctx, IAttributeSet attrs)
: base(ctx, attrs)
{ constructor(); }
void constructor ()
{
// Destination rect for our main canvas draw. It never changes.
displayRect = new Rect(0, 0, displayWidth, displayHeight);
// Scroll rect: this will be used to 'scroll around' over the
// bitmap in memory. Initialize as above.
scrollRect = new Rect(0, 0, displayWidth, displayHeight);
//HACK: hardcoded to load specific image
// Load a large bitmap into an offscreen area of memory.
bmLargeImage = BitmapFactory.DecodeResource(Resources, Resource.Drawable.p000);
}
public override bool OnTouchEvent(MotionEvent @event) {
switch (@event.Action) {
case MotionEventActions.Down:
// Remember our initial down event location.
startX = @event.RawX;
startY = @event.RawY;
break;
case MotionEventActions.Move:
float x = @event.RawX;
float y = @event.RawY;
// Calculate move update. This will happen many times
// during the course of a single movement gesture.
scrollByX = x - startX; //move update x increment
scrollByY = y - startY; //move update y increment
startX = x; //reset initial values to latest
startY = y;
Invalidate(); //force a redraw
break;
}
return true; //done with this event so consume it
}
protected override void OnDraw(Canvas canvas) {
// Our move updates are calculated in ACTION_MOVE in the opposite direction
// from how we want to move the scroll rect. Think of this as dragging to
// the left being the same as sliding the scroll rect to the right.
int newScrollRectX = scrollRectX - (int)scrollByX;
int newScrollRectY = scrollRectY - (int)scrollByY;
// Don't scroll off the left or right edges of the bitmap.
if (newScrollRectX < 0)
newScrollRectX = 0;
else if (newScrollRectX > (bmLargeImage.Width - displayWidth))
newScrollRectX = (bmLargeImage.Width - displayWidth);
// Don't scroll off the top or bottom edges of the bitmap.
if (newScrollRectY < 0)
newScrollRectY = 0;
else if (newScrollRectY > (bmLargeImage.Height - displayHeight))
newScrollRectY = (bmLargeImage.Height - displayHeight);
// We have our updated scroll rect coordinates, set them and draw.
scrollRect.Set(newScrollRectX, newScrollRectY,
newScrollRectX + displayWidth, newScrollRectY + displayHeight);
Paint paint = new Paint();
canvas.DrawBitmap(bmLargeImage, scrollRect, displayRect, paint);
// Reset current scroll coordinates to reflect the latest updates,
// so we can repeat this update process.
scrollRectX = newScrollRectX;
scrollRectY = newScrollRectY;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment