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,098
  • TouchImageView_v_2_00.zip
    200.9 KB · Views: 4,489
Last edited:

Leni Berry

Active Member
Licensed User
Longtime User
hi,

Set touchimageview height and width same with screensize portrait.

can touchimageview (after i touch and zoom) do this :
1. if the picture width after zoom<=screenwidth then the image cannot drag left or right, but only drag up and down.
2. if the picture width after > screenwidth then image can drag left or right and also can drag up and down.

rgds,

LB
 

JohnC

Expert
Licensed User
Longtime User
How could I change the white crop outline to be round and then return a round image?
 

agraham

Expert
Licensed User
Longtime User
This is wonderful! It is the last capability I need to implement to port my Ordnance Survey search and map display app to B4A.

The demo makes it look bad by implementing a re-scale on a Long_Click which happens when you are dragging and pinching and causes unexpected resizing of the image. In fact I rejected this as buggy the first time round but looked closer when I didn't find an alternative. Remove the Long_Click event and it works perfectly.

It also seems to be able to deal responsively with reasonably large images (10,000 x 10,000 pixels) which my maps are. I think that I can display my maps with this rather than opening a separate image viewer and, better, it allows me to pre-zoom and pre-position the map at the road or place that the user searched for.

It doesn't seem to cope well with rotating the display when displaying these large images after which it exhibits very long delays to input and hangs when trying to exit. This seems to be overcome by limiting the Activity orientation to Portrait which is of no consequence in my app.
 

agraham

Expert
Licensed User
Longtime User
To correct my comments about problems rotating a device with a large image. The problem is of course not with this library but is the perennial large un-managed bitmaps not being recycled and running out of memory problem. It behaves properly with code like the following that recycles the bitmap on Pause and reinstates it on Resume. In the real app I will get more sophisticated and save and restore the centre point of the image and its current zoom.

B4X:
Sub Activity_Resume
   If Bitmap1 = Null Then
       Bitmap1.Initialize(File.DirRootExternal, Filename)
       TouchImageView1.SetBitmap(Bitmap1)       
   End If
End Sub

Sub Activity_Pause (UserClosed As Boolean)
   ' avoid hangs on rotation caused by large bitmaps
   Dim Obj1 As Reflector
   Obj1.Target = Bitmap1 ' the unwanted Bitmap
   Obj1.RunMethod("recycle")
   Bitmap1 = Null
End Sub
 

agraham

Expert
Licensed User
Longtime User
I have discovered that this library does not display the image if android:targetSdkVersion is set to anything greater that 13 in the manifest.

In the fragment below the logs indicate the expected size of both bitmap and view but the image is visible only if target SDK is 13 or lower.
B4X:
    Bitmap1.Initialize(File.DirRootExternal, Filename)
   TouchImageView1.SetBitmap(Bitmap1)
   Log("bWidth = " & Bitmap1.Width & " bHeight = " & Bitmap1.Height)
   Log("tWidth = " & TouchImageView1.Width & " tHeight = " & TouchImageView1.Height)
   SourceImageRect.Initialize(Bitmap1.Width/4, Bitmap1.Height/4, Bitmap1.Width/2, Bitmap1.Height/2)
   TouchImageViewRect.Initialize(0, 0, TouchImageView1.Width, TouchImageView1.Height)
   TouchImageView1.ScaleSrcRectToDestRect(SourceImageRect, TouchImageViewRect, "CENTER")   '   make string a static constant in library
As it happens this is not really a problem (yet) for the app I am presently developing as it will always be sideloaded. However I like the simplicity of this control and wonder if it can be update for later SDKs?
 
Top