B4A Library [B4X][XUI] ImageSlider

Status
Not open for further replies.

Erel

Administrator
Staff member
Licensed User
ImageSlider custom view is compatible with B4A, B4i and B4J.



Features:
  • Three transition types: horizontal, vertical and fade. Configured in the visual designer.
  • Images are centered and not distorted.
  • Next and previous images are cached.
  • Sliding gestures.
  • Flexible data source.
  • Cross platform.

Usage:

1. Add ImageSlider with the designer.
2. Set the number of images:
B4X:
ImageSlider1.NumberOfImages = 4
3. Implement the GetImage event. This is a resumable sub.
You should return a B4XBitmap based on the index.
B4X:
Sub ImageSlider1_GetImage (Index As Int) As ResumableSub
   Return xui.LoadBitmapResize(File.DirAssets, $"test_${Index + 1}.jpg"$, _
        ImageSlider1.WindowBase.Width, ImageSlider1.WindowBase.Height, True)
End Sub
In this example the images are loaded from the assets folder.

4. Call ImageSlider.NextImage or PrevImage.

A B4J project with the ImageSlider class: www.b4x.com/b4j/files/ImageSlider.zip

A B4A example where the http requests are made from the starter service is available here: https://www.b4x.com/android/forum/threads/how-to-prevent-the-second-activity-from-closing-when-the-slider-is-on.95779/#post-604705

Updates

V1.11 - Fixes the dot indicator offset.
V1.10 - adds a dot indicator and fixes a bug: https://www.b4x.com/android/forum/threads/b4x-xui-imageslider.87128/page-2#post-618398

The latest version is included in the B4J project.
 
Last edited:

Erel

Administrator
Staff member
Licensed User
Yes. You can either download the images in the GetImage event (this is why it is a resumable sub) or download all of them and keep them in a List and return the image from the list.
 

MarcoRome

Expert
Licensed User
"You can either download the images in the GetImage event "
Pls, can you write a little example
 

Sapta

Member
Licensed User
Hi @Erel,

I use this code for in B4A on Main Activity,
But why when open a new activity, sometimes closed and replaced with main activity again?
Is it because waiting to finish download its image, after that can open new activity?

And how the code if in collaboration with this (Download With Service)? I don't understand :D collaborating

B4X:
Sub TimerSlider_Tick
    ImageSlider1.NextImage
End Sub

Sub ImageSlider1_GetImage (Index As Int) As ResumableSub
    Dim j As HttpJob
    j.Initialize("", Me)
    j.Download(Urls.Get(Index))
    Log("Downloading: " & Urls.Get(Index))
    Wait For (j) JobDone(j As HttpJob)
    Dim x As B4XBitmap
    If j.Success Then
        x = j.GetBitmap
        x = x.Resize(ImageSlider1.WindowBase.Width, ImageSlider1.WindowBase.Height, True)
    End If
    j.Release
    Return x
End Sub

Sub TampilkanImageSlider   
    TimerSlider.Initialize("TimerSlider", 3000)
    Urls.Initialize
    Cursor = SQL.ExecQuery("SELECT NAMA_FILE FROM TB_IMAGE_SLIDER")
    For i = 0 To Cursor.RowCount - 1
        Cursor.Position = i
        If Cursor.GetString("NAMA_FILE") <> "" Then
            Urls.Add("http://" & SESSION_IP_SERVER & "/media/image_slider/" & Cursor.GetString("NAMA_FILE"))
        End If
    Next
    Cursor.Close
    ImageSlider1.NumberOfImages = Urls.Size
    TimerSlider.Enabled = True
End Sub
Download With Service
B4X:
#Region  Service Attributes
    #StartAtBoot: False
#End Region

Sub Process_Globals
    Private cache As Map
    Private tasks As Map
    Private ongoingTasks As Map
End Sub

Sub Service_Create
    tasks.Initialize
    cache.Initialize
    ongoingTasks.Initialize
End Sub

Sub Service_Start (StartingIntent As Intent)

End Sub

Sub Service_Destroy

End Sub

Sub Download (ImageViewsMap As Map)
    For i = 0 To ImageViewsMap.Size - 1
        tasks.Put(ImageViewsMap.GetKeyAt(i), ImageViewsMap.GetValueAt(i))
        Dim link As String = ImageViewsMap.GetValueAt(i)
        If cache.ContainsKey(link) Then
            Dim iv As ImageView = ImageViewsMap.GetKeyAt(i)
            iv.SetBackgroundImage(cache.Get(link))
        Else If ongoingTasks.ContainsKey(link) = False Then
            ongoingTasks.Put(link, "")
            Dim j As HttpJob
            j.Initialize(link, Me)
            j.Download(link)
        End If
    Next
End Sub

Sub JobDone(Job As HttpJob)
    ongoingTasks.Remove(Job.JobName)
    If Job.Success Then
        Dim bmp As Bitmap = Job.GetBitmap
        cache.Put(Job.JobName, bmp)
        If tasks.IsInitialized Then
            For i = 0 To tasks.Size - 1
                Dim link As String = tasks.GetValueAt(i)
                If link = Job.JobName Then
                    Dim iv As ImageView = tasks.GetKeyAt(i)
                    iv.SetBackgroundImage(bmp)
                End If
            Next
        End If
    End If
    Job.Release
End Sub

Sub ActivityIsPaused
    tasks.Clear
End Sub
 

Erel

Administrator
Staff member
Licensed User
You should never limit your questions to a single member.

But why when open a new activity, sometimes closed and replaced with main activity again?
This happens when the HttpJob response arrives after the activity was paused. The event will cause it to be started.
The solution is to download the images from a service (you don't need to use the code you posted) and call a sub in the main activity with the image only if the main activity is not paused.

For further discussion please start a new thread in the questions forum.
 

Erel

Administrator
Staff member
Licensed User
Yes with a small modification:
B4X:
Sub FillImageToView(bmp As B4XBitmap, ImageView As B4XView) As B4XBitmap
   Dim bmpRatio As Float = bmp.Width / bmp.Height
   Dim viewRatio As Float = ImageView.Width / ImageView.Height
   If viewRatio > bmpRatio Then
     Dim NewHeight As Int = bmp.Width / viewRatio
     bmp = bmp.Crop(0, bmp.Height / 2 - NewHeight / 2, bmp.Width, NewHeight)
   Else if viewRatio < bmpRatio Then
     Dim NewWidth As Int = bmp.Height * viewRatio
     bmp = bmp.Crop(bmp.Width / 2 - NewWidth / 2, 0, NewWidth, bmp.Height)
   End If
   Return bmp.Resize(ImageView.Width, ImageView.Height, True)
End Sub
You need to return a bitmap from ImageSlider1_GetImage.
 

Erel

Administrator
Staff member
Licensed User
No. However if you download the B4J example you will see that it is very simple to port it to B4A.
 

desof

Well-Known Member
Licensed User
I would like to report a problem in the control slider used in B4A.
If when you open the application and you do not have access to the internet and slide your finger on the control the application falls down.
Apparently the error in the PrevImage Module and in the line CurrentIndex = (CurrentIndex - 1 + NumberOfImages) Mod NumberOfImages

Why NumberOfImages = 0
 

desof

Well-Known Member
Licensed User
Yes. You can either download the images in the GetImage event (this is why it is a resumable sub) or download all of them and keep them in a List and return the image from the list.
Is it possible to see an example of how to read from a list based on this example?
Because otherwise the images are downloading again and again and is not efficient.
 

Erel

Administrator
Staff member
Licensed User
If when you open the application and you do not have access to the internet and slide your finger on the control the application falls down.
You need to disable this gesture until NumberOfImages is larger than 0. The NumberOfImages is set in this example after it parses the html file with the images.

Is it possible to see an example of how to read from a list based on this example?
Because otherwise the images are downloading again and again and is not efficient.
The images are only downloaded once.
 
Status
Not open for further replies.
Top