O ListView do Instagram tem um efeito de rolagem muito interessante, conforme rolamos a lista o ‘cabeçalho’ de cada item fica fixo até o cabeçalho do próximo item chegar e tomar o seu lugar (conforme a imagem acima).
O Segredo está no item da lista e na implementação da interface AbsListView.OnScrollListener para escutarmos a rolagem da lista.
Vamos criar um item da lista, com um título e conteúdo. O título deve estar acima do conteúdo, portanto, ele deve ser o último elemento em uma RelativeLayout
. Além disso, a criação android:layout_alignParentTop
em título iria tentar aplicar a regra sempre que os parâmetros de layout mudar. Por isso, é melhor não adicionar a regra:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" > <TextView android:id="@+id/content" android:layout_width="fill_parent" android:layout_height="150dp" android:layout_marginTop="50dp" android:gravity="center"/> <TextView android:id="@+id/title" android:layout_width="fill_parent" android:layout_height="50dp" android:background="#CC249ad6" /> </RelativeLayout>
Agora vamos tratar o deslocamento da lista. Porem devemos tratar alguns casos.
O Listener é chamado mesmo quando o ListView não está rolando (SCROLL_STATE_IDLE). Neste caso nao devemos alterar o layout.
Quando o usuário rola para baixo é provavel que o título não alcançou o topo e mudou-se para ser o segundo item visível da lista, neste caso não vamos repor a margem superior do título. Por isso, devemos repor a margem superior da exibição de todos os títulos visíveis, exceto a primeira.
listView.setOnScrollListener(new OnScrollListener() { int mScrollState = OnScrollListener.SCROLL_STATE_IDLE; @Override public void onScrollStateChanged(AbsListView view, int scrollState) { mScrollState = scrollState; } @Override public void onScroll(AbsListView list, int firstItem, int visibleCount, int totalCount) { // se a lista não estiver se movimentando. if (mScrollState == OnScrollListener.SCROLL_STATE_IDLE) { return; } // percorre todos os itens visíveis. for (int i = 0; i < visibleCount; i++) { View listItem = list.getChildAt(i); if (listItem == null) { break; } TextView title = (TextView) listItem .findViewById(R.id.title); int topMargin = 0; // Primeiro item da lista. if (i == 0) { int top = listItem.getTop(); int height = listItem.getHeight(); // Se for negativo a lista foi rolada para cima. if (top < 0) { // se o título está dentro parte visível do // recipiente, coloque a margem superior para ser a // (inverso) quantidade rolada do recipiente. if (title.getHeight() < (top + height)) { topMargin = -top; } else { // define a margem superior com a diferença // entre as alturas. topMargin = height - title.getHeight(); } } } // Define a marginTop do titulo. ((ViewGroup.MarginLayoutParams) title.getLayoutParams()).topMargin = topMargin; listItem.requestLayout(); } } });
Pronto, com isso conseguimos implementar nosso InstaListView tranquilamente, nesse exemplo eu não implementei o adapter porque ele não sofre alterações, deve ser feito normalmente.
Segue o link do exemplo: (InstaListView)
Fonte: http://goo.gl/U4ej7p