B4A Library BetterImageView

This is an enhanced ImageView, closer to the standard Java ImageView, with two layers (foreground and background), a touch event, a scaletype setting (similar to gravity, but for the foreground), an alpha setting and a few functions to alter the colors.
I fixed the issue with the gravity of the B4A ImageView (since it is a property of bitmapdrawables, the setting was lost when the background was changed to another type of drawable; now, this setting is kept whatever may be the contents).
It is a custom view that you can add in the designer.

screenshot.jpg
scnsht2.jpg


v1.1:
- The background set in the designer is properly read now;
- Added five functions: AlterColors, ApplyColorFilter, ReduceColors, LoadScaledBitmap and LoadNinePatchDrawable;
- Added a new demo;
- Fixed an issue in the first demo with some screen resolutions.
 

Attachments

  • BetterImageView v1.1.zip
    132.8 KB · Views: 1,536
  • Java - BetterImageView.zip
    7 KB · Views: 378
Last edited:

Informatix

Expert
Licensed User
Longtime User
:) I'm saying, don't use background at all. Don't set the property. If you just drop the control on a panel, then in code set the bitmap (not backgroundbitmap) to something, it will just display a solid white area.

To get it to work this way, you must change the Drawable type to BitmapDrawable. Then whatever bitmap (not backgroundbitmap) you put on it will show.

In the first demo, replace :
B4X:
        BIV(i).Bitmap = LoadBitmap(File.DirAssets, "b4a_logo.png")
BIV(i).BackgroundBitmap = BIV(i).ReduceColors(BkgdBmp)
by
B4X:
        BIV(i).Bitmap = LoadBitmap(File.DirAssets, "b4a_logo.png")
Dim CD As ColorDrawable
CD.Initialize(Colors.Red, 0)
BIV(i).Background = CD
and you will see that you're wrong. And if you don't set the background, the background will take the color of the activity behind it, which is the expected behavior (the foreground has transparent parts).
 

BarryW

Active Member
Licensed User
Longtime User
Is there any way to get to rect of scaled image inside the betterimageview. thanks
 

BarryW

Active Member
Licensed User
Longtime User
i used to initailize a larger bitmap on my program then load it to your betterimageview with scaletype of SCALETYPE_FIT_CENTER
now i want to get the height and width of image inside your better imageview

Tnx
 

Informatix

Expert
Licensed User
Longtime User
i used to initailize a larger bitmap on my program then load it to your betterimageview with scaletype of SCALETYPE_FIT_CENTER
now i want to get the height and width of image inside your better imageview

Tnx
There's no property or function for that. You have to compute the new width and height yourself. It's a very easy computation (ratio width/height of the image * height of the imageview to get the width for example).
 

BarryW

Active Member
Licensed User
Longtime User
Where i can get the variable ratio?

Im confused in
(ratio width/height of the image * height of the imageview to get the width for example).

Can you post a sample?
Tnx
 

Informatix

Expert
Licensed User
Longtime User
Where i can get the variable ratio?

Im confused in
(ratio width/height of the image * height of the imageview to get the width for example).

Can you post a sample?
Tnx
It's very simple math:
scaled width = image view height * image width / image height
scaled height = image view width * image height / image width
You have to choose the right formula depending on the main orientation of the image.
 

BarryW

Active Member
Licensed User
Longtime User
Sir sorry but i still got a stretch imageview

bm.Initialize(Dir, FileName)
Dim scaled_width As Int = 100%y * bm.Width / bm.Height
Dim scaled_height As Int = 100%x * bm.Height / bm.Width
ImageView1.Height = scaled_height
ImageView1.Width = scaled_width
ImageView1.Bitmap = bm
 

Informatix

Expert
Licensed User
Longtime User
Sir sorry but i still got a stretch imageview

bm.Initialize(Dir, FileName)
Dim scaled_width As Int = 100%y * bm.Width / bm.Height
Dim scaled_height As Int = 100%x * bm.Height / bm.Width
ImageView1.Height = scaled_height
ImageView1.Width = scaled_width
ImageView1.Bitmap = bm
Seeing your code, I realize that I did not understand what you asked (and obviously, you did not understand my answer). So unless you give me clear explanations about what you're trying to do, I won't be able to help.
 

BarryW

Active Member
Licensed User
Longtime User
After inserting large image inside betterimageview i scaled it using SCALETYPE_CENTER_INSIDE

And the image is now like this...

I want to get the scaled height and width. How to do it?
 

Attachments

  • Height.png
    Height.png
    338.7 KB · Views: 194
  • Width.png
    Width.png
    160.1 KB · Views: 191

Informatix

Expert
Licensed User
Longtime User
After inserting large image inside betterimageview i scaled it using SCALETYPE_CENTER_INSIDE

And the image is now like this...

I want to get the scaled height and width. How to do it?
If I understand you well, my answer is still the same:
scaled width = image view height * image width / image height
scaled height = image view width * image height / image width
You have to choose the right formula depending on the main orientation of the image.
You probably did not pay attention to the last sentence of my advice. You have to change only one dimension of your ImageView, the one that is not sized as expected.
 

Phayao

Active Member
Licensed User
Longtime User
Hello,

I'm not sure if this is an issue about Betterimageview Library - anyhow I like to ask here:
I simply want to show a map on the screen and let the user click on several points which should be a path from a start to an endpoint.
The imageview-touchevent collects each click and stores the x/y data in an array.
So far, so good - but after 2 or 3 clicks, the application stops. The unfiltered log says:
" Skipped 54 frames! The application may be doing too much work on its main thread. "
Well, I have no clue which frames should be there and why the app is soo busy ?

Here is part of the code:

B4X:
Sub Globals
    Private pnlDraw, pnlFinish As Panel
    Private bmpDrawAll As Bitmap

    Private ivTargets As BetterImageView
    Private cv As Canvas
    Private trgPoints As Int = 0
    Type target(name As String,X(10) As Int,Y(10) As Int)
    Private targets As target
end sub

Sub Activity_Create(FirstTime As Boolean)
 
    Activity.LoadLayout("main")
    pnlFinish.Visible = False
    bmpDrawAll.Initialize(File.DirAssets,"map.gif")
 
    Start

End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub Start
    ' initialize counters:
    trgPoints = 0
    ' panel to draw on:
    pnlDraw.Initialize("")
    pnlDraw.Color = Colors.Transparent
    Activity.AddView(pnlDraw,0,0,100%x,90%y)
 
    cv.Initialize(pnlDraw)  ' new canvas
 
    Dim bmpPlus As BitmapPlus
    Dim bmpDraw As Bitmap
    bmpDraw = bmpPlus.createScaledBitmap(bmpDrawAll,100%x,90%y,True)
 
    ivTargets.Initialize("ivTargets")    ' new imageview
    ivTargets.Bitmap = bmpDraw
    Activity.AddView(ivTargets,0,0,100%x,90%y)
    ivTargets.SetLayout(0,0,bmpDraw.Width,bmpDraw.Height)
    ' initialize targets arrays:
    targets.initialize  
    Dim dia As InputDialog
    dia.InputType = dia.INPUT_TYPE_TEXT
    dia.Show("Name of the Target:","Target","OK","","",Null)
    If dia.Response = DialogResponse.POSITIVE Then targets.name = dia.Input
 
    ToastMessageShow("Start to mark waypoints", True)
End Sub

' Select target points:
Sub ivTargets_Touch(Action As Int, X As Double, Y As Double)
    pnl_info.Visible = True
    pnlDraw.BringToFront
    If Action = Activity.ACTION_DOWN Then
        Log("-----trgpoints: "&trgPoints)
       cv.DrawCircle(X,Y,8,Colors.Black,True,0)
        If trgPoints > 0 Then _ 
            cv.DrawLine(targets.X(trgPoints-1),targets.Y(trgPoints-1),X,Y,Colors.Blue,3)

        targets.X(trgPoints) = X    : targets.Y(trgPoints) = Y
        Log("*** target "&trgPoints&"  x/y: "&targets.X(trgPoints)&" / "&targets.Y(trgPoints))

        trgPoints = trgPoints + 1
    End If
End Sub

Any help is higly appreciated !

Chris
 
Last edited:

Informatix

Expert
Licensed User
Longtime User
Hello,

I'm not sure if this is an issue about Betterimageview Library - anyhow I like to ask here:
I simply want to show a map on the screen and let the user click on several points which should be a path from a start to an endpoint.
The imageview-touchevent collects each click and stores the x/y data in an array.
So far, so good - but after 2 or 3 clicks, the application stops. The unfiltered log says:
" Skipped 54 frames! The application may be doing too much work on its main thread. "
Well, I have no clue which frames should be there and why the app is soo busy ?

Here is part of the code:

B4X:
Sub Globals
    Private pnlDraw, pnlFinish As Panel
    Private bmpDrawAll As Bitmap

    Private ivTargets As BetterImageView
    Private cv As Canvas
    Private trgPoints As Int = 0
    Type target(name As String,X(10) As Int,Y(10) As Int)
    Private targets As target
end sub

Sub Activity_Create(FirstTime As Boolean)

    Activity.LoadLayout("main")
    pnlFinish.Visible = False
    bmpDrawAll.Initialize(File.DirAssets,"map.gif")

    Start

End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub Start
    ' initialize counters:
    trgPoints = 0
    ' panel to draw on:
    pnlDraw.Initialize("")
    pnlDraw.Color = Colors.Transparent
    Activity.AddView(pnlDraw,0,0,100%x,90%y)

    cv.Initialize(pnlDraw)  ' new canvas

    Dim bmpPlus As BitmapPlus
    Dim bmpDraw As Bitmap
    bmpDraw = bmpPlus.createScaledBitmap(bmpDrawAll,100%x,90%y,True)

    ivTargets.Initialize("ivTargets")    ' new imageview
    ivTargets.Bitmap = bmpDraw
    Activity.AddView(ivTargets,0,0,100%x,90%y)
    ivTargets.SetLayout(0,0,bmpDraw.Width,bmpDraw.Height)
    ' initialize targets arrays:
    targets.initialize 
    Dim dia As InputDialog
    dia.InputType = dia.INPUT_TYPE_TEXT
    dia.Show("Name of the Target:","Target","OK","","",Null)
    If dia.Response = DialogResponse.POSITIVE Then targets.name = dia.Input

    ToastMessageShow("Start to mark waypoints", True)
End Sub

' Select target points:
Sub ivTargets_Touch(Action As Int, X As Double, Y As Double)
    pnl_info.Visible = True
    pnlDraw.BringToFront
    If Action = Activity.ACTION_DOWN Then
        Log("-----trgpoints: "&trgPoints)
       cv.DrawCircle(X,Y,8,Colors.Black,True,0)
        If trgPoints > 0 Then _
            cv.DrawLine(targets.X(trgPoints-1),targets.Y(trgPoints-1),X,Y,Colors.Blue,3)

        targets.X(trgPoints) = X    : targets.Y(trgPoints) = Y
        Log("*** target "&trgPoints&"  x/y: "&targets.X(trgPoints)&" / "&targets.Y(trgPoints))

        trgPoints = trgPoints + 1
    End If
End Sub

Any help is higly appreciated !

Chris
If you replace the BetterImageView by an ImageView, do you have the same problem?
 

somed3v3loper

Well-Known Member
Licensed User
Longtime User
Why don't ChangeAlpha() and ChangeBackgroundAlpha have any effect ?
I am trying to make it transparent gradually but it does not seem to work for me .
 

susu

Well-Known Member
Licensed User
Longtime User
I have problem when using StartAppInAppB4AWrapper (link) with BetterImageView.

B4X:
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
main_showbanner (B4A line: 747)
autoBanner.addBannerWithPositionAndType(bannerPos
java.lang.ClassCastException: flm.b4a.betterimageview.BetterImageView cannot be cast to android.widget.RelativeLayout
    at com.startapp.android.publish.b4a.banner.BannerWrapper.addBannerWithPositionAndType(BannerWrapper.java:77)
    at my.app.net.main._showbanner(main.java:2662)
    at my.app.net.main._icon_click(main.java:2144)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:187)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:175)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:171)
    at anywheresoftware.b4a.objects.ViewWrapper$1.onClick(ViewWrapper.java:78)
    at android.view.View.performClick(View.java:4120)
    at android.view.View$PerformClick.run(View.java:17112)
    at android.os.Handler.handleCallback(Handler.java:615)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:4886)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
    at dalvik.system.NativeStart.main(Native Method)

Code of showBanner sub:
B4X:
Sub showBanner
    Dim autoBanner As Banner
    Dim bannerPositionToSet As BannerPosition
    Dim BannerType As BannerType
    autoBanner.addBannerWithPositionAndType(bannerPositionToSet.BOTTOM, BannerType.AUTOMATIC)
End Sub

StartApp Example code works fine.
If I don't call showBanner sub, everything works fine. I don't have a clue where's the problem. @Informatix , could you please help me? Thank you.
 

Informatix

Expert
Licensed User
Longtime User
I have problem when using StartAppInAppB4AWrapper (link) with BetterImageView.

B4X:
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
main_showbanner (B4A line: 747)
autoBanner.addBannerWithPositionAndType(bannerPos
java.lang.ClassCastException: flm.b4a.betterimageview.BetterImageView cannot be cast to android.widget.RelativeLayout
    at com.startapp.android.publish.b4a.banner.BannerWrapper.addBannerWithPositionAndType(BannerWrapper.java:77)
    at my.app.net.main._showbanner(main.java:2662)
    at my.app.net.main._icon_click(main.java:2144)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:187)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:175)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:171)
    at anywheresoftware.b4a.objects.ViewWrapper$1.onClick(ViewWrapper.java:78)
    at android.view.View.performClick(View.java:4120)
    at android.view.View$PerformClick.run(View.java:17112)
    at android.os.Handler.handleCallback(Handler.java:615)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:4886)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
    at dalvik.system.NativeStart.main(Native Method)

Code of showBanner sub:
B4X:
Sub showBanner
    Dim autoBanner As Banner
    Dim bannerPositionToSet As BannerPosition
    Dim BannerType As BannerType
    autoBanner.addBannerWithPositionAndType(bannerPositionToSet.BOTTOM, BannerType.AUTOMATIC)
End Sub

StartApp Example code works fine.
If I don't call showBanner sub, everything works fine. I don't have a clue where's the problem. @Informatix , could you please help me? Thank you.
In your log, you have:
flm.b4a.betterimageview.BetterImageView cannot be cast to android.widget.RelativeLayout
at com.startapp.android.publish.b4a.banner.BannerWrapper.addBannerWithPositionAndType(BannerWrapper.java:77)
That means a RelativeLayout is expected by addBannerWithPositionAndType, not an ImageView. I don't know why this library asks for a view that does not exist in B4A.
 

susu

Well-Known Member
Licensed User
Longtime User
Thanks @Informatix , it means I need to ask StartApp to fix their wrapper?
 
Top