Skip to content

Instantly share code, notes, and snippets.

@lucasr
Last active November 20, 2017 19:02
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lucasr/9508647 to your computer and use it in GitHub Desktop.
Save lucasr/9508647 to your computer and use it in GitHub Desktop.
Animated ListView with TransitionManager
<ListView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="org.lucasr.transition.samples.MainActivity"/>
package org.lucasr.transition.samples;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.transition.TransitionManager;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView;
import java.util.Random;
public class MainActivity extends ActionBarActivity {
private ListView listView;
private TransitionAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.list);
adapter = new SomeAdapter(this);
adapter.add("One");
adapter.add("Another");
listView.setAdapter(adapter);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
final int id = item.getItemId();
if (id == R.id.action_add) {
TransitionManager.beginDelayedTransition(listView);
adapter.add(1, "New item");
return true;
} else if (id == R.id.action_remove) {
TransitionManager.beginDelayedTransition(listView);
adapter.remove(1);
return true;
}
return super.onOptionsItemSelected(item);
}
}
package org.lucasr.transition.samples;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class SomeAdapter extends BaseAdapter {
private static class Item {
public final long id;
public final String value;
public Item(long id, String value) {
this.id = id;
this.value = value;
}
}
private final Context context;
private final List<Item> items = new ArrayList<Item>();
private int currentId = 0;
public SomeAdapter(Context context) {
super();
this.context = context;
}
@Override
public int getCount() {
return items.size();
}
@Override
public Object getItem(int position) {
return items.get(position);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.text_item, parent, false);
}
Item item = items.get(position);
((TextView) convertView).setText(item.value + " (" + item.id + ")");
return convertView;
}
@Override
public long getItemId(int position) {
return items.get(position).id;
}
@Override
public boolean hasStableIds() {
return true;
}
private Item createItem(String value) {
long id = ++currentId;
return new Item(id, value);
}
public void add(String value) {
items.add(createItem(value));
notifyDataSetChanged();
}
public void add(int index, String value) {
items.add(index, createItem(value));
notifyDataSetChanged();
}
public void remove(int index) {
items.remove(index);
notifyDataSetChanged();
}
}
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center"
android:layout_margin="2dp"
android:paddingLeft="64dp"
android:paddingRight="64dp"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:background="#ffcc00"/>
@keyboardr
Copy link

If the Adapter can get a reference to the ListView, is there anything stopping you from calling TransitionManager.beginDelayedTransition(listView) in notifyDataSetChanged()? I'd like to do this in a ListView populated by a CursorAdapter where the contents can change at any time.

@imminent
Copy link

@keyboardr It's better to leave it in the ListView or Activity, and use PageAdapter.registerDataSetObserver(DataSetObserver) to register to be notified with notifyDataSetChanged() is triggered. Then you can do the TransitionManager.beginDelayedTransition(listView) there. You really don't want the adapter to deal with the ListView.

@imminent
Copy link

@lucasr You have SomeAdapter as the class name, but elsewhere (including the constructor) you say TransitionAdapter (line 14 of SomeAdapter.java). Do you mean for them to always say TransitionAdapter instead of SomeAdapter?

@slidenerd
Copy link

well a good approach but you wont be needing this anymore since the RecyclerView has come into the picture, it supports 2 types of animations 1) Animators that manage structural or data change and animate them and 2)Animations that you can apply on the ViewHolder root inside onBindViewHolder for animating how the recyclerview is loaded

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment