B4A Library TouchImageView

TouchImageView is an updated version of ImageView.
It adds support for touch events - drag and pinch zoom.

On devices with an Android version older than Eclair 2.0 and on devices without multitouch support only drag will be supported.
The same also applies when using the emulator.


Reference

Events:
TouchImageView generates no events.
Note however that the Click and LongClick events generated by the standard ImageView WILL be generated if the TouchImageView TouchEnabled property is False.
If TouchEnabled is set to True then the standard Click and LongClick events will NOT be generated.

Methods and properties:

CreateLog

Creates log entries with details about the current state of the TouchImageView, for debugging purposes:

** TouchImageView.CreateLog **
Original image: width = 962, height = 962
Scaled image: width = 294, height = 294
Translate position: x = 172, y = 346
ScaleX = 0.30614918, ScaleY = 0.30614918

MinScale As Float

Get or set the minimum scale that the image can be reduced by (zoomed out).
Default MinScale is 0.5.

B4X:
TouchImageView1.MinScale = 0.25

MaxScale As Float

Get or set the maximum scale that the image can be enlarged by (zoomed in).
Default MaxScale is 2.5.

B4X:
TouchImageView1.MaxScale = 3.75

GetScaleRect As anywheresoftware.b4a.objects.drawable.CanvasWrapper.RectWrapper

Returns a Rect that describes the current scale and position of the image.
You can get use this ScaleRect to restore a TouchImageView state on orientation change.

B4X:
Dim ScaleRect As Rect
ScaleRect = TouchImageView1.GetScaleRect

SetScaleRect (Rect as android.graphics.Rect, String as ScaleToFit)

Scale and position the image to the area of the TouchImageView defined by ScaleRect.
ScaleToFit controls how the image should be aligned in the Rect:

"CENTER" - Center and maximise the image to fit the Rect maintaining the aspect ratio.
"END" - Maximise the image to fit the Rect maintaining the aspect ratio, align the image with the bottom and right edges of the Rect.
"FILL" - Maximise the image to completely fill the Rect, the aspect ratio may not be maintained.
"START" - Maximise the image to fit the Rect maintaining the aspect ratio, align the image with the top and left edges of the Rect.

Note that if as a result of fitting the image to the Rect, the image has been scaled less than the current MinScale value then MinScale will be set to the current scale.
Likewise if when fitting the image to the Rect, the image has been scaled more than the current MaxScale value then MaxScale will be set to the current scale.

Documentation for the B4A Rect can be found here: Basic4android - Drawing (Core)
Documentation for Android ScaleToFit can be found here: Matrix.ScaleToFit

Example to position and scale the image so that it centers within a rectangle Left 20dip, Top 30dip, Right 100dip, Bottom 120dip, maximised but maintains it's aspect ratio:

B4X:
Dim ScaleRect As Rect
ScaleRect.Initialize(20dip, 30dip, 100dip, 120dip)
TouchImageView1.SetScaleRect(ScaleRect, "CENTER")

TouchEnabled as Boolean

Get or set whether touch events are currently enabled in the TouchImageView.

If touch events are enabled then the TouchImageView will NOT generate the standard ImageView Click and LongClick events.
These standard ImageView events will however be generated if touch events are NOT enabled.

TranslatePadding As Int

Get or set the minimum number of pixels that the image will always display within the TouchImageView.
Default TranslatePadding is 10 pixels - the image can not be dragged out of visibility, at least 10 pixels of width and/or height will always be visible.

B4X:
TouchImageView1.TranslatePadding = 50

I couldn't decide whether to implement setter and getter methods for the translate position and zoom scale - methods that would enable you to programmatically pan and zoom the image.
If anyone wants such methods then make a post in this thread and i'll see what i can do.


All other methods and properties of TouchImageView are inherited from the standard ImageView.
Documentation for the standard ImageView can be found here: Basic4android - Views (Core)

The attached demo shows basic usage and how to save and restore the TouchImageView state on orientation change.

TouchImageView updated to version 2.00, version 2.00 is not compatible with previous versions.
Methods and properties have changed.
Click here to read more


Martin.
 

Attachments

  • TouchImageView_v1_1.zip
    177.8 KB · Views: 2,105
  • TouchImageView_v_2_00.zip
    200.9 KB · Views: 4,498
Last edited:

Swissmade

Well-Known Member
Licensed User
Longtime User

warwound

Expert
Licensed User
Longtime User
Yes the TouchImageView certainly has a canvas - it's the canvas that your image is drawn on when you drag or zoom it.

Pass an instance of a TouchImageView to the Sub viewAsBitmap (aView As View) As Bitmap that's found in the post i linked to in my previous post and (in theory!) it should return the Bitmap you require.

Martin.
 

Swissmade

Well-Known Member
Licensed User
Longtime User
Yes the TouchImageView certainly has a canvas - it's the canvas that your image is drawn on when you drag or zoom it.

Pass an instance of a TouchImageView to the Sub viewAsBitmap (aView As View) As Bitmap that's found in the post i linked to in my previous post and (in theory!) it should return the Bitmap you require.

Martin.

Thanks Martin will try this out.
Let you know when it is working.;)
 

Swissmade

Well-Known Member
Licensed User
Longtime User
Thanks Martin will try this out.
Let you know when it is working.;)

Hi Martin sorry for the late responds i'm very busy at the moment and just now I get the change to try this.
Its working like a charm. Many thanks for this.;);):)
 

SnowyDog

Member
Licensed User
Longtime User
Hello, it looks like the member Bitmap is not valid for version 2.00 of this library.

How should one specify an image for the TouchImageView?

For a standard ImageView I have always used the Bitmap member like this:-

B4X:
ImageView1.Bitmap=LoadBitmap(File.DirAssets, "luce.jpg")

What is the alternative for TouchImageView version 2.00?

Thanks
 

warwound

Expert
Licensed User
Longtime User
TouchImageView has these two methods which allow you to set the image and background image:

SetBackgroundImage (Bitmap1 As Bitmap)
SetBitmap (Bitmap1 As Bitmap)

Martin.
 

mitsusdev

Member
Licensed User
Longtime User
is it possible set the right corner of image is not major of 0 ?

i don't want that the right corner of image can be into the backgroud.
 

Attachments

  • Immagine.JPG
    Immagine.JPG
    22.5 KB · Views: 221

jyounger

Member
Licensed User
Longtime User
Hey Warwound,

Killer library. Works almost perfectly for my needs. I have the tiniest of requests that I wonder if it would not be too hard for you to implement. If I could just be able to get and set the top and left of the image inside the TouchImageView control without changing whatever scaling it is at currently, it would be so incredibly easy to use this for an infinite slippy map of my own local tiles. I don't want to have to set up a map tile server to be able to slide around a map and pinch to zoom. I am really fighting the control the way it is because there is something funny in the ScaleSrcRectToDestRect method. If, however, I could just move the already scaled image to any position I want programmatically, then I can use a canvas to paint my new tiles at the current pinched zoom level. The new proposed GetTopLeft method is required so that when I repaint the new tiles, I need to know how to offset the image with the proposed SetTopLeft method so that the entire image appears as though it is in the same place. I hope this is clear enough...

Let me know!
 

warwound

Expert
Licensed User
Longtime User
@jyounger

I'll take a look at this but won't have time today.
I'm away for a few days next week so it's likely to be next Thursday before i have time to give it a look.

Martin.
 

andrewj

Active Member
Licensed User
Longtime User
Hi,
I want to pan the image within the view under programmatic control. I have "sort of" got it working by modifying the TouchImageViewRect, and then calling ScaleSrcRectToDestRect, but as this re-scales the image it doesn't respond very well. Is there a simpler way of panning the viewport without re-scaling?
Thanks
Andrew
 

warwound

Expert
Licensed User
Longtime User
Hi,
I want to pan the image within the view under programmatic control. I have "sort of" got it working by modifying the TouchImageViewRect, and then calling ScaleSrcRectToDestRect, but as this re-scales the image it doesn't respond very well. Is there a simpler way of panning the viewport without re-scaling?
Thanks
Andrew

Have you tried using the GetScaleRect method, modifying the Rect returned by that method - change the Top and Left as required and then passing the Rect back to the library using the SetScaleRect method?

Or is this what you're trying and you're getting problems?

Martin.
 

andrewj

Active Member
Licensed User
Longtime User
Hi,
My Object doesn't have the two methods you've named. It has a GetDestRect() method, and no setters.
The library version reports as 2.00
How Do I get access to those methods?
Thanks
Andrew
 

warwound

Expert
Licensed User
Longtime User
Ah yes i was getting confused between the current and previous versions.

TouchImageView
Author:
Martin Pearman
Version: 2.11
  • TouchImageView
    Events:
    • Click (X As Int, Y As Int)
    • LongClick (X As Int, Y As Int)
    Methods:
    • BringToFront
    • CreateLog
      Creates log entries with details about the current state of the TouchImageView.
    • GetDestRect As RectWrapper
      Returns a Rect that describes the current scale and position of the image within the TouchImageView.
    • Initialize (EventName As String)
    • Invalidate
    • Invalidate2 (arg0 As Rect)
    • Invalidate3 (arg0 As Int, arg1 As Int, arg2 As Int, arg3 As Int)
    • IsInitialized As Boolean
    • PreScale (Scale As Float, PointX As Int, PointY As Int)
      Change the current image scale by Scale, centering the change on (X, Y).
    • RemoveView
    • RequestFocus As Boolean
    • ScaleSrcRectToDestRect (SrcRect As Rect, DestRect As Rect, ScaleToFit As String)
      Scale and position the area of the (foreground) image defined by SrcRect to the area of the TouchImageView defined by DestRect.
      ScaleToFit controls how the image should be aligned in the DestRect:
      CENTER - Center and maximise the image to fit the DestRect maintaining the aspect ratio.
      END - Maximise the image to fit the DestRect maintaining the aspect ratio, align the image with the bottom and right edges of the DestRect.
      FILL - Maximise the image to completely fill the DestRect, the aspect ratio may not be maintained.
      START - Maximise the image to fit the DestRect maintaining the aspect ratio, align the image with the top and left edges of the DestRect.
    • SendToBack
    • SetBackgroundImage (arg0 As Bitmap)
    • SetBitmap (aBitmap As Bitmap)
      Set the (foreground) image.
    • SetLayout (arg0 As Int, arg1 As Int, arg2 As Int, arg3 As Int)
    Properties:
    • Background As Drawable
    • BackgroundImage As Bitmap
      Get or Set the BackgroundImage.
    • ClickPeriod As Int
      Get or Set the ClickPeriod in milliseconds.
      The ClickPeriod is the threshold between a click being treated as a Click or a LongClick.
      The default ClickPeriod is 200 milliseconds.
    • Color As Int [write only]
    • Enabled As Boolean
    • Gravity As Int
      Get or Set the Gravity of the BackgroundImage.
    • Height As Int
    • Left As Int
    • MaxScale As Float
      Get or set the maximum scale that the image can be enlarged by (zoomed in).
      Default MaxScale is 1.5.
    • MinScale As Float
      Get or set the minimum scale that the image can be reduced by (zoomed out).
      Default MinScale is 0.5.
    • ScaleX As Float [read only]
      Get the factor which the image is currently scaled by on it's X axis.
    • ScaleY As Float [read only]
      Get the factor which the image is currently scaled by on it's Y axis.
    • Tag As Object
    • Top As Int
    • TouchEnabled As Boolean
      Get or Set whether touch events are enabled.
    • TransformedBitmap As BitmapWrapper [read only]
      Get the transformed image as a Bitmap.
    • TranslatePadding As Int [write only]
    • TranslatePaddingX As Int
      Get or set the minimum number of pixels that the image will always display within the TouchImageView.
      Default TranslatePadding is 64 pixels.
      The image can not be dragged out of visibility, at least 64 pixels of width and height will always be visible.
    • TranslatePaddingY As Int
    • Visible As Boolean
    • Width As Int

I see no methods there that will help you and if you look back at the last few 'feature requests' in this thread you'll see requests that have no solution either.
I wrote this library when android 2.? was the current version - that's way back to Eclair and Froyo time, a long while ago.
The library uses dated and clumsy techniques to achieve it's functions and isnt code that can be easily updated.

The library would benefit from a rewrite using features available in newer versions of android.

I'll have a look though and see whether any updates can be made over the weekend.

Martin.
 

andrewj

Active Member
Licensed User
Longtime User
Dear Martin,
Thanks for the update.

It would be great if we can resolve this, because your library supports the scaling features I need, and I'm also hopeful that I can get a neat image switching model working using the "Background Image" concept.

To meet my requirements all I think you need to do is implement a "SetDestRec" companion to "GetDestRec". This would allow me to pan within the image. Is there any chance you could try this before doing anything more complicated?
Thanks
Andrew
 

warwound

Expert
Licensed User
Longtime User
Can you test the attached update?
I've added a single new method:

PostTranslate(X As Float, Y as Float)

This will move the image by (X, Y), for example:

B4X:
MyTouchImageView.PostTranslate(-10, 40)

Will move the image 10 pixels to the left and 40 pixels down.
This is untested - i'm assuming that the pixel amounts are not relative to the image's current scale.
That is i'm assuming that a value of 40 will move the image by 40 pixels regardless of whether the image is scaled to 50% or 150% etc.

Martin.
 

Attachments

  • TouchImageView-PostTranslate.zip
    18.6 KB · Views: 740

andrewj

Active Member
Licensed User
Longtime User
Dear Martin,
Thanks for the very quick work!
This looks very good, although it took a slight adjustment to get it working "the right way around"...
I'll test more fully later, but thanks again.
Andrew
 

warwound

Expert
Licensed User
Longtime User
OK.
Keep this thread updated with your results and if it works as expected then i'll upload it as a 'proper' update.

Martin.
 
Top