Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Mobile

ListView auto scroll horizontally

4.75/5 (6 votes)
5 Sep 2013CPOL4 min read 49.3K   3K  
Develop a list view which auto scrolled horizontally.

Introduction

With my experience, customize a View is really a difficult taskSmile | <img src=. Fortunately, Android supports SurfaceView, which is useful in view customize.

In this article, I guided the way to custom a Half Circle list view. Today, I will also use SurfaceView o custom a auto horizontal scroll view.

Image 2

Background

You should spend time to read SurfaceView document in Android developer website before reading this article.

Using the code

Animation.java

To auto slide list view from right to left, the idea is we will update the coordinate of each item in list view and draw it continuously in a background thread.

How to update the coordinate of each item continuously?

Suppose that, from time t1 to time t2, we must translate item from coordinate x1, to x2. The problem is, at time t, x = ? The formula will be easy:

x = x1 + t * (x2-x1) / (t2-t1)

Base on idea above, I made a simple Animation class which is used to calculate the current value, with below properties:

  • mStartValue: The beginning value when animation starting.
  • mEndValue: The final value when animation ending.
  • mDuration: The duration to change value from mStartValue to mEndValue.
  • mStartTime: The time animation starting. At the time animation is started, it is got by System.currentTimeMillis().
  • mEndTime: The time animation ending. mEndTime = mStartTime + mDuration.

The method to get the current value at specified time will be:

Java
public float getCurrentValue(long currentTime) {
   float currentValue = mStartValue + (currentTime)
                * (mEndValue - mStartValue) / mDuration;
   if (currentTime > mEndTime) {
           currentValue = mEndValue;
   }
   return currentValue;
} 

Extends above class, I made TranslateXAnimation.java

Java
public class TranslateX extends Animation {
    public TranslateX() {
        super(Type.Translate);
    }
}

Offcourse, we can make more Animation such as: FadeAnimation, ScaleAnimation... with the same idea. In this article, I use TranslateXAnimation only.

ImageItem.java

This object is an item of ListView.

Java
private class ImageItem {
     public float x;
     public float y;
     public Bitmap bitmap; 
     public TranslateXAnimation translateX; 
}    
  • x and y: is the coordinate of image item. The coordinate will be updated at real time. Base on x, y, item will be drawn in a thread by using Canvas canvas.drawBitmap(bitmap, x, y, paint);
  • translateX: when start to auto scrolling, item will be executed this animation. It will updated the x at runtime:

Java
x = translateX.getCurrentValue(System.currentTimeMillis() - translateX.mStartTime);

And item will be drawn by Canvas.

Java
canvas.drawBitmap(bitmap, x, y, paint);    

AutoHorizontalScrollView.java

This class is extends from SurfaceView which keeps an array list of ImageItem.

How to auto scroll for each 2 seconds?

I keep a variable startDisplayTime in this list view with idea:

  • From the first time AutoHorizontalScrollView is being displayed, startDisplayTime = System.currentTimeMillis().
  • When runtime, if <span style="font-size: 14px;"> </span>^__em style="font-size: 14px;">startDisplayTime >= 2 seconds,
    • Start auto scroll.
    • Update startDisplayTime = System.currentTimeMillis()

How to looping?

Looping means that, when the last item is being began to display from the right, the next right item will be the first item:)

If we have ITEM_WIDTH is the width of each list item, we will update its x coordinate:

Java
if (item.x <= -ITEM_WIDTH) {
  item.x = VIEW_WIDTH - 2 * ITEM_WIDTH;
}  

How to draw list item?

It is a easy work, because we only draw all item of list in background thread continuously.
Java
Canvas canvas = getHolder().lockCanvas();
if (canvas == null) {
   return; 
}
canvas.save();
canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
for (int i = 0; i < items.size(); i++) {
  ImageItem item = items.get(i);
  item.draw(canvas);
}
canvas.restore();
getHolder().unlockCanvasAndPost(canvas); 

ImageItem.draw()

Java
public void draw(Canvas canvas) {
            canvas.save();
            if (translateX != null && !translateX.isEnded()) {
                x = translateX.getCurrentValue(System.currentTimeMillis()
                        - translateX.mStartTime);
            } else {
                // translateX = null;
            }
            Paint paint = new Paint();
            paint.setAntiAlias(true);
            paint.setFilterBitmap(true);
            paint.setAntiAlias(true);
            canvas.drawBitmap(bitmap, x, y, paint);
            canvas.restore();
        }  

I put here the class diagram for easy understanding.

Image 3

Advance animation

20130906.

I have finished the article to guide the way to execute animation in SurfaceView. Base on the animation in this article, I will apply it to improve function of this list view? What do you think if I added more requirement as below:

  • All item will be has alpha is 100 at default.
  • The last right item will be scale from 1 to 1.5 and its alpha will be changed from 100 to 255 when slide from the right to the left.
  • The center item will be scale down 1.5 to 1 and its alpha will be changed from 255 to 100 when slide from the right to the left.
Base on Animation class, it is easy to make the ScaleXAnimation, ScaleYAnimation, AlphaAnimation.

The ImageItem will be added more properties:

  • scaleX: keep the scale ratio
  • scaleY: keep the scale ratio
  • alpha: Keep alpha value for fade in/out animation.
  • animations: The array list of animation which is executed.

With AutoHorizontalScrollView.java, I added:

  • firstItemPos: The position in list items of the first item in the left. Default is 0 from starting.
  • secondItemPos: The position in list items of the first item in the center. Default is 1 from starting.
  • thirdItemPos: The position in list items of the first item in the center. Default is 2 from starting.

Animation

When slide, if the position is thirdItemPos , beside the TranslateXAnimation, add to it:

ScaleXAnimation

Java
ScaleXAnimation scaleX = new ScaleXAnimation();
scaleX.mStartTime = System.currentTimeMillis();
scaleX.mDuration = 500;
scaleX.mEndTime = System.currentTimeMillis() + 500;
scaleX.mStartValue = 1f;
scaleX.mEndValue = 1.5f;
item.animations.add(scaleX);

ScaleYAnimation

Java
ScaleYAnimation scaleY = new ScaleYAnimation();
scaleY.mStartTime = System.currentTimeMillis();
scaleY.mDuration = 500;
scaleY.mEndTime = System.currentTimeMillis() + 500;
scaleY.mStartValue = 1f;
scaleY.mEndValue = 1.5f;
item.animations.add(scaleY);

And AlphaAnimation

Java
AlphaAnimation alpha = new AlphaAnimation();
alpha.mStartTime = System.currentTimeMillis();
alpha.mDuration = 500;
alpha.mEndTime = System.currentTimeMillis() + 500;
alpha.mStartValue = 150;
alpha.mEndValue = 255;
item.animations.add(alpha);  

And if it is the center position secondItemPos, add to it

ScaleXAnimation

Java
ScaleXAnimation scaleX = new ScaleXAnimation();
scaleX.mStartTime = System.currentTimeMillis();
scaleX.mDuration = 500;
scaleX.mEndTime = System.currentTimeMillis() + 500;
scaleX.mStartValue = 1.5f;
scaleX.mEndValue = 1f;
item.animations.add(scaleX);

ScaleYAnimation

Java
ScaleYAnimation scaleY = new ScaleYAnimation();
scaleY.mStartTime = System.currentTimeMillis();
scaleY.mDuration = 500;
scaleY.mEndTime = System.currentTimeMillis() + 500;
scaleY.mStartValue = 1.5f;
scaleY.mEndValue = 1f;
item.animations.add(scaleY);

And AlphaAnimation

Java
AlphaAnimation alpha = new AlphaAnimation();
alpha.mStartTime = System.currentTimeMillis();
alpha.mDuration = 500;
alpha.mEndTime = System.currentTimeMillis() + 500;
alpha.mStartValue = 255;
alpha.mEndValue = 100; 

And 3 three position will be updated as below:

Java
thirdItemPos++;
if (thirdItemPos == items.size()) {
   thirdItemPos = 0;
}
secondItemPos++;
if (secondItemPos == items.size()) {
    secondItemPos = 0;
}
firstItemPos++;
if (firstItemPos == items.size()) {
   firstItemPos = 0; 
}    

Draw

To draw ItemImage, do as below:

Java
for (int i = 0; i < animations.size(); i++) {
                Animation animation = animations.get(i);
                if (animation.isStarted()) {
                    if (!animation.isEnded()) {
                        if (animation.mType == Type.TranslateX) {
                            x = animation
                                    .getCurrentValue(System.currentTimeMillis()
                                            - animation.mStartTime);
                        } else if (animation.mType == Type.ScaleX) {
                            scaleX = animation
                                    .getCurrentValue(System.currentTimeMillis()
                                            - animation.mStartTime);
                        } else if (animation.mType == Type.ScaleY) {
                            scaleY = animation
                                    .getCurrentValue(System.currentTimeMillis()
                                            - animation.mStartTime);
                        } else if (animation.mType == Type.Alpha) {
                            alpha = (int) animation
                                    .getCurrentValue(System.currentTimeMillis()
                                            - animation.mStartTime);
                        }
                    } else {
                        animations.remove(i);
                    }
                }
            }
            paint.setAlpha(alpha);
            canvas.scale(scaleX, scaleX, x, y);
            canvas.drawBitmap(bitmap, x, y, paint); 

You can download AdvandeHorizontalAutoScrollListView.zip to view the result. 

HISTORY

20130905: First created. 

20130906: After finishing the article about SurfaceView animation add alpha, scaleX, scaleY animation to it. 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)