Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

By the power of MergeAdapter, StickyListHeaders and ListViewAnimations combined I'm captain Android

Has anyone joined MergeAdapter, StickyListHeaders and ListViewAnimations android libraries?

My needs are:

  • multiple ListViews in one vertically scrolled view
  • heterogenous item views
  • multiple list items separated by headers, which should be sticky
  • ability to expand some list items
  • drag'n'drop some of them
  • support android 14+

My extras:

  • rely on CursorAdapters

Cherrypick:

  • sometimes my very top header (which is separate view not part of my list and I'll prefer it to stay that way) need to slide a bit over to the top; my combined list should follow but in the same time animate extend of it's height in order to always be attached to a bottom.

Mentioned libraries were:

  • MergeAdapter - https://github.com/commonsguy/cwac-merge
  • StickyListHeaders - https://github.com/emilsjolander/StickyListHeaders
  • ListViewAnimations - https://github.com/nhaarman/ListViewAnimations

Please give me some hope if it's possible and some useful tips how to avoid pitfalls. Maybe I should use some other libs. Or I'll just have to write that myself :(

====EDITED====

In the end I have managed to build a stub of what I was hoping to do (in early 2014). It is functional expandable and draggable listview and adapter lib with nice animations (no sticky headers yet). Here's repo:

  • https://github.com/fada21/HydraListAndroid

Since RecyclerView is now available there's no need to use overcomplicated listview code. Here is quick switch guide - http://andraskindler.com/2014/11/22/migrating-to-recyclerview/.

like image 285
fada21 Avatar asked Dec 06 '13 22:12

fada21


2 Answers

From the ListViewAnimations wiki: http://nhaarman.github.io/ListViewAnimations/#getting-started

ListViewAnimations also supports appearance animations on StickyListHeaderListViews. You must wrap your AnimationAdapter in a StickyListHeadersAdapterDecorator:

StickyListHeadersListView listView = (...); AlphaInAnimationAdapter
animationAdapter = new AlphaInAnimationAdapter(adapter);
StickyListHeadersAdapterDecorator stickyListHeadersAdapterDecorator =
new StickyListHeadersAdapterDecorator(animationAdapter);
stickyListHeadersAdapterDecorator.setStickyListHeadersListView(listView);
listView.setAdapter(stickyListHeadersAdapterDecorator); 

Just like with the normal ListView, you can use any implementation of the AnimationAdapter class.

In combination with the solution from StickyListHeaders and MergeAdapter the uber-mergeadapter should be a possiblity :P

like image 162
MrMaffen Avatar answered Oct 23 '22 01:10

MrMaffen


I ended up creating an adapter to handle the headers.

Using the adapter class:

StickyHeaderMergeAdapter stickyHeaderMergeAdapter = new StickyHeaderMergeAdapter(this.getActivity(), R.layout.list_item_header, R.id.text1);
stickyHeaderMergeAdapter.addAdapter(
                myTypcalAdapter,
                R.string.stringName
);
this.stickyHeaderListView.setAdapter(stickyHeaderMergeAdapter);

The Adapter class:

package mypackagename.widget;

import android.content.Context;
import android.support.annotation.IdRes;
import android.support.annotation.LayoutRes;
import android.support.annotation.StringRes;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;
import android.widget.TextView;

import com.commonsware.cwac.merge.MergeAdapter;
import org.apache.commons.lang3.NotImplementedException;
import java.util.LinkedHashMap;

import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter;

public class StickyHeaderMergeAdapter extends MergeAdapter implements StickyListHeadersAdapter {
    private final LinkedHashMap<ListAdapter,Integer> adapterViewHashMap = new LinkedHashMap<>();
    private final Context context;
    private final int headerLayoutId;
    private final int headerLayoutTextId;

    public StickyHeaderMergeAdapter(Context context, @LayoutRes int headerLayoutId, @IdRes int headerLayoutTextId) {
        this.context = context;
        this.headerLayoutId = headerLayoutId;
        this.headerLayoutTextId = headerLayoutTextId;
    }

    public void addAdapter(ListAdapter listAdapter, @StringRes int stringId) {
        super.addAdapter(listAdapter);
        this.adapterViewHashMap.put(listAdapter, stringId);
    }

    @Override
    public void addAdapter(ListAdapter adapter) {
        throw new NotImplementedException("You should use addAdapter(ListAdapter, View)");
    }

    @Override
    public View getHeaderView(int position, View convertView, ViewGroup parent) {
        if (convertView == null)
            convertView = View.inflate(this.context, this.headerLayoutId, null);

        ((TextView) convertView.findViewById(this.headerLayoutTextId)).setText(
                this.adapterViewHashMap.get(this.getAdapter(position))
        );

        return convertView;
    }

    @Override
    public long getHeaderId(int i) {
        ListAdapter listAdapter = this.getAdapter(i);
        if (!this.adapterViewHashMap.containsKey(listAdapter))
            return 0;

        return this.adapterViewHashMap.get(listAdapter);
    }
}
like image 35
vangorra Avatar answered Oct 23 '22 02:10

vangorra