Scrolling a Picture (horizontally and vertically)

Tutorials with advanced 'difficulty' and more Lines of Code.

Scrolling a Picture (horizontally and vertically)

Postby Danuubz » Thu Oct 23, 2008 12:33 pm

I've written a small code example which shows how to make a picture scrollable by hand. You can scroll it by dragging it with the mouse (or finger).

In this case, the picture has to be sized exactly [800x600], named like 'pic.jpg' or 'pic.png' and it should be placed in the folder 'res>drawable>' of your project.

Actually, making more complex views scrollable by hand should work the same way. However the coordinates of each component and its behavior have to be adapted after every single scroll movement. So if there's a way making it out of the box, that would be the preferable choice of course :D


Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. package de.horizontalscroll;
  2.  
  3.  
  4.  
  5. import de.horizontalscroll.R;
  6.  
  7. import android.app.Activity;
  8.  
  9. import android.os.Bundle;
  10.  
  11. import android.view.*;
  12.  
  13. import android.view.GestureDetector.OnGestureListener;
  14.  
  15. import android.content.*;
  16.  
  17. import android.graphics.*;
  18.  
  19. import android.content.res.*;
  20.  
  21.  
  22.  
  23. public class HorizontalScroll extends Activity implements OnGestureListener
  24.  
  25. {
  26.  
  27.         private static final int X_MAX = 800;
  28.  
  29.         private static final int Y_MAX = 600;
  30.  
  31.         private int scrollX = 0;
  32.  
  33.     private int scrollY = 0;
  34.  
  35.        
  36.  
  37.     MyView main;  
  38.  
  39.     Bitmap bmp;
  40.  
  41.     Bitmap adapt;
  42.  
  43.     Resources res;
  44.  
  45.     Paint paint;
  46.  
  47.     GestureDetector gestureScanner;
  48.  
  49.        
  50.  
  51.     @Override
  52.  
  53.     public void onCreate(Bundle savedInstanceState)
  54.  
  55.     {
  56.  
  57.         super.onCreate(savedInstanceState);
  58.  
  59.        
  60.  
  61.         gestureScanner = new GestureDetector(this);
  62.  
  63.         paint = new Paint();
  64.  
  65.        
  66.  
  67.         res = getResources();
  68.  
  69.         bmp = BitmapFactory.decodeResource(res, R.drawable.pic);
  70.  
  71.         adapt = Bitmap.createBitmap(bmp);
  72.  
  73.              
  74.  
  75.         main = new MyView(this);        
  76.  
  77.         setContentView(main,new ViewGroup.LayoutParams(800,600));
  78.  
  79.     }
  80.  
  81.    
  82.  
  83.     @Override
  84.  
  85.     public boolean onTouchEvent(MotionEvent me)
  86.  
  87.     {
  88.  
  89.         return gestureScanner.onTouchEvent(me);
  90.  
  91.     }
  92.  
  93.    
  94.  
  95.     @Override
  96.  
  97.     public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
  98.  
  99.     {
  100.  
  101.         main.handleScroll(distanceX,distanceY);
  102.  
  103.         return true;
  104.  
  105.     }
  106.  
  107.    
  108.  
  109.     ////////////////////
  110.  
  111.     ///////////////////
  112.  
  113.     //////////////////
  114.  
  115.     @Override
  116.  
  117.     public boolean onDown(MotionEvent e)
  118.  
  119.     {
  120.  
  121.         return true;
  122.  
  123.     }
  124.  
  125.    
  126.  
  127.     @Override
  128.  
  129.     public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
  130.  
  131.     {
  132.  
  133.         return true;
  134.  
  135.     }
  136.  
  137.    
  138.  
  139.     @Override
  140.  
  141.     public void onLongPress(MotionEvent e){    }
  142.  
  143.    
  144.  
  145.     @Override
  146.  
  147.     public void onShowPress(MotionEvent e) {   }    
  148.  
  149.    
  150.  
  151.     @Override
  152.  
  153.     public boolean onSingleTapUp(MotionEvent e)    
  154.  
  155.     {
  156.  
  157.         return true;
  158.  
  159.     }
  160.  
  161.     ////////////////////
  162.  
  163.     ///////////////////
  164.  
  165.     //////////////////
  166.  
  167.    
  168.  
  169.     class MyView extends View
  170.  
  171.     {
  172.  
  173.         public MyView(Context context)
  174.  
  175.         {
  176.  
  177.                 super(context);
  178.  
  179.         }
  180.  
  181.        
  182.  
  183.         @Override
  184.  
  185.         protected void onDraw(Canvas canvas)
  186.  
  187.         {
  188.  
  189.                 canvas.drawBitmap(adapt, 0, 0, paint);
  190.  
  191.         }
  192.  
  193.        
  194.  
  195.         public void handleScroll(float distX, float distY)
  196.  
  197.         {
  198.  
  199.                 // X-Axis ////////////////////////////////
  200.  
  201.                
  202.  
  203.                 if(distX > 6.0)
  204.  
  205.                 {
  206.  
  207.                         if(scrollX < 460)
  208.  
  209.                         {
  210.  
  211.                                 scrollX += 15;
  212.  
  213.                         }
  214.  
  215.                 }
  216.  
  217.                 else if(distX < -6.0)
  218.  
  219.                 {
  220.  
  221.                         if(scrollX >= 15)
  222.  
  223.                         {
  224.  
  225.                                 scrollX -= 15;
  226.  
  227.                         }
  228.  
  229.                 }
  230.  
  231.                 ////////////////////////////////////////////
  232.  
  233.                        
  234.  
  235.                 // Y-AXIS //////////////////////////////////
  236.  
  237.                 if(distY > 6.0)
  238.  
  239.                 {
  240.  
  241.                         if(scrollY < 100)
  242.  
  243.                         {
  244.  
  245.                                 scrollY += 15;
  246.  
  247.                         }
  248.  
  249.                 }
  250.  
  251.                 else if(distY < -6.0)
  252.  
  253.                 {
  254.  
  255.                         if(scrollY >= 15)
  256.  
  257.                         {
  258.  
  259.                                 scrollY -= 15;
  260.  
  261.                         }
  262.  
  263.                 }              
  264.  
  265.                 ////////////////////////////////////////////
  266.  
  267.                
  268.  
  269.                 if((scrollX <= 480) && (scrollY <= 120))
  270.  
  271.                 {
  272.  
  273.                         adapt = Bitmap.createBitmap(bmp, scrollX, scrollY, 320, 480);                  
  274.  
  275.                         invalidate();
  276.  
  277.                 }
  278.  
  279.         }
  280.  
  281.     }
  282.  
  283. }
Parsed in 0.043 seconds, using GeSHi 1.0.8.4
User avatar
Danuubz
Experienced Developer
Experienced Developer
 
Posts: 78
Joined: Wed Dec 19, 2007 10:44 pm
Location: Germany

Top

Postby ravi » Thu Nov 13, 2008 12:16 am

Thanks for the tutorial, it was helpful to me!
ravi
Freshman
Freshman
 
Posts: 8
Joined: Tue Nov 04, 2008 11:27 pm

Help

Postby weldrian » Tue Dec 09, 2008 9:12 am

Can you please help me solve the problem ?
Please.please refer the pic below!
Attachments
1.png
1.png (104.12 KiB) Viewed 58110 times
weldrian
Junior Developer
Junior Developer
 
Posts: 23
Joined: Tue Dec 09, 2008 1:30 am

Re: Help

Postby jinez » Tue Dec 09, 2008 8:25 pm

hello weldrian!

I think ur package name in code is not match with ur package name.

Ur package name is "com.a.a", but "de.horazontalscroll" is package name in ur code.

try to fix "de.horazontalscroll" to "com.a.a"
jinez
Once Poster
Once Poster
 
Posts: 1
Joined: Tue Dec 09, 2008 8:14 pm

Postby Danuubz » Fri Dec 12, 2008 4:52 pm

Additonally you have to delete 'import de.horizontalscroll.R'.
Sticky Note Cork&Orc [Android Market] : http://www.youtube.com/watch?v=ewWaquAwZQY
User avatar
Danuubz
Experienced Developer
Experienced Developer
 
Posts: 78
Joined: Wed Dec 19, 2007 10:44 pm
Location: Germany

another problem

Postby weldrian » Fri Dec 12, 2008 4:55 pm

hi man,

i hav solve the package problem, but i cant see anything on my picture folder.
i think you have to teach me how to upload or put pic on the emulator.

what i mean is, when i compile to the emulator, there have no pic showing on the picture folder,
actually what i m trying to do is..

1: put pic on the folder
2: zoom in, zoom out
3: slider for next pic
4: rotating.

do you think possible? can you do it? can you teach me?
weldrian
Junior Developer
Junior Developer
 
Posts: 23
Joined: Tue Dec 09, 2008 1:30 am

Top

Postby Danuubz » Fri Dec 12, 2008 7:29 pm

Hello,

Generally it is possible. To implement step 2-4 may need some time. I'm rather busy with other projects, so currently I cannot make these steps for you.

Loading a picture into the app should be no problem:
1.) Put the image into ProjectFolder/res/drawable/
2.) Now you load it with bmp = BitmapFactory.decodeResource(res, R.drawable.pic);

if the picture has the name other.jpg then you load it with
bmp = BitmapFactory.decodeResource(res, R.drawable.other);

3.) my example is made for a picture sized 800x600. If you would like to take one with other size, you need to adapt the code on several places.
Sticky Note Cork&Orc [Android Market] : http://www.youtube.com/watch?v=ewWaquAwZQY
User avatar
Danuubz
Experienced Developer
Experienced Developer
 
Posts: 78
Joined: Wed Dec 19, 2007 10:44 pm
Location: Germany

Thank you

Postby cdspace » Thu Dec 18, 2008 1:26 am

Thank you so much for this. I've been trying to figure this out for a week. This is exactly what I've been trying to do.
The Code Demon Rises
cdspace
Once Poster
Once Poster
 
Posts: 1
Joined: Thu Dec 18, 2008 1:20 am

Postby MrSnowflake » Thu Dec 18, 2008 1:52 am

You should have come here earlier :).
User avatar
MrSnowflake
Moderator
Moderator
 
Posts: 1439
Joined: Sat Feb 16, 2008 3:11 pm
Location: Flanders, Belgium

thx

Postby weldrian » Fri Dec 19, 2008 8:02 am

hey all,

when i compile to the emulator, the system show," the app close unexpectedly,"
but is ok, i will try to fingure out what is the problem. Thx for your soure.

now i m learning zoom in and zoom out!
weldrian
Junior Developer
Junior Developer
 
Posts: 23
Joined: Tue Dec 09, 2008 1:30 am

Postby pjv » Sat Jan 24, 2009 12:58 pm

I've concocted a version of ScrollView that also does horizontal scrolling. It works quite well when containing only one TextView but was NOT tested apart from that. Probably still has many bugs, but at least it's a starting point to improve on for anyone facing the same problem of the only-vertically scrolling ScrollView. Code is here: http://bazaar.launchpad.net/~pjv/androi ... lView.java.
pjv
Developer
Developer
 
Posts: 39
Joined: Tue Aug 19, 2008 7:11 pm

Cleaned up version

Postby wormhole009 » Sat Dec 19, 2009 11:53 pm

Here's a little more cleaned up version (and works for the Droid), but still needs work. The package visibility and lack of getter/setter is because of Android's crappy compiler (see their "Performance" dev page).

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2.  
  3.  
  4. import android.app.Activity;
  5.  
  6. import android.content.Context;
  7.  
  8. import android.graphics.Bitmap;
  9.  
  10. import android.graphics.BitmapFactory;
  11.  
  12. import android.graphics.Canvas;
  13.  
  14. import android.graphics.Paint;
  15.  
  16. import android.os.Bundle;
  17.  
  18. import android.util.Log;
  19.  
  20. import android.view.Display;
  21.  
  22. import android.view.GestureDetector;
  23.  
  24. import android.view.MotionEvent;
  25.  
  26. import android.view.View;
  27.  
  28. import android.view.WindowManager;
  29.  
  30. import android.view.GestureDetector.OnGestureListener;
  31.  
  32. import android.view.ViewGroup.LayoutParams;
  33.  
  34.  
  35.  
  36. public class Timeline extends Activity {
  37.  
  38.    
  39.  
  40.    ScrollableImageView scrollImageView;
  41.  
  42.    
  43.  
  44.    @Override
  45.  
  46.    public void onCreate(Bundle savedInstanceState) {
  47.  
  48.       super.onCreate(savedInstanceState);
  49.  
  50.      
  51.  
  52.       WindowManager w = getWindowManager();
  53.  
  54.       Display d = w.getDefaultDisplay();
  55.  
  56.      
  57.  
  58.       scrollImageView = new ScrollableImageView(this,
  59.  
  60.             BitmapFactory.decodeResource(getResources(), R.drawable.rocks),
  61.  
  62.             d.getWidth(), d.getHeight(),
  63.  
  64.             null);
  65.  
  66.       setContentView(scrollImageView);
  67.  
  68.    }
  69.  
  70.    
  71.  
  72.    public boolean onTouchEvent(MotionEvent event) {
  73.  
  74.       return scrollImageView.getGestureScanner().onTouchEvent(event);
  75.  
  76.    }
  77.  
  78.    
  79.  
  80.    ////
  81.  
  82.    ////
  83.  
  84.  
  85.  
  86.    class ScrollableImageView extends View {
  87.  
  88.      
  89.  
  90.       int scrollRate = 40;
  91.  
  92.      
  93.  
  94.       int scrollX = 0;
  95.  
  96.      
  97.  
  98.       int scrollY = 0;
  99.  
  100.      
  101.  
  102.       boolean scrollHorizontalEnabled = true;
  103.  
  104.      
  105.  
  106.       boolean scrollVerticalEnabled = true;
  107.  
  108.      
  109.  
  110.       ////
  111.  
  112.      
  113.  
  114.       Bitmap image;
  115.  
  116.      
  117.  
  118.       Bitmap bufferImage;
  119.  
  120.      
  121.  
  122.       int maxWidth;
  123.  
  124.      
  125.  
  126.       int maxHeight;
  127.  
  128.      
  129.  
  130.       int pictureWidth;
  131.  
  132.      
  133.  
  134.       int pictureHeight;
  135.  
  136.      
  137.  
  138.       ////
  139.  
  140.      
  141.  
  142.       Paint paint;
  143.  
  144.      
  145.  
  146.       GestureDetector gestureScanner;
  147.  
  148.      
  149.  
  150.       ////
  151.  
  152.       ////
  153.  
  154.  
  155.  
  156.       public ScrollableImageView(Context context, Bitmap image, int width,
  157.  
  158.             int height, Paint paint) {
  159.  
  160.          super(context);
  161.  
  162.          this.image = image;
  163.  
  164.          this.paint = paint;
  165.  
  166.          
  167.  
  168.          bufferImage = Bitmap.createBitmap(image);
  169.  
  170.          
  171.  
  172.          calculateSize(width, height);
  173.  
  174.          createGestureListener();
  175.  
  176.       }
  177.  
  178.      
  179.  
  180.       public ScrollableImageView(Context context, Bitmap image,
  181.  
  182.             int width, int height, Paint paint,
  183.  
  184.             boolean scrollHorizontal, boolean scrollVertical) {
  185.  
  186.          super(context);
  187.  
  188.          this.image = image;
  189.  
  190.          this.paint = paint;
  191.  
  192.          this.scrollHorizontalEnabled = scrollHorizontal;
  193.  
  194.          this.scrollVerticalEnabled = scrollVertical;
  195.  
  196.          
  197.  
  198.          bufferImage = Bitmap.createBitmap(image);
  199.  
  200.          
  201.  
  202.          calculateSize(width, height);
  203.  
  204.          createGestureListener();
  205.  
  206.       }
  207.  
  208.      
  209.  
  210.       protected void calculateSize(int width, int height) {
  211.  
  212.          
  213.  
  214.          //picture size
  215.  
  216.          pictureWidth = image.getWidth();
  217.  
  218.          pictureHeight = image.getHeight();
  219.  
  220.          
  221.  
  222.          //window size
  223.  
  224.          maxWidth = Math.min(pictureWidth, width);
  225.  
  226.          maxHeight = Math.min(pictureHeight, height);
  227.  
  228.          
  229.  
  230.          //layout size
  231.  
  232.          setLayoutParams(new LayoutParams(pictureWidth, pictureHeight));
  233.  
  234.       }
  235.  
  236.      
  237.  
  238.       protected void createGestureListener(){
  239.  
  240.          setGestureScanner(new GestureDetector(new OnGestureListener() {
  241.  
  242.            
  243.  
  244.             public boolean onScroll(MotionEvent event1, MotionEvent event2,
  245.  
  246.                   float distanceX, float distanceY) {
  247.  
  248.                handleScroll(distanceX, distanceY);
  249.  
  250.                return true;
  251.  
  252.             }
  253.  
  254.  
  255.  
  256.             public boolean onDown(MotionEvent event) {
  257.  
  258.                return true;
  259.  
  260.             }
  261.  
  262.            
  263.  
  264.             public boolean onFling(MotionEvent event1, MotionEvent event2,
  265.  
  266.                   float velocityX, float velocityY) {
  267.  
  268.                return true;
  269.  
  270.             }
  271.  
  272.  
  273.  
  274.             public void onLongPress(MotionEvent event) {
  275.  
  276.                //do nothing
  277.  
  278.             }
  279.  
  280.  
  281.  
  282.             public void onShowPress(MotionEvent event) {
  283.  
  284.                //do nothing
  285.  
  286.             }
  287.  
  288.  
  289.  
  290.             public boolean onSingleTapUp(MotionEvent event) {
  291.  
  292.                return true;
  293.  
  294.             }
  295.  
  296.          }));
  297.  
  298.       }
  299.  
  300.  
  301.  
  302.       @Override
  303.  
  304.       protected void onDraw(Canvas canvas) {
  305.  
  306.          canvas.drawBitmap(bufferImage, 0, 0, paint);
  307.  
  308.       }
  309.  
  310.  
  311.  
  312.       protected void handleScroll(float distX, float distY) {
  313.  
  314.          
  315.  
  316.          int maxScrollX = Math.max(pictureWidth - maxWidth, 0);
  317.  
  318.          int maxScrollY = Math.max(pictureHeight - maxHeight, 0);
  319.  
  320.          
  321.  
  322.          //X-Axis
  323.  
  324.          if(scrollHorizontalEnabled){
  325.  
  326.             if (distX > 6.0) {
  327.  
  328.                if (scrollX < maxScrollX - scrollRate) {
  329.  
  330.                   scrollX += scrollRate;
  331.  
  332.                }
  333.  
  334.                else {
  335.  
  336.                   scrollX = maxScrollX;
  337.  
  338.                }
  339.  
  340.             } else if (distX < -6.0) {
  341.  
  342.                if (scrollX >= scrollRate) {
  343.  
  344.                   scrollX -= scrollRate;
  345.  
  346.                }
  347.  
  348.                else {
  349.  
  350.                   scrollX = 0;
  351.  
  352.                }
  353.  
  354.             }
  355.  
  356.          }
  357.  
  358.  
  359.  
  360.          //Y-AXIS
  361.  
  362.          if(scrollVerticalEnabled){
  363.  
  364.             if (distY > 6.0) {
  365.  
  366.                if (scrollY < maxScrollY - scrollRate) {
  367.  
  368.                   scrollY += scrollRate;
  369.  
  370.                }
  371.  
  372.                else {
  373.  
  374.                  
  375.  
  376.                }
  377.  
  378.             } else if (distY < -6.0) {
  379.  
  380.                if (scrollY >= scrollRate) {
  381.  
  382.                   scrollY -= scrollRate;
  383.  
  384.                }
  385.  
  386.                else {
  387.  
  388.                   scrollY = 0;
  389.  
  390.                }
  391.  
  392.             }
  393.  
  394.          }
  395.  
  396.          
  397.  
  398.          //Swap image
  399.  
  400.          if ((scrollX <= maxWidth) && (scrollY <= maxHeight)) {
  401.  
  402.             swapImage();
  403.  
  404.             invalidate();
  405.  
  406.          }
  407.  
  408.       }
  409.  
  410.      
  411.  
  412.       protected void swapImage() {
  413.  
  414.          bufferImage = Bitmap.createBitmap(image, scrollX, scrollY,
  415.  
  416.                maxWidth, maxHeight);
  417.  
  418.       }
  419.  
  420.  
  421.  
  422.       /**
  423.  
  424.        * @return the gestureScanner
  425.  
  426.        */
  427.  
  428.       public GestureDetector getGestureScanner() {
  429.  
  430.          return gestureScanner;
  431.  
  432.       }
  433.  
  434.  
  435.  
  436.       /**
  437.  
  438.        * @param gestureScanner the gestureScanner to set
  439.  
  440.        */
  441.  
  442.       public void setGestureScanner(GestureDetector gestureScanner) {
  443.  
  444.          this.gestureScanner = gestureScanner;
  445.  
  446.       }
  447.  
  448.    }
  449.  
  450. }
  451.  
  452.  
Parsed in 0.058 seconds, using GeSHi 1.0.8.4
wormhole009
Once Poster
Once Poster
 
Posts: 1
Joined: Sat Dec 19, 2009 11:38 pm

Postby alejo » Wed Mar 31, 2010 9:14 am

Hi there,

I'm quite a newbie here, so I'm still playing with the basics... trying to figure out how to create this and that... but I fail to make this code work smoothly.

I'm trying this with an image which is higher than wider, and the lower part of the image gets cut.
The second bug is related with the scrolling action, it stops working after a few taps on screen. Could this be related with the lack of response to the "long press"?

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

Postby pskink » Wed Mar 31, 2010 9:49 am

alejo wrote:Hi there,

I'm quite a newbie here, so I'm still playing with the basics... trying to figure out how to create this and that... but I fail to make this code work smoothly.

I'm trying this with an image which is higher than wider, and the lower part of the image gets cut.
The second bug is related with the scrolling action, it stops working after a few taps on screen. Could this be related with the lack of response to the "long press"?

Thank you


see this (it scrolls, flings/swipes and zooms): viewtopic.php?p=39071#39071

download Scroll.tar.gz - its complete eclipse project
pskink
pskink
Master Developer
Master Developer
 
Posts: 719
Joined: Mon Nov 24, 2008 3:49 pm

Postby alejo » Wed Mar 31, 2010 10:07 am

Ah!! Ok, thank you,

I'll try it right now.
alejo
Junior Developer
Junior Developer
 
Posts: 10
Joined: Wed Mar 31, 2010 9:08 am

Top
Next

Return to Advanced Tutorials

Who is online

Users browsing this forum: No registered users and 2 guests