Android Tutorial Android SlidingPanels - Simple way to create sliding layouts

This is an old tutorial. There are now simpler and better ways to achieve this effect.

For example: https://www.b4x.com/android/forum/threads/tabstripviewpager-better-viewpager.63975/

Sliding layouts are cool.

Using the Animation library it is not difficult to animate single views and panels that hold other views.
The following code module and example project makes it even simpler to create a layout that is made of a number of panels. Whenever the current visible panel is changed, the current panel slides out and the new panel slides in.
As Panels can load layout files, you can create complex layouts by loading a layout file to each panel.

slidingpanels_1.png


The project is made of two components. The Main activity and the SlidingPanels code module.
You should add the SlidingPanels code module to your project and add a reference to the Animation library.

The main activity code is commented and explains the several integration points required.

Animations look much better on real devices than on the slow emulator.
Even if you are not interested in sliding layouts it is recommended to go over the code. It demonstrates the power of custom types which enable you to easily group many objects.
As code modules cannot hold references to Activity objects (like views), the calling activity passes the type with all the required data each time it calls a method (passing the data is done by passing a single pointer, there is no overhead here).

Questions and comments are always welcomed.
 

Attachments

  • SlidingPanels.zip
    6.9 KB · Views: 9,816
Last edited:

Smee

Well-Known Member
Licensed User
Longtime User
Slowly but surely.....

I am having some trouble understanding this code,


why is Duration = SlidingDuration? i cannot see where it is used anywhere

these statements also confuse me
Dim a(2) As Animation
sd.leftAnimations = a
Dim a(2) As Animation
sd.rightAnimations = a

i would have thought they would be like this in other langs

Dim a(2) As Animation
sd.leftAnimations = a(1)
sd.rightAnimations = a(2)
s there somewhere that could explan them?

thanks

Joe

i


Sub Initialize (sd As SlidingData, SlidingDuration As Int)
Duration = SlidingDuration
Main.tmrAnimation.Initialize("tmrAnimation", 2)
Dim a(2) As Animation
sd.leftAnimations = a
Dim a(2) As Animation
sd.rightAnimations = a
'Initialize the animation objects. We need two objects for each direction as both the current panel and the new panel are animated.
For i = 0 To 1
sd.leftAnimations(i).InitializeTranslate("animation" & i, 0, 0, -100%x, 0)
sd.leftAnimations(i).Duration = SlidingDuration
sd.rightAnimations(i).InitializeTranslate("animation" & i, 0, 0, 100%x, 0)
sd.rightAnimations(i).Duration = SlidingDuration
Next
For i = 0 To sd.panels.Length - 1
sd.Panels(i).Left = 100%x 'Move the panels right of the screen
Next
sd.currentPanel = -1
End Sub
 

Smee

Well-Known Member
Licensed User
Longtime User
Erel,

Another problem i have come across is this, I have been trying to load a panel layout dynamically but i am having very little success. (panels(2).LoadLayout("scr2") )

I placed test code in the changepanel routine in the main module but it does not work. As i have said earlier i need to be able to load many pictures. A user may go forwared or backward and i intend to use a database of links to a photo directory. From here a user would scroll through the links which would show a picture.

so using this method i would also need to be able to dynamically set a filename to an imageview

Many Thanks
 

Smee

Well-Known Member
Licensed User
Longtime User
Hi,

Sorry those two outer brackets were not part of the code. it probably should have read 'panels(2).LoadLayout("scr2") ' . it was just to highlight the statement i had used.

Update:

I think i have worked out how to do the file updating depending on the panels however i have hit the following problem before i get to that. First my code

Select Left
Case False
If sd.currentPanel=0 Then
JumpToPanel(2)
Else
SlidingPanels.ChangePanel(sd, Left)
End If

Case True
If sd.currentPanel=2 Then
JumpToPanel(0)
Else
SlidingPanels.ChangePanel(sd, Left)
End If
End Select
Now to put a new file on an ImageView i have

If sd.currentPanel=2 Then IV2.Bitmap = LoadBitmap(File.DirAssets, "26809.jpg")

But i do not know how to reference the IV2 that has been placed on panel2
if it is Dim in Globals the program stops
This is an 'Activity Object', it cannot be declared under Sub Process_Globals.
if it is dim in Activity_Create it is not available to other modules
:sign0085:

Other Questions

1) The code "works" in a fashion, i get an image of the previous panel also. Is there a way to stop or at least hide that? it also obviously jumps backwards when the intent is to have it look as though it is in a smooth scroll one way. Could this be tidied up?

2) Is the ChangePanel Sub in the Main mod the best place for this code?


As you can see i am just trying to create a loop so that irrespective of the way a person moves the panel, if its at the end it will go back to the first one and if the first one and they scroll backwards it will go to the last and step backwards. (At least that is my intent)

Once this is working i will try loading different pics based on a counter

Many thanks for any help

Joe

PS

The only other way I could see to overcome this would be to have over 100 panels with 3 imageviews on each of them and i dont know what this sort of overhead would do to speed/memory etc.

Thanks again
 
Last edited:

Smee

Well-Known Member
Licensed User
Longtime User
Good, no replies as yet.

Erel,

I have re-written the code as follows

Sub ChangePanel(Left As Boolean)
'disable the buttons during the animation
btnLeft.Enabled = False
btnRight.Enabled = False
'Call SlidingPanels.ChangePanel to actually change the panels.

Dim xy As Int
If sd.currentPanel=-1 Then
xy=0
Else If sd.currentPanel=0 Then
xy=2
Else If sd.currentPanel=2 Then
xy=1
End If

Dim Iviews(3) As ImageView
Dim LeftPos As Int
LeftPos=40
'Top =100

For i = 0 To Iviews.Length-1
Iviews(i).Initialize("views")
Iviews(i).Gravity=Gravity.FILL
sd.Panels(xy).AddView(Iviews(i),LeftPos, 30, 280, 280)
Iviews(i).Bitmap = LoadBitmap(File.DirAssets, "26809.jpg") ' use a different bitmap for each panel
LeftPos=LeftPos+330
Next


Select Left
Case False
If sd.currentPanel=0 Then
' SlidingDuration = 0
JumpToPanel(2)
' SlidingDuration = 500
Else
SlidingPanels.ChangePanel(sd, Left)
End If

Case True
If sd.currentPanel=2 Then
' SlidingDuration = 0
JumpToPanel(0)
Else
SlidingPanels.ChangePanel(sd, Left)
End If
End Select



End Sub

I am not getting a smooth scroll when i go from the last panel to the first or first to last. I have tried setting the duration to 0 but that does not really work. Any ideas how i could switch from the last panel to the first in one easy "slide" ?

Also is this sub the best place for this code?

Thanks

Joe
 

Smee

Well-Known Member
Licensed User
Longtime User
Ok
This is the original Code

B4X:
Sub ChangePanel(Left As Boolean)
   'disable the buttons during the animation
   btnLeft.Enabled = False
   btnRight.Enabled = False
   'Call SlidingPanels.ChangePanel to actually change the panels.
   SlidingPanels.ChangePanel(sd, Left)
End Sub

The change is as follows

B4X:
Dim xy As Int
If sd.currentPanel=-1 Then 
   xy=0
Else If sd.currentPanel=0 Then
   xy=2
Else If sd.currentPanel=2 Then
   xy=1
End If
   
Dim Iviews(3) As ImageView      
Dim LeftPos As Int
LeftPos=40
'Top =100

For i = 0 To Iviews.Length-1
   Iviews(i).Initialize("views")
   Iviews(i).Gravity=Gravity.FILL
   sd.Panels(xy).AddView(Iviews(i),LeftPos, 30, 280, 280)
   Iviews(i).Bitmap = LoadBitmap(File.DirAssets, "26809.jpg") ' use a different bitmap for each panel
   LeftPos=LeftPos+330
Next
      

   Select Left
   Case False
      If sd.currentPanel=0 Then
'         SlidingDuration = 0
         JumpToPanel(2)
'         SlidingDuration = 500
      Else
         SlidingPanels.ChangePanel(sd, Left)
      End If

   Case  True
      If sd.currentPanel=2 Then
'         SlidingDuration = 0
         JumpToPanel(0)
      Else
         SlidingPanels.ChangePanel(sd, Left)
      End If      
   End Select

i will try to explain the problem with JumpToPanel.

If you go to the last panel and jump to panel 0, the panels slide by 1 at a time. What i am trying to do is go from panel 7 to panel 0 in 1 go. i.e like a wrap around ( if at end start again)

The idea is i use 3 panels with 3 pictures on each, but each panel is loaded with new pictures each time the user goes forward.
If they go backwards then the pictures are loaded in reverse

Hope this clarifies the problem and hope you can offer a solution

Regards

Joe
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
Now that I understand what you are trying to achieve I can help you.
The Mod operator is your friend here:
B4X:
Sub ChangePanel(sd As SlidingData, left As Boolean)
    If left Then            
        If sd.currentPanel >= 0 Then 'remove current panel if such exists (it will not be the case on the first call).
            sd.leftAnimations(0).Start(sd.panels(sd.currentPanel)) 'Animate current panel and move it out
        End If
        sd.leftAnimations(1).Start(sd.panels((sd.currentPanel + 1) Mod sd.Panels.Length)) 'Animate new panel
        sd.currentPanel = (sd.currentPanel + 1) Mod sd.Panels.Length
    Else
        Dim leftPanel As Int
        leftPanel = (sd.currentPanel + sd.Panels.Length - 1) Mod sd.Panels.Length
        sd.panels(leftPanel).Left = -100%x
        sd.rightAnimations(0).Start(sd.panels(sd.currentPanel))
        sd.rightAnimations(1).Start(sd.panels(leftPanel))
        sd.currentPanel = leftPanel
    End If
End Sub
Use the above code instead of the original and it will work. Note that you also need to change Sub Animation1_AnimationEnd and always enable the two buttons.
 

Smee

Well-Known Member
Licensed User
Longtime User
Erel,

What can i say? I am in awe of your code. i look at it but i do not yet fully follow even though i understand the mod operator and how you have re-dim the panel. I did not even think of that

This really is a beautiful piece of code.

Thank you so much. :sign0188:

i am now going to try to load the different jpgs on to the panels by myself but i doubt if it can be so eloquent as your code.

:sign0188:
 

Smee

Well-Known Member
Licensed User
Longtime User
Sorry, i thought you wanted posts regarding this subject in this thread. I will post any new questions in a new thread fafter this last one

The panel is not redimmed in the new code/
Does it not get re-dimensioned each time the code is called in the else statement?
 

Smee

Well-Known Member
Licensed User
Longtime User
Sorry, i thought you wanted posts regarding this subject in this thread. I will post any new questions in a new thread fafter this last one

The panel is not redimmed in the new code

Does it not get re-dimensioned each time the code is called in the else statement?

Else
Dim leftPanel As Int
 

danoptic

Member
Licensed User
Longtime User
I didnt find out how to open a new thread so here is my question:

I m trying to make an horyzontal scrollview of labels.

I used the slidepanel but I put on each 4 labels.
How can I separate between the labels? it looks like 1 giant lable !
Is that any "table" option"
 

ietv

Member
Licensed User
Longtime User
I get an Array Index Out of Bounds error.

Update: No, I think it was a problem with another app with the same name. I modified the old example and broke it. I think the process was still in memory.
 
Last edited:

danoptic

Member
Licensed User
Longtime User
http in sliding panel

Hi Erel,
I need to do Http request with sliding panels but it's not possible because of the timer!
When will be a sliding panel - left to right like the up & down sliding already existing?

thanks
 
Top