Today, I wanna introduce how to make an android infinite loop gallery. This new gallery actually basing on the android gallery, but not really extends from it. The default android gallery can provide a common gallery function. For the common usage, you can easily get the example code from Android Gallery Example: Widget Gallery. But for some advanced usage, it has lots of limitations, for example, infinite loop. Here, I will tell you why and how to create a gallery which has the infinite loop feature.


Before we start it, let us analyze the default android widget gallery:
android gallery class diagram

As the class diagram, the default widget is the subclass of AbsSpinner, and which subclass is AdapterView. And Gallery also implements the interface OnGestureListener.

AdapterView has four abstract methods that we need to implement: getAdapter(), setAdapter(), getSelectedView() and setSelection(). The most important one we need to mension is the setAdapter(). As you will see in the Gallery source code, it will set the data adapter, and initialize the view, and call the function requestLayout() to trigger the view do the layout job. So the next important function is onLayout(), which will be overriden, so that the gallery can customize the look and feel.

GestureDetector.OnGestureListener is the interface which you can implements to listen all the different gestures. The android gallery implements the onFling() function to create the scroll effect, which will use the private inner class FlingRunnable.

After reading the android gallery widget source code, I just realized that it’s impossible to add the infinite looping feature by extending from the exist gallery. The reason is lots of critical functions inside android gallery are private method, or package method. So I decide to implement a new android widget, InfiniteGallery. This widget are open source project, hosting on the google code server. I just simply extends it from AdapterView.

Infinite Loop Gallery Component Source Code

In this example, I will using the Android Gallery widget. I will put a gallery on the screen. The layout xml looks quite simple. Here is the source code:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/layout1">
    <Gallery
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/mygallery"
        android:layout_weight="1"/>
</LinearLayout>

Now, let’s talk about the Item render for gallery. To make this example simple, I just use an ImageView. If you want to show more information in your gallery, you can improve this item render. Here is my item render layout xml source code:

<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
	android:id="@+id/imageItem"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent"
	android:scaleType="fitCenter"/>

We have finished the layout part. Now let’s move to Java code.

	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		
		Gallery gallery = (Gallery) findViewById(R.id.mygallery);
		gallery.setAdapter(new ImageAdapter(this));
		gallery.setSpacing(10);
		gallery.setSelection((Integer.MAX_VALUE/2) - (Integer.MAX_VALUE/2) % 12 );

	    gallery.setOnItemLongClickListener(longClickListener);

		AdView adview = (AdView)findViewById(R.id.adView);
        AdRequest re = new AdRequest();
        //re.setTesting(true);
        re.setGender(AdRequest.Gender.FEMALE);
        
        adview.loadAd(re);
	}

In the above source code, I am get the gallery instance and set an ImageAdapter to it. ImageAdapter is a subclass of BaseAdapter, which controls how to show the images in gallery. To implement the infinite gallery, I will put my code in this class.

public class ImageAdapter extends BaseAdapter {
    private LayoutInflater inflater = null;

    private final Integer[] imageDataList = { R.drawable.a, R.drawable.b,
            R.drawable.c, R.drawable.d, R.drawable.e, R.drawable.f,
            R.drawable.g, R.drawable.h, R.drawable.i, R.drawable.j,
            R.drawable.k, R.drawable.l };

    public ImageAdapter(Context c) {
        inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    public int getCount() {
        if (imageDataList != null) {
            return Integer.MAX_VALUE;
        } else {
            return 0;
        }
    }

    public Object getItem(int position) {
        if(position >= imageDataList.length) {
            position = position % imageDataList.length;
        }
        
        return position;
    }

    public long getItemId(int position) {
        if(position >= imageDataList.length) {
            position = position % imageDataList.length;
        }
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        View view = convertView;

        if (view == null) {
            view = inflater.inflate(R.layout.itemrender, parent, false);
        }

        if(position >= imageDataList.length) {
            position = position % imageDataList.length;
        }
        
        ((ImageView) view).setImageResource(imageDataList[position]);
        return view;
    }
    
    public int checkPosition(int position) {
        if(position >= imageDataList.length) {
            position = position % imageDataList.length;
        }
        
        return position;
    }
}

This part is a little bit long. But if you look at the code line by line, it is quite simple actually. First, I define integer array, imageDataList. It is a list of images which I will show in my gallery example. Then I overwrite the getCount() function. This function will tell the Android gallery widget how many images will be shown in it. In my code, I put Integer.MAX_VALUE. For a 32 bit system, Integer.MAX_VALUE is 231-1. It looks like an infinite gallery. 🙂 This is the key of infinite.

Try Example Android App

You can download and install this android app by click the following link, or scan the following QR code to download and install on your android phone simply.
Click here to download the android example (.apk)

chartinfiniteloop

Previous PostNext Post

46 Comments

  1. InfiniteGallery doesn’t work well with smaller images. For example, try using a few 60×60 images instead of the large images that come with the sample app.

  2. Wrote this feedback, they’re a hard-to-find short lived beauty, of which a lot of folks neglect.

  3. I must quotation this page at my blog site. It can? And you et an account provider on Twitter?

  4. Congratulations, it’s a very good job :=)
    However, I’m wondering how to start the animation at the beginning ? And how don’t stop animation between each element to have the impression of a single animation ?

    Thanks

    1. You can use the OnGestureListener to detect the onfling event to decide if u need to do animation.

      For the second question, I quit don’t get it. Can u make it clear?

      1. OK, I’ll try to see the OnGestureListener, thanks
        I’m sorry for my second question, I’m french and my english is sometimes too bad :/
        In fact, the animation of the infinite gallery stop every two picture, and then restart. I want that the animation never stop (even if user scroll).

  5. Hi, Seb. I check the project again. And I find there is bug that the scrolling direction is wrong when you fling the gallery. I already fix the bug. And I test on my HTC Desire. And It works fine.

    someone also report a bug about the small image. My test is full screen image. And I’m sorry that I’m too busy to fix it. If you also want to improve it. We can work together.

    1. I don’t have understood why you talk to me about these bugs, there arn’t linked to my problem, isnt it ? Or do you mean that the bug with small images is the reason of my problems ? In your test, do you have the same problem as me (animation paused every two pictures) ?

      1. No. In my device, it is quit smooth. Do u test in simulator or device? If in the simulator, I guess the performance cause your problem. When i run it in simulator, it is quite un-smooth

        1. OK, thanks for your answer. I have only test on an emulator because I don’t have any device for the moment…

          So, if it works in device it’s cool, but it’s very strange that the gallery stop every two picture on simulator… oO
          The reason of performance is not the good one I think, it’s too strange. No ?

          I think we don’t set the parameter mAnimationDuration with the same value. Under 100, it seems to work because it’s very quick, but when I want to have an animation slower, with a parameter of 10000 for example, we see the default of the animation : every two picture, it stops.

          It seems that another problem exists : my gallery was wrapped correctly. I have replaced my gallery with your, and now, I have some problems with that. Your gallery is not correctly wrap.

          Thanks for your help and your quick answer :=)

          1. Hi, You can check the startUsingDistance() in the InfiniteGallery class. The mAnimationDuration is just the duration of the scrolling. The scrolling distance is decided outside.

            For another problem you mentioned, is the picture sequence wrong??

            Thanks for the feedback.

  6. Thanks a lot for this code.
    I was wondering if you could tell me how to implement an OnItemLongClickListener.
    It doesn’t seem to register when I use

    gallery.setOnItemLongClickListener(new OnItemLongClickListener(){

    @Override
    public boolean onItemLongClick(AdapterView arg0, View arg1, int position,
    long arg3) {
    String temp = position + “”;
    Toast toast = Toast.makeText(getBaseContext(), temp, Toast.LENGTH_SHORT);
    toast.show();
    return true;
    }

    });

    I appreciate your help.

    1. Hi, Fabian. If you want to get it works, you need to override the onLongPress function inside the InfiniteGallery. Maybe you can simply to return true. Tell me if it works after you override that function. Good luck.

      1. Hey James. Thanks for responding. The onLongPress is overriden in the InfiniteGallery in your code and it returns true, however neither an onLongClickListener nor an onItemLongClickListener seem to register when I call gallery.setOnItemLongClickListener from inside the InfiniteGalleryActivity class.

        1. Hi Fabian. You are right. It doesn’t work in that way. This morning, I work it out and update the source code. You can update from google code by svn. And in the example, you can see the long click working ;P. You can call setOnItemLongClickListener, it works. Hopefully, it will help you. Have a nice day.

          1. I haven’t had a chance to give it a try yet, but thank you very much for responding so quickly.

          2. This works beautifully now. I also found that if you add android:configChanges="orientation" to the activity in the manifest file, it will retain the current image when switching screen orientations. Thanks again for this code and for your quick help.

  7. Hi,
    thank you for this great help.
    Why when the images are less than the screen width and scroll to rigth it keeps moving infinity
    how can I fix that, thankyou

    1. It seems a big problem for many people. Can u send me your code example? It will be very helpful to debug and solve the problem. Please contact me on my Contact Us page.

  8. Hi James,

    First congrats, you did a great work, helped me alot. My doubt is how i can change the spacing between views ?

    Thanks

    1. Hi, Jonas,

      I have updated source code. Now you can set the space between images by “gallery.setMSpacing()”. You need to updated the source code before you try is.

      Thanks

      1. James, thank you very much.

        But now I have another problem. When I changed the spacing and tap some image, the galley starts the animation and doesn’t stop aymore =/. Can you look this for me please ? I’m looking here but until now I got nothing.

        1. Hi, Jonas.

          I have tested the infinite gallery. It works in my Android HTC Desire. In my test case, I set the spacing to 50 and 100. Both of them works very well.

          1. Hi James.

            Thanks again. Here my images are small and I put “wrap_content” in width and height atributes. So in my screen, I see 3 images each time. I’m testing in Samsung Galaxy 5 and Sony Xperia mini. Both with this problem =/. Perhaps the problem is with the small images. What do you think?

          1. Ok James. Thanks again for your help man. =). Do you have any idea to fix it ? I’m studing your code and It seems that something goes wrong in the method setSelectionToCenterChild. If I find some solution I’ll post here. Thanks

        2. I debug it last night. I think you can pay attention on the function updateSelectedItemMetadata(), while will change the attribute mSelectedChild.

          The reason why setSelectionToCenterChild() doesn’t work well is the mSelectedChild is wrong.

          In the updateSelectedItemMetadata(), mSelectedChild is decided by mSelectedPosition, and mFirstPosition.

          So you need to follow the code from trackMotionScroll(), which is the engine of moving animation.

  9. Hi James,

    thx for this widget, really appreciated.
    Unfortunately I have a problem with the height of InfiniteGallery. I put 3 InfiniteGalleries into a linearlayout (orientation is vertical). The width is fill_parent but the height is wrap_content. When I add layout_weight=”1″ to each Gallery, every gallery uses the exact same space on the screen not caring about the Views I put in there (every View added to the gallery gets the same LayoutParams per Gallery). Without layout_weight=”1″ only the top gallery is displayed and the rest of the screen is black .. I can still scroll the gallery in the black screen.
    What am I missing to get wrap_content to the views in that gallery so my galleries have no space between each other?

    Thx for your help.
    Regards,
    Norbert

    1. Hi Norbert,

      You put 3 infinite gallery in 3 lines (which is layouted vertically). As you mentioned that you can only get the top gallery working, and other two lines are black. And in your black screen, you can still scroll the top gallery.

      In this situation, I guess the top gallery’s height is same as the parent which is linearlayout. To figure out what happened, i think you can use the absolutelayout, and hard code the position, width and height for these 3 android infinite gallery to see what will happed :P…

      Or you can define a linearlayout which include other 3 linearlayout. For each linearlayout, you put one infinite gallery inside.

      Good Luck, buddy. I hope my suggestion is helpful.

      James

      1. Hi James,

        unfortunately I can’t get it to work. I tried diverse layout combinations and none of them work except for setting the layout_weight for each infinite gallery, which I cannot do because I need to calculate the size of the child ImageViews first in code.
        Is it possible that there is something not working with measuring the child views and then setting the height of the infinite gallery?
        Maybe you can provide me with a layout setup that has 3 infinite galleries in vertical orientation having 3 different heights depending on the ImageViews you put inside? Maybe I’m just missing some little detail but I just can’t get it to work.

        Thx again,
        Norbert

        1. There are lots of bugs for small pictures. And I still don’t find where the problem is. Sorry for that. If i fixed it in the future, i will give u a message.

  10. Hi

    it is really a nice work and it is working fine in my galaxy s2.

    can you please tell me how to implement a pinch zoom for this imageview . i tried to use the TouchImageView insted of imageview , TouchImageView is having the zooming function so i used it . but it is not working . can you pls guide me . then it will be very help full.

    thanks

    1. I think it can not. In my another application, I implement the zoom-in and zoom-out outside the infinite loop image widget. Using “setOnTouchListener()”, when you zoom-in or zoom out, return true, otherwise return false.

  11. hi my friend
    nice tutorial , can help me in how to set for each image atitle ( text to descripe each image )
    thanks

      1. thanks my friend for your replay , im new in android development , would you please , explain more with sample code ,
        appreciate it
        thanks

Leave a Reply

Your email address will not be published. Required fields are marked *