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

bgsoft

Well-Known Member
Licensed User
Longtime User
Thank you very much for your answer, now what to do to avoid this memory error.

regards

Jesus
 

jiangws

Member
Licensed User
Longtime User
Thank for your sharing, it's useful!
 

romario11

Member
Licensed User
Longtime User
write file from TouchImageView

first of all, thanks you for all posts.
I have been very helpful

but i have a question

how i can, one time fix the image on base, write a file jpg or png from the TouchImageView area?

i think i could make a rect capture screen ¿?

took hours trying it
i need help :(
 

warwound

Expert
Licensed User
Longtime User
Try the attached update, i've added a new property to the TouchImageView TransformedBitmap.

The TransformedBitmap is the same size as the TouchImageView, i can find no way to get a Bitmap that is the same size as the scaled/transformed image when the image is smaller than the TouchImageView.

Here's some example code:

B4X:
Sub Process_Globals
   Dim SourceImageRect, TouchImageViewRect As Rect
End Sub

Sub Globals
   Dim TouchImageView1 As TouchImageView
End Sub

Sub Activity_Create(FirstTime As Boolean)
   Activity.AddMenuItem("Get transformed image", "GetTransformedImage")
   
   TouchImageView1.Initialize("TouchImageView1")
   Activity.AddView(TouchImageView1, 0, 0, 100%x, 100%y)
   
   TouchImageView1.MinScale=0.25         '   default is 0.5
   TouchImageView1.MaxScale=2            '   default is 1.5
   TouchImageView1.TranslatePadding=128dip   '   default is 64dip
   
   TouchImageView1.Gravity=Gravity.FILL
   TouchImageView1.SetBackgroundImage(LoadBitmap(File.DirAssets, "b4a_logo.png"))
   
   Dim Bitmap1 As Bitmap
   Bitmap1.Initialize(File.DirAssets, "cromer_pier.jpg")
   TouchImageView1.SetBitmap(Bitmap1)
   
   If FirstTime Then
      '   Rect parameters are: left, top, right, bottom
      SourceImageRect.Initialize(0, 0, Bitmap1.Width, Bitmap1.Height)
      TouchImageViewRect.Initialize(0, 0, TouchImageView1.Width, TouchImageView1.Height)
   End If
   
   '   if the scaling process scales the image to less than the current MinScale or more than the current MaxScale then MinScale or MaxScale will be adjusted
   TouchImageView1.ScaleSrcRectToDestRect(SourceImageRect, TouchImageViewRect, "CENTER")   '   make string a static constant in library
   
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)
   TouchImageViewRect=TouchImageView1.GetDestRect
End Sub

Sub GetTransformedImage_Click
   Dim TransformedImage As Bitmap
   TransformedImage=TouchImageView1.TransformedBitmap
   Dim OutputStream1 As OutputStream
   OutputStream1=File.OpenOutput(File.DirRootExternal, "transformed_image.jpg", False)
   TransformedImage.WriteToStream(OutputStream1, 70, "JPEG")
End Sub

The Sub GetTransformedImage_Click shows how to get the transformed image.

Martin.
 

Attachments

  • TouchImageView_v2_11.zip
    178.7 KB · Views: 473

basil99

Active Member
Licensed User
Longtime User
Hi, Warwound !
A great lib, thank you very much for it.

My humble wish is to have smth like FlingEventOff and FlingEventOn in Methods ( as I understand this event consumes internally in you lib atm ) and onFling in Events.

Is it possible ?

Thank you
 

warwound

Expert
Licensed User
Longtime User
Hi, Warwound !
A great lib, thank you very much for it.

My humble wish is to have smth like FlingEventOff and FlingEventOn in Methods ( as I understand this event consumes internally in you lib atm ) and onFling in Events.

Is it possible ?

Thank you

Can you explain more exactly what you require?

There is an existing property to enable or disable the touch event - that's the TouchEnabled property.

Or is the problem that the TouchImageView consumes a touch event and you want the touch event to propogate through to another View in your layout?

Martin.
 

basil99

Active Member
Licensed User
Longtime User
Thanks for the fast reply. Actually seems i need this:

Or is the problem that the TouchImageView consumes a touch event and you want the touch event to propogate through to another View in your layout?

Martin.

Let me explain. Atm "fling" and "drag" works in the same way with TIV - this events moves view rect. I need to keep "drag" option, it works perfect. But sometimes I need to detect "fling" on TIV and consume it in way i need.

Something similar to gallery app, when you can swith to next/previous pic with fling left or right

I'm working on my own implementation of this with gestures lib, but have a feeling i'm inventing a bycircle ) TIV saves me a lot of time, exept this fling issue

Thank you. Hope, I was clear
 

basil99

Active Member
Licensed User
Longtime User
Hello, Warwound !

I have another question rearding TIV.
I have a panel with no events and a TIV attached in the following way:

B4X:
TIVpanel.Initialize("")
TIVpanel.Color = Colors.Transparent

TIV.Initialize( "TIVclick" )
TIV.MinScale = 1.0   
TIV.MaxScale = 2.0         
TIV.TranslatePadding = 32dip         
TIV.Gravity = Gravity.FILL
TIVviewRect.Initialize(0, 0, 100%x, 100%y )
TIVpanel.AddView( TIV, 0,0, 100%x, 100%y )

and TIV click sub:

B4X:
Sub TIVclick_Click( X As Int, Y As Int)

   Log( "Click X=" & X & ", Y=" & Y )
   
End Sub

I notice, clicking event fires when i click the image, but no when i click somewhere outside. Is any chance to get X/Y for this case ?

Thank you
 

warwound

Expert
Licensed User
Longtime User
Not without a major re-write of the touch detection code.

A touch is discarded if it's not within the bounds of the image, it's essential to discard such touches so that a drag only occurs if the visible image is touched and dragged. (All touches outside of the image bounds are ignored).

Adding code to remember a touch outside of the image bounds and then deciding whether to raise a click event or not would not fit in with the existing code - and i'm afraid i don't have time to take on a re-write of the touch detection.

Martin.
 

YoungOne

New Member
Licensed User
Longtime User
Have you had time to look at a fix for long_click firing after a drag? I have an app that I'd like to use long_click for that also uses drag.

I could probably increase the time but people also drag things around quite a bit so I don't think that's an option. Nearly every time I drag, I also get a long_click.

Thanks for any help you can give!
 
Last edited:

Swissmade

Well-Known Member
Licensed User
Longtime User
Nice Library,
Just a question how can i save the View to a file so not the hole image but just the view.
What is the latest version?

Thanks for help
 
Top