Large Image Scrolling Using Low Level Touch Events

Basic Tutorials concerning: GUI, Views, Activites, XML, Layouts, Intents, ...

Postby pskink » Sat Mar 13, 2010 10:27 am

XCaffeinated wrote:I guess that is a long-winded way of answering your question of why I didn't add fling or double tap to the tutorials :). As for zoom, yes I should probably add that somewhere :).

Regards,
Sharon


hi Sharon

yes i understand why you didn'n add those flings and double taps ;)

in my Scroll.java i added zoom and it took just couple of lines of code (except handler implementation) but i hate idea how my zooming works - i cannot find out some elegant solution for zooming where the content zooms in, exactly in the spot of double tap (i mean double tap screen location doesn't move, everything else zooms in). i tried several approaches and always it gets too complicated (tons of fields, complex logic etc).

so if you are considering adding zoom, and will figure it out please share it somewhere here. or maybe you know any tutorials describing how to do such things?

my optimized Scroll.java is here, it uses Picture for speeding graphics and StaticLayout for compex text drawing on canvas

thanks
Attachments
Scroll.java
(5.1 KiB) Downloaded 773 times
pskink
pskink
Master Developer
Master Developer
 
Posts: 719
Joined: Mon Nov 24, 2008 3:49 pm

Top

Postby M4RC0 » Sat Mar 13, 2010 12:58 pm

certainly, Scroll class worked for me, now I have fling effect on my image, thanks a lot

i only had to change some scales (to set a min_scale), change the animation velocity on scale change (by divide velocity by scale factor)

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
  3.  
  4.         velocityX *= 0.75 / mScale;
  5.  
  6.         velocityY *= 0.75 / mScale;
  7.  
  8.         mScroller.fling((int) mX, (int) mY, (int) velocityX, (int) velocityY, -WIDTH, 0, -HEIGHT, 0);
  9.  
  10.         invalidate();
  11.  
  12.         return true;
  13.  
  14. }
  15.  
  16.  
Parsed in 0.030 seconds, using GeSHi 1.0.8.4

and implement the onDown method to stop fling on user tap (dont know if its the best way of stop fling :P):
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. public boolean onDown(MotionEvent e) {
  3.  
  4.         mScroller.forceFinished(true);
  5.  
  6.         return true;
  7.  
  8. }
  9.  
  10.  
Parsed in 0.031 seconds, using GeSHi 1.0.8.4


now scroll and fling behaviours are perfect for me :P

next, im trying to get the center of zoom_in on the point of double tap, or at least to the screen center.
it could be a bit hard for be because of the scalation...

thank you all guys, we appreciate your help!!
M4RC0
Junior Developer
Junior Developer
 
Posts: 12
Joined: Sun Feb 28, 2010 10:53 pm

Postby pskink » Sat Mar 13, 2010 2:53 pm

M4RC0 wrote:and implement the onDown method to stop fling on user tap (dont know if its the best way of stop fling :P):
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. public boolean onDown(MotionEvent e) {
  2.         mScroller.forceFinished(true);
  3.         return true;
  4. }
  5.  
Parsed in 0.033 seconds, using GeSHi 1.0.8.4


it is the perfect way of stopping Scroller

M4RC0 wrote:now scroll and fling behaviours are perfect for me :P

next, im trying to get the center of zoom_in on the point of double tap, or at least to the screen center.
it could be a bit hard for be because of the scalation...

thank you all guys, we appreciate your help!!


i already tried to do that (see my previous post) but unfortunately i cannot find elegant solution (without millions of variables and messy code) - but i believe it must be easy solution for such simple thing - if you find out something share it here
pskink
pskink
Master Developer
Master Developer
 
Posts: 719
Joined: Mon Nov 24, 2008 3:49 pm

Postby pskink » Tue Mar 16, 2010 9:21 pm

M4RC0 wrote:now scroll and fling behaviours are perfect for me :P

next, im trying to get the center of zoom_in on the point of double tap, or at least to the screen center.
it could be a bit hard for be because of the scalation...

thank you all guys, we appreciate your help!!


i almost did it! i tried several attempts and my code always got messy, now i know why: i was first scaling the canvas and then translating, now i'm first translating then scaling. it turns out that this approach is much better

now zooming 'pivot' is located on the left/top corner of the view, but i also managed to "center" zoom: see onDraw and zoomTopLeft boolean variable. the only problem is when zoomed i cannot reach left/top side and also can move behind right/bottom side.... :-(

any suggestions?
Attachments
Scroll.java
(6.62 KiB) Downloaded 362 times
pskink
pskink
Master Developer
Master Developer
 
Posts: 719
Joined: Mon Nov 24, 2008 3:49 pm

Postby M4RC0 » Tue Mar 16, 2010 11:02 pm

great!!

it now it could be dificult for me to adapt my modified Scroll.java to implement your solution (diff match almost 15 lines :P), could you point to the base solution code?
anyway im gonna try to mix by myself

i'm now also trying to prevent OutOfMemory exception when changing the lange image (user can change from various large images), i didnt find the way to remove old image from memory (recycle() didnt worked)...

thanks pskink, great job!
M4RC0
Junior Developer
Junior Developer
 
Posts: 12
Joined: Sun Feb 28, 2010 10:53 pm

Postby pskink » Tue Mar 16, 2010 11:27 pm

M4RC0 wrote:great!!

it now it could be dificult for me to adapt my modified Scroll.java to implement your solution (diff match almost 15 lines :P), could you point to the base solution code?
anyway im gonna try to mix by myself


basically i changed zooming using standard zooming controls, the code itself didn'n change much - it should be quite easy to integrate it
pskink
pskink
Master Developer
Master Developer
 
Posts: 719
Joined: Mon Nov 24, 2008 3:49 pm

Top

Postby pskink » Tue Mar 23, 2010 9:57 am

good news, i managed to do the zoom i wanted - the code is even more simple then before - i only need to handle scale < 1 or more precisely when canwas width/height is lower then view width/height and draw scrollbars - but those are piece of cake...

stay tuned
Attachments
Scroll.java
(7.05 KiB) Downloaded 340 times
pskink
pskink
Master Developer
Master Developer
 
Posts: 719
Joined: Mon Nov 24, 2008 3:49 pm

Postby pskink » Wed Mar 24, 2010 4:38 pm

pskink wrote:good news, i managed to do the zoom i wanted - the code is even more simple then before - i only need to handle scale < 1 or more precisely when canwas width/height is lower then view width/height and draw scrollbars - but those are piece of cake...

stay tuned


as promised - added scrollbars, what is left is support when canwas width/height is lower then view width/height

this time complete eclipse project attached

stay tuned
Attachments
Scroll.tar.gz
(17.31 KiB) Downloaded 588 times
pskink
pskink
Master Developer
Master Developer
 
Posts: 719
Joined: Mon Nov 24, 2008 3:49 pm

Postby M4RC0 » Wed Mar 24, 2010 4:45 pm

thank u very much... ill test ti soon (lot of work now...)

great job!
M4RC0
Junior Developer
Junior Developer
 
Posts: 12
Joined: Sun Feb 28, 2010 10:53 pm

Postby XCaffeinated » Wed Mar 24, 2010 5:19 pm

Here is a version of the long-press tutorial with center-and-zoom added. On a long press it will center and zoom. It zooms in 6 levels, then zooms back out. It also respects bitmap boundaries, and scroll rectangle edges at whatever the current zoom level is. So if you press in the upper left corner say, the bitmap will stay locked in that corner and just zoom around the original center point, rather than try to 'center' around the upper left corner. I did this because it's a harder problem to solve (boundary tracking at a particular zoom level) than just 'center wherever you press' and also gives us a nice look and feel. Take a look at the comments at the clamp() calls for more. If you don't need this functionality, it should be easy to strip it out and update the scroll rectangle coordinates accordingly.

Seems like there are a few good solutions posted in this thread now, so hopefully this can just be another data point for those needing zoom-and-center solutions.

The changes from the long-press tutorial are the addition of a bitmap tracking point (bmRefPtX, bmRefPtY) which gets coordinated with the scroll rectangle, where the scroll rectangle is adjusted by the current zoom value. There is a set of tracking variables for screen width and height (scaledWidth, scaledHeight) that will track the current screen width and height, adjusted by the current zoom level. All the zoom code is in handleLongPress() and the scroll rectangle updates are handled in onDraw(). I changed .getRawX() and .getRawY() to .getX() and .getY() in the touch event handler, which otherwise remains unchanged.

You can diff this code with the long-press tutorial to see the changes. handleLongPress() is commented heavily, and onDraw() is commented at the changes. Most other comments were stripped but can be found in the original tutorial.

-XCaf
Attachments
ImageScrollZoom.java
(11.6 KiB) Downloaded 538 times
XCaffeinated
Developer
Developer
 
Posts: 25
Joined: Sun Nov 29, 2009 10:16 pm

Postby pskink » Mon Mar 29, 2010 8:58 am

hi,

added auto zoom in/out on double click.

in my previous post i used Handlers to achieve this effect but custom Animations are much better for this purpose since timing/duration is made by system and the only thing you have to do is to implement animation itself.

also Animation framework uses notion of normalized time <0..1> which is very easy to combine with Interpolators - i used it in zomming in/out by creating two OvershootInterpolators - two or three lines of code and you can have quite nice visual effects

everyone who wants to create custom complex animation can see it in action - refer to inner ZoomAnimation class

have fun

p.s. it also shows how to use custom scrollbars in a custom View
Attachments
Scroll.tar.gz
(19.83 KiB) Downloaded 1741 times
pskink
pskink
Master Developer
Master Developer
 
Posts: 719
Joined: Mon Nov 24, 2008 3:49 pm

Postby alejo » Wed Mar 31, 2010 11:44 am

hey, thank you for your code. It's been very useful for the my learning... in fact, I could learn a few things from your code, but I'd like to comment on a couple of lines, since some newbies (just like me) may have issues.

This piece of code is the loader of the image:
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. // draw droids
  3.  
  4.         c.save();
  5.  
  6.         Paint droidPaint = new Paint();
  7.  
  8.         Bitmap android = BitmapFactory.decodeResource(getResources(), R.drawable.droid);
  9.  
  10.         c.translate(200, 250);
  11.  
  12.         c.scale(2, 2);
  13.  
  14.         droidPaint.setAlpha(192);
  15.  
  16.         c.drawBitmap(android, 0, 0, droidPaint);
  17.  
  18.         droidPaint.setAlpha(255);
  19.  
  20.         c.drawBitmap(android, 100, 300, droidPaint);
  21.  
  22.         c.restore();
Parsed in 0.037 seconds, using GeSHi 1.0.8.4


First: Where it states R.drawable.droid, you can change "droid" for your image in the drawable folder.
Second: As you can see there are two droidPaint, so the image will be shown twice, the first one certain transparency (alpha) and the second one, though solid, is moved to the lower right corner.
Third: The translate command creates a certain initial distance between the image and the screen top-left corners.

So, in the end, for my application I used this code:

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. // draw droids
  3.  
  4.         c.save();
  5.  
  6.         Paint droidPaint = new Paint();
  7.  
  8.         Bitmap android = BitmapFactory.decodeResource(getResources(), R.drawable.MYIMAGE);
  9.  
  10.         c.scale(1, 1);
  11.  
  12.         droidPaint.setAlpha(255);
  13.  
  14.         c.drawBitmap(android, 0, 0, droidPaint);
  15.  
  16.         c.restore();
Parsed in 0.036 seconds, using GeSHi 1.0.8.4


I've disabled the text lines, so the image loads smoothly.
Were I to release a program, would it be better to clean the code by deleting these lines? Since I'm new to modifying anything rather than php or html, I'm unaware of the usual prog-ettiquete (net-ettiquete for programmers?). On the other hand, since there's an image within, the influence of a few extra lines may not be noteworthy.

Thank you
alejo
Junior Developer
Junior Developer
 
Posts: 10
Joined: Wed Mar 31, 2010 9:08 am

Postby pskink » Wed Mar 31, 2010 12:07 pm

alejo wrote:I've disabled the text lines, so the image loads smoothly.
Were I to release a program, would it be better to clean the code by deleting these lines? Since I'm new to modifying anything rather than php or html, I'm unaware of the usual prog-ettiquete (net-ettiquete for programmers?). On the other hand, since there's an image within, the influence of a few extra lines may not be noteworthy.

Thank you


if you just want to draw bitmap, simply call:

canvas.drawBitmap(mBitmap, 0, 0, null)

in onDraw(Canvas canvas, Matrix matrix)
pskink
pskink
Master Developer
Master Developer
 
Posts: 719
Joined: Mon Nov 24, 2008 3:49 pm

Postby alejo » Wed Mar 31, 2010 12:28 pm

Ah... ummm..... seems like I'm more or less able to read some lines, but I totally lack of knowledge to write them by myself...

Thank you once again, pskink
alejo
Junior Developer
Junior Developer
 
Posts: 10
Joined: Wed Mar 31, 2010 9:08 am

Postby alejo » Thu Apr 08, 2010 10:09 pm

I've been doing some testing with other tutorials and have tried a couple of them in friends' devices.
For some reason, the milestone doesnt load the full image. At first there was a force close error which turned out to be, as the first post mentions, a memory problem.
Now, with a smaller image, Milestone doesnt load the full image, it's missing the lower third of it.
I've successfully tested it on an htc magic and an htc hero
alejo
Junior Developer
Junior Developer
 
Posts: 10
Joined: Wed Mar 31, 2010 9:08 am

Top
PreviousNext

Return to Novice Tutorials

Who is online

Users browsing this forum: No registered users and 5 guests