3

I'm trying to implement a banner in my app that works similar to how a an advertising banner works, where every few seconds it would scroll to the next ad. I wanted it to be dynamic so I used a RecyclerView, I've got it horizontal using the snap helper for a nice effect. However it's the automatic scrolling I'm struggling with, I need it to scroll to the next card after a few seconds and when it reaches the end scroll back to the first and start over.

I have also seen people talk of a viewflipper for this but I've never used one and not sure if it will give the desired effect.

halfer
  • 19,824
  • 17
  • 99
  • 186
Demonic218
  • 893
  • 2
  • 15
  • 33
  • `scrollToPosition(int position);` ? and if is last position then you go to 0 – Ionut J. Bejan May 08 '18 at 06:12
  • But it could also be a circular viewpager, you can find some nice library that can help you – Ionut J. Bejan May 08 '18 at 06:13
  • `ViewFlipper` or `RecyclerView` is up to your expectation. Do you want to show a peek from previous and next View or only current View is visible on screen? If only current `View` is visible, then go with `ViewFlipper`, it replaces the whole frame with new `View`, also support automatically flipping animation and easier to use than `RecyclerView`. – Tam Huynh May 08 '18 at 06:24
  • 1
    @TamHuynh I'll definitely check it out, thanks for the comment ! – Demonic218 May 08 '18 at 06:26
  • You can checkout : https://android-arsenal.com/details/1/5168 – Jaimin Modi May 08 '18 at 06:32
  • Possible duplicate of [How to auto scroll up Recycler view in Android?](https://stackoverflow.com/questions/33229806/how-to-auto-scroll-up-recycler-view-in-android) – Ganesh May 08 '18 at 07:00
  • Maybe you can use Carousel Page / View : https://github.com/sayyam/carouselview , the ability are exactly the same with your needs. – Vincent Elbert Budiman May 08 '18 at 07:30
  • 1
    @TamHuynh If i were to go the ViewFlipper route, how dynamic is it ? Would I be able to pull json down and display different views each populated with the parsed json data ? – Demonic218 May 09 '18 at 14:07
  • `ViewFlipper` doesn't work in `Adapter` way like `RecyclerView`, so just do a `for loop` through your list, call `addView` or `removeView`. There will be a performance hit if your list is large, like 50-100... because all the views are kept in memory – Tam Huynh May 09 '18 at 14:13
  • 1
    Am I able to defy how the views look ? Like how I would build a card for an 'RecyclerView' ? – Demonic218 May 09 '18 at 14:15
  • Yeap, of course, you have to create or `inflate` the View yourself before adding it to the `ViewFlipper`. Found this: https://stackoverflow.com/a/8908962/3627898 – Tam Huynh May 09 '18 at 15:30

2 Answers2

1

First, Create A TimerTask class like this,

  private class ScrollTask extends TimerTask {
                public void run() {
                recyclerview.post(new Runnable() {
                    public void run() {

                        int nextView = (adapter.getAdapterPosition() + 1) % adapter.getItemCount()

                       recyclerView.smoothScrollToPosition(nextView);    
                    }
                });
            }
        }

Then create a timer object

Timer timer = new Timer();

and Schedule the task like this,

timer.schedule(new ScrollTask(), interval // delay before task is to be executed,
 interval //period between successive task executions.)

interval is integer containing time in milliseconds

Ganesh
  • 368
  • 5
  • 15
  • 1
    What have you got the current position divided by the total count ? – Demonic218 May 08 '18 at 11:09
  • That's a way of having go in a loop indefinitely. If it is discrete scrolling you want (sounds like it is) I think you could accomplish the same with if/else that jumps you back to the first as Ionut J. Bejan commented above (though ViewFlipper: https://developer.android.com/reference/android/widget/ViewFlipper seems built for that purpose). I used the mod (%) logic to implement a continuously scrolling banner (like a news or stocks ticker). – Alan Todtenkopf May 08 '18 at 17:37
  • to avoid gettinf out of bounds, But, as @AlanTodtenkopf said, you can give a if/else to, which jumps back when limit is reached. Try, & use what's works best for you – Ganesh May 09 '18 at 07:44
  • 1
    I see, where does getAdapterPosition() get its value from ? – Demonic218 May 09 '18 at 13:37
  • 1
    @AlanTodtenkopf I am trying to get it to loop indefinitely, lets say for example I have 3 items, and the RV scrolls through i0 -> i1 -> i2. I'd like it to go through i2 back to i0. However if I use 'smoothScrollToPosition(0)' , items 2 and 1 briefly flash. I'm trying to avoid this and go with what looks like a continuous loop. I hope this makes sense. – Demonic218 May 09 '18 at 13:44
  • Then the % logic helps. Just to be clear, you are creating a "virtual" adapter position (e.g. you have i0, i1, i2, adapter thinks it is at i3, but you return i0). – Alan Todtenkopf May 09 '18 at 15:50
  • Let me know if it works or not, Now, I'm getting curious – Ganesh May 10 '18 at 07:11
  • 1
    @Ganesh Your code works until it loads the last card, I'm not sure if I've got the adapter.getAdapterPosition() set up right, currently I've got it assigned to a value which a class in the adapter sends back to me. The value that gets sent back is assigned onBindViewHolder by using holder.getAdapterPosition(); – Demonic218 May 10 '18 at 07:58
  • Can you put an if condition checking if the position + 1 > getItemCount, & set it to zero if that's the case. You won't have to use the modulus in that case then. & also log the values, maybe you'll understands what's wrong with that. & mark it as an answer, i have a repo to build(just kidding) – Ganesh May 10 '18 at 08:19
  • 1
    @Ganesh That would then just cycle through all of the previous items till it gets to i0 wouldn't it ? - I'm trying to avoid that effect – Demonic218 May 10 '18 at 08:43
  • Nope, if it reaches last item, it'll start from 0 to size of list. & the if condition will only execute at end of list. The modulus was added to achieve the same effect, but it maybe not working in your case. – Ganesh May 10 '18 at 08:48
  • 1
    @Ganesh Yeah it doesn't seem to be working, thank for your input though. – Demonic218 May 10 '18 at 10:30
1

So I've tried many approaches to solve this, Firstly, I tried @Ganesh's answer which I modified to get working. For those interested here is what I did,

Firstly created a timer object, as well as scheduled the timer task I created with a delay.

Blockquote

timer.scheduleAtFixedRate(new AutoScrollTask(), 2000, 5000);

The timer task uses the arraylist to work out it's current position and when it reaches the end it simply goes in reserve, to avoid that sudden jump to the first item.

private class AutoScrollTask extends TimerTask{
        @Override
        public void run() {
            if(position == arrayList.size() -1){
                end = true;
            } else if (position == 0) {
                end = false;
            }
            if(!end){
                position++;
            } else {
                position--;
            }
            recyclerView.smoothScrollToPosition(position);
        }
    }

This method does have it's flaws which I why I took @Tam Huynh's advice and researched the ViewFlipper. In this case however I used an AdapterViewFlipper. This allowed me to build a custom adapter where I could dynamically add views based on what data I was receiving.

Community
  • 1
  • 1
Demonic218
  • 893
  • 2
  • 15
  • 33