ListViewAnimations library - Animate additions? - android

I've been having trouble implementing the animate additions functionality of nhaarman's ListViewAnimations library.
As specified in the wiki, I'm using the DynamicListView, and my ArrayAdapter implements Insertable.
However, things aren't working. A couple of questions:
Do I use a normal ArrayAdapter or do I have to use the library's ArrayAdapter? I've tried both. I suspect the correct answer is to use a normal ArrayAdapter and override the following function:
public void add(int i, #NonNull Comment comment)
If that's the case, what do I have to put inside this function? notifyDataSetChanged()?
Do I have to wrap my adapter in of the AnimationAdapters?

Related

RecyclerView 1.2.0-alpha02: setting shared RecycledViewPool to RV makes MergeAdapter crash and view types in other screens inconsistent

I use shared RecycledViewPool between some Fragments. I decided to try out MergeAdapter in one fragment. For that screen, I created a separate adapter for each viewType and overrode getItemViewType method to return layout ID as view type.
When I go to any other screen that has shared RecycledViewPool but is not using MergeAdapter I see some of the viewHolders from previous screen showing up. When I return back app crashes and in logs I see ClassCastException saying that ViewHolder1 cannot be casted to ViewHolder2.
My code looks like this:
recyclerView.setRecycledViewPool(sharedViewPool)
val adapter = MergeAdapter(adapter1, adapter2, adapter3, adapter4)
recyclerView.adapter = adapter
How to keep shared RecycledViewPool, but eliminate ClassCastException and stop showing ViewHolders in other screens where they should not be shown?
After digging more into the documentation I found that the problem was MergeAdapter with default configuration.
from documentation:
By default, MergeAdapter isolates view types of nested adapters from each other such that it will change the view type before reporting it back to the RecyclerView to avoid any conflicts between the view types of added adapters. This also means each added adapter will have its own isolated pool of RecyclerView.ViewHolders, with no re-use in between added adapters.
If your RecyclerView.Adapters share the same view types, and can support sharing RecyclerView.ViewHolder s between added adapters, provide an instance of MergeAdapter.Config where you set MergeAdapter.Config.isolateViewTypes to false. A common usage pattern for this is to return the R.layout. from the RecyclerView.Adapter.getItemViewType(int) method.
I also read this in article written by Florina Muntenescu and for some reason I thought that isolateViewTypes is only affecting adapters added to one MergeAdapter. But since in default config it will modify returned view types for each ViewHolder it might (most likely will) cause inconsistency in shared RecycledViewPool. Not sure if it is a bug or expected behaviour. Would be great to hear something from team working on RecyclerView.
Solution was setting isolateViewTypes to false.
val adapter = MergeAdapter(
MergeAdapter.Config.Builder().setIsolateViewTypes(false).build(),
adapter1,
adapter2,
adapter3,
adapter4
)
I think it is pretty easy mistake to make and I hope this solution will save some time for others.

Butterknife OnClick with TabLayout

I just got a hold of Butterknife and have been trying my best to standardize all of my 'OnClick's to be bound via Butterknife.
I have found though, that it's difficult to follow Butterknife's standard binding pattern when dynamically populating views (via adapters for example) since the individual views don't have id's
#OnClick(What Do I put here if I have no ID?)
public void OnClickMethod(View view) {
//Body
}
Specifically, I'm having problems adding onClicks to views that are part of a TabLayout. I know I can use the built in
TabLayout.setOnTabSelectedListener()
But ideally I'd like to be consistent in binding all forms of onClick via Butterknife. Is there a clean way of doing this?
Set an id in res/values/ids.xml like :
<item name="my_view" type="id"/>
And then add the id to the view :
myView.setId(R.id.my_view);
#OnClick(R.id.my_view)
public void OnClickMethod(View view) {
//Body
}

PullToRefresh list with pinned section header

Does anyone has practice of using Pull to refresh list with Pinned section header?
I use Android-PullToRefresh lib with my list and I want to add ability of showing pinned section header at the top of list. I used PinnedHeaderListView lib in another project for pinned section. But I can't combine these two libraries into one.
Is Android-PullToRefresh can show pinned section header? Perhaps any other Pull to refresh lib can do it?
It's possible to integrate the Actionbar-PullToRefresh library with the StickyListHeaders library, but you need to use a custom Delegate in order to get Actionbar-PullToRefresh to work correctly:
public class StickyListViewDelegate extends AbsListViewDelegate {
#Override public boolean isReadyForPull(View view, final float x, final float y) {
StickyListHeadersListView sticky = (StickyListHeadersListView) view;
return super.isReadyForPull(sticky.getWrappedList(), x, y);
}
Integrated like so:
StickyListViewDelegate delegate = new StickyListViewDelegate();
ActionBarPullToRefresh.from(getActivity()).theseChildrenArePullable(mListView)
.useViewDelegate(StickyListHeadersListView.class, delegate)
.listener(this).setup(mPullToRefreshLayout);
The reason that the two libraries don't work together is because the StickyListHeadersListView class does not actually extend ListView (which is what the Actionbar-PullToRefresh library looks for when assigning a delegate by default).
I did some research and I found 2 alternatives:
StickyListHeaders. This library is contributed by Jake Wharton (reference) so it is promising and could be compatible with other libraries. You should try to use it.
PinnedSectionListView - easy to use ListView with pinned sections for Android.
You can try combining these two libraries with ActionBar-PullToRefresh. I suppose you can implement the solution ;)
You can use a combination of SwipeRefreshLayout of support-library and the PinnedHeaderListview.
In your XML file, use like following:
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/pinned_lisview_container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<za.co.immedia.pinnedheaderlistview.PinnedHeaderListView
android:id="#+id/event_items_lisview"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</za.co.immedia.pinnedheaderlistview.PinnedHeaderListView>
</android.support.v4.widget.SwipeRefreshLayout>
And then in java code, just write codes for your PinnedHeaderListView as usual. Finally just put a Refresh Listener for your SwipeRefreshLayout like below:
pinned_lisview_container
.setOnRefreshListener(new OnRefreshListener() {
#Override
public void onRefresh() {
// do your refresh tasks here
}
});
You are done.
SwipeRefreshLayout + any other suitable library that you would use can do the job.
I would prefer PinnedSectionListView beacuse it uses Listview and it has it its pros in terms of UI/UX.

How to extend a complex Android view like the GridView?

Background:
I'm looking for a way to extend the GridView I need implement a col- and row-span like in HTML. I have hunderds of elements so I cannot use e.g. a TableLayout. However that would be too localized. So far I reduce the question to how to extend the GridView?
What I have tried and where I have failed:
My first approach was to look which methods I need to replace and I found some private methods which cannot be overriden. So I tried to copy the hole source code from the GridView to a new class called CustomGrid. That was a terrible failure since I cannot access the com.android.internal.R class.
Then I dropped that idea and looked if I can normal extend the class and replace all the private methods with custom copies. I took a pen and build a huge tree where all methods are used.
After I found all references I tried to extend the class normal and I added the first method:
private View fillDown(int pos, int nextTop) {
View selectedView = null;
int end = (mBottom - mTop);
if((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) {
end -= mListPadding.bottom;
}
// ...
Here is my next problem that member variables mBottom and mTop are unknown. I digged a little through the sources and found them finally in the View class, but unfortunately they are hidden.
/**
* The distance in pixels from the top edge of this view's parent
* to the bottom edge of this view.
* {#hide}
*/
#ViewDebug.ExportedProperty(category = "layout")
protected int mBottom;
Question:
How can I extend the GridView without hitting that lamentations and without the usage of massive reflection? I mean it seems to be impossible to write that as a pure custom control.
How can I extend the GridView without hiting that limentations and without the usage of massive reflection?
Most likely, you don't. You copy the code into your project and modify to suit, including all requisite superclasses (up to ViewGroup). I will be stunned if you can achieve your aims by a simple subclass of GridView. You may even have to completely write your desired widget from scratch.
That was a terrible failior due I cannot access the com.android.internal.R class.
You will also need to copy over relevant resources, then fix up R references to point to your own resources.
but unforcantly they are hidden.
You find other ways of getting this data. mBottom, for example, can be changed to getBottom().

Drag and drop sorting of cursor adapter and list adapter

I'm very surprised there is such a small amount of info on drag and drop sorting with a cursor adapter and list adapter.
The closest post I have found on stackoverflow is this one:
https://stackoverflow.com/a/5047618/317889
But, it's not clear to me how to implement what CommonsWare suggests - clarification would be very helpful.
So far I am binding the cursor data to a list adapter and setting this as follows:
mMyCursorAdapter = new MyCursorAdapter(getActivity(), null);
setListAdapter(mMyCursorAdapter);
getLoaderManager().initLoader(0, null, this);
The list is generated but I now wish to add drag and drop functionality to the list items.
I would like to know the best way to go about this from an architectural point of view and any pointers as to how to go about the development of the core functionality would also be useful.
This blog post by Jason McReynolds (including a sample project) helped me a whole lot.
It explains how to use Carl A. Bauer's Library Drag-Sort-ListView with a CursorAdapter and SqLite. It shows how to save the the ListView's newly ordered state in the database as well.
This can definitely be achieved and lucky for you most of the work has already been taken care of, but you will need to modify a class slightly to meet your specifications.
The default Android music app has all of the classes you'll need.
First, you'll need to grab their custom ListView that allows for dragging and dropping.
That can be found here - TouchInterceptor.java.
You'll also need to grab their custom Cursor that's used to actually move the items in your ListView. It's an inner class called NowPlayingCursor.
That can be found here - TrackBrowserActivity.java
NowPlayingCursor extends AbstractCursor and its used to return the queue. The method makeNowPlayingCursor() is specifcally where you'll write most of your own code. Instead of returning the queue, you'll need to return the items you interested in moving, whatever they may be.
In order to use the TouchInterceptor, you'll need to implement TouchInterceptor.DropListener.
private TouchInterceptor.DropListener mDropListener =
new TouchInterceptor.DropListener() {
public void drop(int from, int to) {
final NowPlayingCursor mNowPlayingCursor = (NowPlayingCursor) YOUR_CURSOR;
mNowPlayingCursor.moveItem(from, to);
// Call `notifyDataSetChanged` here.
}
};
You should also look their moveQueueItem method used to move an item from one index to another. This method is used in the NowPlayingCursor when onMove and moveItem are called.
That can be found here - MediaPlaybackService.java
So, there's some work to be done on your part, but this definitely possible.
Here is a library that hopefully will solve your problem, it enables drag and drop reordering of list items.
Has an excellent demo that includes use cases for Fragments and Cursors
https://github.com/bauerca/drag-sort-listview
Key features:
Clean drag and drop (no visual glitches; I hope!).
Intuitive and smooth scrolling while dragging.
Support for heterogeneous item heights.
Public startDrag() and stopDrag() methods.
Public interface for customizing the floating View.

Categories

Resources