Android: Animation in Gallery View? - android

When I use the Gallery widget, how do I get the images to say scale up & glow on being selected and scaled down & un-glow on being unselected?
All tutorials I've seen have this effect but I'm not able to see it...
Is there some kind of an animation that I have to attach to the Gallery?

Hope this is helpful. I manage to "simulate" the shrink/grow solution with the Gallery widget. Since they removed the getScale(), things get a little bit complicated. I think that this it's not the best solution at all, but at least I can live with it.
What I have found is that Gallery manages the focus EXTREMELY BAD. So, the first approach was to add a focus change listener on the ImageView displayed, but no luck there. Focus is a MESS there... in terms that, the selected image it's not the currently focused view. I have sent a mail to android-developers mailing list about some error on API doc (regarding the focusSearch()method and some focus contants).
Here's my solution to this problem:
Build an animation resource to 'grow' the image:
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXScale="1.0"
android:toXScale="1.10"
android:fromYScale="1.0"
android:toYScale="1.10"
android:duration="300"
android:pivotX="50%"
android:pivotY="50%"
android:interpolator="#android:anim/accelerate_decelerate_interpolator"
android:fillAfter="false"/>
If you don't get what that means then you should proceed to read this
That will be our 'grow' effect, and you will need to save it in: res/anim/grow.xml or whatever name it suites you (but always in res/anim dir).
You can follow the resource guide from here to create a Gallery view. The ImageAdapter builds an ImageView every time that the Gallery object calls getView(). One workaround you could implement is adding a line to the getView() method that identifies a View with a position, this way:
...
i.setId(position);
...
With that line added to the getView() method of the ImageAdpater object, you can then unequivocally identify that view within a listener, for instance:
g.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected (AdapterView<?> parent, View v, int position, long id) {
Animation grow = AnimationUtils.loadAnimation(YourActivity.this, R.anim.grow);
View sideView = parent.findViewById(position - 1);
if (sideView != null)
((ImageView)sideView).setLayoutParams(new Gallery.LayoutParams(150, 100));
sideView = parent.findViewById(position + 1);
if (sideView != null)
((ImageView)sideView).setLayoutParams(new Gallery.LayoutParams(150, 100));
v.startAnimation(grow);
v.setLayoutParams(new Gallery.LayoutParams(170, 150));
}
public void onNothingSelected (AdapterView<?> parent) {
System.out.println("NOTHING SELECTED");
}
});
NOTE: You may notice that all the values from animation and from layout parameters has been choosen by me at hand. This is because i'm not going to clean code for you. And, this is just a workaround the BAD focus issue with this widget or the android view system. If focus were OK, then, all you need to do is set a focus change listener that makes the gros/shrink when it got focus/unfocused.
I hope this may help you to find a way around for your problem,
Regards,
New EDIT: This is the listener I have set, I also added the line i.clearAnimation() in the getView() method:
private class SelectListener implements AdapterView.OnItemSelectedListener {
private Animation grow;
private int last;
public SelectListener() {
grow = AnimationUtils.loadAnimation(RouteGallery.this, R.anim.grow);
last = 0;
}
public void onItemSelected (AdapterView<?> parent, View v, int position, long id) {
View sideView = parent.findViewById(last);
if (sideView != null && last != position)
sideView.clearAnimation();
v.startAnimation(grow);
last = position;
}
public void onNothingSelected (AdapterView<?> parent) {
}
}

You need to use an ImageSwitcher. The ImageSwitcher has methods for setting the in and out animations (when image is selected and deselected, or selected and replaced).
The following link has a good tutorial on how to use it in conjunction with the Gallery.

I implemented a similar animation like this:
final Animation shrink = AnimationUtils.loadAnimation(activity, R.anim.shrink);
shrink.setFillAfter(true);
gallery.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
// This iterates through the views which are currently displayed on screen.
for (int k=0; k<gallery.getChildCount(); k++){
// Do whatever else you want, here.
// This is how you get a particular element of a view
ImageView background = (ImageView) gallery.getChildAt(k).findViewById(R.id.menu_item_background);
//clear animation
gallery.getChildAt(k).clearAnimation();
}
// Scale the selected one
view.startAnimation(shrink);
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {}
});

Related

Implement Google+ card liked animation via RecylerView

Previously, I implemented Google+ card liked animation (Video), by using technique mentioned in New Google Now and Google+ card interface
Override LinearLayout's onGlobalLayout to start animation, so that when activity first launched, we can see the slide up animation of cards.
Override ScrollView's onScrollChanged to start animation, so that during scrolling, we can see the newly visible cards being animated.
So far, I don't see any technique from RecylerView's example.
I was wondering, without using LinearLayout and ScrollView, can with achieve the same outcome, by using RecylerView? Is there any code example available? (So far, I unable to find one yet)
Add these lines in RecyclerView 's adaptor. Make a Variable for Each card i.e(convertView) here and initialise it.
int mLastPosition = 0;
public static class ViewHolder extends RecyclerView.ViewHolder {
TextView card_head, card_body;
View convertView;
#SuppressLint("NewApi")
public ViewHolder(View v) {
super(v);
convertView = v;
}
}
Bind you view by position
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
// do your thing here
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {
float initialTranslation = (mLastPosition <= position ? 150f
: -150f);
holder.convertView.setTranslationY(initialTranslation);
holder.convertView.animate()
.setInterpolator(new DecelerateInterpolator(1.0f))
.translationY(0f).setDuration(900l).setListener(null);
}
// Keep track of the last position we loaded
mLastPosition = position;
}
here , you have to animate the who view it calls onBindViewHolder method when new card is created animate the whole view customize it.

Android ExpandableListView using animation

I'm using
<ExpandableListView
android:id="#+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ExpandableListView>
i want add animation slide for child when onclick parent . So How can i do ?
Final Update
It's been quite a while since I wrote this answer. Since then a lot has changed. The biggest change is with the introduction of RecyclerView that makes animating a list or grid easy. I highly recommend switching over to RecyclerViews if you can. For those who can't I will see what I can do regarding fixing the bugs for my library.
Original answer
I actually do not like the popular implementation of an animated ExpandableListView that simply uses a ListView with an expand animation because in my use case, each of my groups had a lot of children, therefore it was not feasible to use a normal ListView as the child views will not be recycled and the memory usage will be huge with poor performance. Instead, I went with a much more difficult but more scalable and flexible approach.
I extended the ExpandableListView class and overrode the onCollapse and onExpand functions, I also created a subclass of a BaseExpandableListAdapter called AnimatedExpandableListAdapter. Inside the adapter, I overrode the getChildView function and made the function final so that the function cannot be overrode again. Instead I provided another function called getRealChildView for subclasses to override to provide a real child view. I then added an animation flag to the class and made getChildView return a dummy view if the animation flag was set and the real view if the flag was not set. Now with the stage set I do the following for onExpand:
Set the animation flag in the adapter and tell the adapter which group is expanding.
Call notifyDataSetChanged() (forces the adapter to call getChildView() for all views on screen).
The adapter (in animation mode) will then create a dummy view for the expanding group that has initial height 0. The adapter will then get the real child views and pass these views to the dummy view.
The dummy view will then start to draw the real child views within it's own onDraw() function.
The adapter will kick off an animation loop that will expand the dummy view until it is of the right size. It will also set an animation listener so that it can clear the animation flag once the animation completes and will call notifyDataSetChanged() as well.
Finally with all of this done, I was able to not only get the desired animation effect but also the desired performance as this method will work with group with over 100 children.
For the collapsing animation, a little more work needs to be done to get this all setup and running. In particular, when you override onCollapse, you do not want to call the parent's function as it will collapse the group immediately leaving you no chance to play an animation. Instead you want to call super.onCollapse at the end of the collapse animation.
UPDATE:
I spent some time this weekend to rewrite my implementation of this AnimatedExpandableListView and I'm releasing the source with an example usage here:
https://github.com/idunnololz/AnimatedExpandableListView/
animateLayoutChanges adds auto-animation
<ExpandableListView
android:animateLayoutChanges="true"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
#idunnololz solution works great. however i would like to add some code to collapse previously expanded group.
private int previousGroup=-1;
listView.setOnGroupClickListener(new OnGroupClickListener() {
#Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
// We call collapseGroupWithAnimation(int) and
// expandGroupWithAnimation(int) to animate group
// expansion/collapse.
if (listView.isGroupExpanded(groupPosition)) {
listView.collapseGroupWithAnimation(groupPosition);
previousGroup=-1;
} else {
listView.expandGroupWithAnimation(groupPosition);
if(previousGroup!=-1){
listView.collapseGroupWithAnimation(previousGroup);
}
previousGroup=groupPosition;
}
return true;
}
});
#idunnololz solution is working great, but I experienced weird behavior with my custom layout for group. The expand operation was not executed properly, the collapse however worked perfect. I imported his test project and it worked just fine, so I realized the problem is with my custom layout. However when I was not able to locate the problem after some investigation, I decided to uncomment these lines of code in his AnimatedExpandListView:
if (lastGroup && Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
return expandGroup(groupPos, true);
}
which caused the problem (my app is aimed for Android 4.0+).
Found this snnipet not remebering where here in Stack Overflow. Have two basic static methods: expand(View v) and collapse(View v).
You only have to pass the view you want to hide show.
Note: I Don't recomend pass a view having wrap_content as height. May not work fine.
public class expand {
public static void expand(View view) {
view.setVisibility(View.VISIBLE);
final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
view.measure(widthSpec, heightSpec);
ValueAnimator mAnimator = slideAnimator(view, 0, view.getMeasuredHeight());
mAnimator.start();
}
public static void collapse(final View view) {
int finalHeight = view.getHeight();
ValueAnimator mAnimator = slideAnimator(view, finalHeight, 0);
mAnimator.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationEnd(Animator animator) {
view.setVisibility(View.GONE);
}
#Override
public void onAnimationStart(Animator animation) {
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
});
mAnimator.start();
}
private static ValueAnimator slideAnimator(final View v, int start, int end) {
ValueAnimator animator = ValueAnimator.ofInt(start, end);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int value = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = v.getLayoutParams();
layoutParams.height = value;
v.setLayoutParams(layoutParams);
}
});
return animator;
}
}

Move/scroll clicked listitem view at top of screen in the expandablelistview

I seen SimpleExpandableListAdapter example when i clicked expanded group item at moving top of the screen. i created NewAdapter which extends
BaseExpandableListAdapter. I want to do same thing but dont know how to do. i searched lot of things which is not worked for me. Please let me know how to do.
Thank you in Advance.
This one is working for me
expandList.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
#Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
if (!parent.isGroupExpanded(groupPosition)) {
parent.expandGroup(groupPosition);
} else {
parent.collapseGroup(groupPosition);
}
parent.setSelectedGroup(groupPosition);
return true;
}
});
As the main working part for scroll is
parent.setSelectedGroup(groupPosition);
may this solve your problem .
I think using duration gives a better user experience. So you can use this, with duration added. Will scroll the item in position smoothly to the top of the listview.
int duration = 500; //miliseconds
int offset = 0; //fromListTop
listview.smoothScrollToPositionFromTop(position,offset,duration);
descrease duration to make scrolling faster
What you are looking for is,
public void onItemClick(AdapterView<?> arg0, View view, int position, long arg3)
{
myListview.setSelectionFromTop(position, 5);
}
This will position your selected list item as the first visible item on screen. However, it does so without any smooth scroll animation, the moment you tap the item, it becomes the first item visible.
If you want the scroll animation, you could use,
public void onItemClick(AdapterView<?> arg0, View view, int position, long arg3)
{
int offset = position - myListview.getFirstVisiblePosition();
if(myListview.getFirstVisiblePosition() > 0)
offset -= 1;
myListview.smoothScrollByOffset(offset);
}
Note that smoothScrollByOffset is available from API-Level 11 onward.
However, both these methods will not work if you select an item close to the bottom of the list, as the list will not scroll further upwards if the last list item is visible. To overcome this, you could convert your listview into a circular listview, as described here.

Adding items into listview dynamically [duplicate]

In iOS, there is a very easy and powerful facility to animate the addition and removal of UITableView rows, here's a clip from a youtube video showing the default animation. Note how the surrounding rows collapse onto the deleted row. This animation helps users keep track of what changed in a list and where in the list they were looking at when the data changed.
Since I've been developing on Android I've found no equivalent facility to animate individual rows in a TableView. Calling notifyDataSetChanged() on my Adapter causes the ListView to immediately update its content with new information. I'd like to show a simple animation of a new row pushing in or sliding out when the data changes, but I can't find any documented way to do this. It looks like LayoutAnimationController might hold a key to getting this to work, but when I set a LayoutAnimationController on my ListView (similar to ApiDemo's LayoutAnimation2) and remove elements from my adapter after the list has displayed, the elements disappear immediately instead of getting animated out.
I've also tried things like the following to animate an individual item when it is removed:
#Override
protected void onListItemClick(ListView l, View v, final int position, long id) {
Animation animation = new ScaleAnimation(1, 1, 1, 0);
animation.setDuration(100);
getListView().getChildAt(position).startAnimation(animation);
l.postDelayed(new Runnable() {
public void run() {
mStringList.remove(position);
mAdapter.notifyDataSetChanged();
}
}, 100);
}
However, the rows surrounding the animated row don't move position until they jump to their new positions when notifyDataSetChanged() is called. It appears ListView doesn't update its layout once its elements have been placed.
While writing my own implementation/fork of ListView has crossed my mind, this seems like something that shouldn't be so difficult.
Thanks!
Animation anim = AnimationUtils.loadAnimation(
GoTransitApp.this, android.R.anim.slide_out_right
);
anim.setDuration(500);
listView.getChildAt(index).startAnimation(anim );
new Handler().postDelayed(new Runnable() {
public void run() {
FavouritesManager.getInstance().remove(
FavouritesManager.getInstance().getTripManagerAtIndex(index)
);
populateList();
adapter.notifyDataSetChanged();
}
}, anim.getDuration());
for top-to-down animation use :
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromYDelta="20%p" android:toYDelta="-20"
android:duration="#android:integer/config_mediumAnimTime"/>
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
android:duration="#android:integer/config_mediumAnimTime" />
</set>
The RecyclerView takes care of adding, removing, and re-ordering animations!
This simple AndroidStudio project features a RecyclerView. take a look at the commits:
commit of the classic Hello World Android app
commit, adding a RecyclerView to the project (content not dynamic)
commit, adding functionality to modify content of RecyclerView at runtime (but no animations)
and finally...commit adding animations to the RecyclerView
Take a look at the Google solution. Here is a deletion method only.
ListViewRemovalAnimation project code and Video demonstration
It needs Android 4.1+ (API 16). But we have 2014 outside.
Since ListViews are highly optimized i think this is not possible to accieve. Have you tried to create your "ListView" by code (ie by inflating your rows from xml and appending them to a LinearLayout) and animate them?
Have you considered animating a sweep to the right? You could do something like drawing a progressively larger white bar across the top of the list item, then removing it from the list. The other cells would still jerk into place, but it'd better than nothing.
call
listView.scheduleLayoutAnimation();
before changing the list
I hacked together another way to do it without having to manipulate list view. Unfortunately, regular Android Animations seem to manipulate the contents of the row, but are ineffectual at actually shrinking the view. So, first consider this handler:
private Handler handler = new Handler() {
#Override
public void handleMessage(Message message) {
Bundle bundle = message.getData();
View view = listView.getChildAt(bundle.getInt("viewPosition") -
listView.getFirstVisiblePosition());
int heightToSet;
if(!bundle.containsKey("viewHeight")) {
Rect rect = new Rect();
view.getDrawingRect(rect);
heightToSet = rect.height() - 1;
} else {
heightToSet = bundle.getInt("viewHeight");
}
setViewHeight(view, heightToSet);
if(heightToSet == 1)
return;
Message nextMessage = obtainMessage();
bundle.putInt("viewHeight", (heightToSet - 5 > 0) ? heightToSet - 5 : 1);
nextMessage.setData(bundle);
sendMessage(nextMessage);
}
Add this collection to your List adapter:
private Collection<Integer> disabledViews = new ArrayList<Integer>();
and add
public boolean isEnabled(int position) {
return !disabledViews.contains(position);
}
Next, wherever it is that you want to hide a row, add this:
Message message = handler.obtainMessage();
Bundle bundle = new Bundle();
bundle.putInt("viewPosition", listView.getPositionForView(view));
message.setData(bundle);
handler.sendMessage(message);
disabledViews.add(listView.getPositionForView(view));
That's it! You can change the speed of the animation by altering the number of pixels that it shrinks the height at once. Not real sophisticated, but it works!
After inserting new row to ListView, I just scroll the ListView to new position.
ListView.smoothScrollToPosition(position);
I haven't tried it but it looks like animateLayoutChanges should do what you're looking for. I see it in the ImageSwitcher class, I assume it's in the ViewSwitcher class as well?
Since Android is open source, you don't actually need to reimplement ListView's optimizations. You can grab ListView's code and try to find a way to hack in the animation, you can also open a feature request in android bug tracker (and if you decided to implement it, don't forget to contribute a patch).
FYI, the ListView source code is here.
Here's the source code to let you delete rows and reorder them.
A demo APK file is also available. Deleting rows is done more along the lines of Google's Gmail app that reveals a bottom view after swiping a top view. The bottom view can have an Undo button or whatever you want.
As i had explained my approach in my site i shared the link.Anyways the idea is create bitmaps
by getdrawingcache .have two bitmap and animate the lower bitmap to create the moving effect
Please see the following code:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
public void onItemClick(AdapterView<?> parent, View rowView, int positon, long id)
{
listView.setDrawingCacheEnabled(true);
//listView.buildDrawingCache(true);
bitmap = listView.getDrawingCache();
myBitmap1 = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), rowView.getBottom());
myBitmap2 = Bitmap.createBitmap(bitmap, 0, rowView.getBottom(), bitmap.getWidth(), bitmap.getHeight() - myBitmap1.getHeight());
listView.setDrawingCacheEnabled(false);
imgView1.setBackgroundDrawable(new BitmapDrawable(getResources(), myBitmap1));
imgView2.setBackgroundDrawable(new BitmapDrawable(getResources(), myBitmap2));
imgView1.setVisibility(View.VISIBLE);
imgView2.setVisibility(View.VISIBLE);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
lp.setMargins(0, rowView.getBottom(), 0, 0);
imgView2.setLayoutParams(lp);
TranslateAnimation transanim = new TranslateAnimation(0, 0, 0, -rowView.getHeight());
transanim.setDuration(400);
transanim.setAnimationListener(new Animation.AnimationListener()
{
public void onAnimationStart(Animation animation)
{
}
public void onAnimationRepeat(Animation animation)
{
}
public void onAnimationEnd(Animation animation)
{
imgView1.setVisibility(View.GONE);
imgView2.setVisibility(View.GONE);
}
});
array.remove(positon);
adapter.notifyDataSetChanged();
imgView2.startAnimation(transanim);
}
});
For understanding with images see this
Thanks.
I have done something similar to this. One approach is to interpolate over the animation time the height of the view over time inside the rows onMeasure while issuing requestLayout() for the listView. Yes it may be be better to do inside the listView code directly but it was a quick solution (that looked good!)
Just sharing another approach:
First set the list view's android:animateLayoutChanges to true:
<ListView
android:id="#+id/items_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"/>
Then I use a handler to add items and update the listview with delay:
Handler mHandler = new Handler();
//delay in milliseconds
private int mInitialDelay = 1000;
private final int DELAY_OFFSET = 1000;
public void addItem(final Integer item) {
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
new Thread(new Runnable() {
#Override
public void run() {
mDataSet.add(item);
runOnUiThread(new Runnable() {
#Override
public void run() {
mAdapter.notifyDataSetChanged();
}
});
}
}).start();
}
}, mInitialDelay);
mInitialDelay += DELAY_OFFSET;
}

Android Gallery control - need infinite loop of images

Without starting from the middle of the stack of images how do I rotate them in the infinite loop left to right and right to left? I tried setSelection(position) but for some reason I get that method called few times and inconsistently. My images increment has to be saved int he app state so it makes it a bit more complicated.
#Override
public void setSelection(int position){
int sectionPos = getCurrentPositionFromState();
if (sectionPos == (this._images - 1)){
setCurrentPositionFromState(0);
sectionPos = 0;
}
else {
setCurrentPositionInState(sectionPos +1);
}
if (sectionPos <= (this._images - 1) ){
super.setSelection(sectionPos);
}
}
gallery.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView parent, View view, int position, long id) {
gallery.setSelection(position);
#Override
public void onNothingSelected(AdapterView parent) {
}
});
I should also mention that I have an onFling() overriden like so:
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return super.onFling(e1, e2, 0, velocityY);
}
There are a few ways to go about it, but in all cases, it's never technically "infinite." I got the basis of mine from snooping around for a while.
First we need to put a gallery into the xml file in the layout. So after creating the file put in a little snippet like this:
<!-- Gallery To show images Gallery -->
< Gallery
android:id="#+id/galleryView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingBottom="15dip"/>
Now lets set up a Vector of different images so we can loop through. We will be getting these images from our resources, but if you want to get them from somewhere else then just insert that instead. We are going to insert this into onCreate(). This will allow us to have a vector of id's that we can reference when getting images to put into the gallery later:
public Vector<Integer> mPhotoVector = new Vector<Integer>();
public void setPhotos() {
for(as many photos as you want){
int imageResource = getResources().getIdentifier("imageNAme", "drawable", getPackageName());
mPhotoVector.add(imageResource);
}
Where galView is my gallery view from the layout. And as we finish up this project we need to call the gallery view from the xml and initialize it to a gallery variable we will have in the code.
LoopingGalleryAdapter adapter;
Gallery galView;
adapter = new LoopingGalleryAdapter(this, mPhotoVector);
galView = (LoopingGallery)mLayoutView.findViewById(R.id.galleryView);
galView.setAdapter(adapter);
galView.setSelection((galView.getCount() / 2));
The setSelection() will have us looking at the middle of the gallery, this makes it appear to be "infinite" since there are now 1073741823 elements to each side.
Next we need to create the adapter. The basis is to make the largest gallery you can, so next we just add in our own little getCount method. This will create a gallery that is too large for the user to (plausibly) scroll to the end of.
Lastly on the adapter we have the meat of the project which requires us to set where our position is. This is the key. Once the position is set to the middle-ish of the gallery, it seems as though you have an infinite loop of images on either side.
I started mine off a little like this:
public class LoopingGalleryAdapter extends BaseAdapter {
private ImageView iv;
private Context mContext;
public PhotoVector mPhotoVector = null;
int mGalleryItemBackground;
public LoopingGalleryAdapter(Context c, PhotoVector aVector) {
this.mContext = c;
mPhotoVector = aVector;
}
public int getCount() {
return Integer.MAX_VALUE;
}
#Override
public Object getItem(int position) {
return position;
}
public ImageView getImage(){
return iv;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
iv = new ImageView(mContext);
private final int middle = 1073741823; //this is the middle index of the gallery in galView
/************************************************************************
*if you have a vector/array/arrayList of photos you would like to display
************************************************************************/
if((position - middle) >= 0) { relativePosition = (position-middle) % mPhotoVector.size(); }
else { relativePosition = mPhotoVector.size() - (Math.abs(position - middle) % mPhotoVector.size()); }
Drawable draw = mContext.getResources().getDrawable(mPhotoVector.get(relativePosistion));
/*********************************************
*otherwise you can just insert a photo like so
*********************************************/
Drawable draw = mContext.getResources().getDrawable(R.drawable.what_you_want);
iv.setImageDrawable(draw);
return iv;
}
}
And we are now done!
Additionally, one of the tricks I have found quite useful, if not necessary when getting images from the internet is to keep a count of how many times you have gone through getView() and after 10-20 times clear your cache so you don't throw a OutOfMemoryError by doing:
if(counter >= 20){
galView.destroyDrawingCache();
counter = 0;
}
Or have getView() throw a OutOfMemoryError, catch it and return an empty ImageView (iv) and then clear then call galView.destroyDrawingCache();
A shameless self plug, just wrote an Infinite Scrolling Gallery tutorial:
http://blog.blundellapps.com/infinite-scrolling-gallery/
Source code can be downloaded also, you choose the image size.
You can use images on your SD card or images in your /resources/drawable directory.

Categories

Resources