package org.wikipedia.feed.view;
import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.AttributeSet;
import android.view.View;
import org.wikipedia.R;
import org.wikipedia.crash.RemoteLogException;
import org.wikipedia.util.log.L;
import org.wikipedia.views.AutoFitRecyclerView;
import org.wikipedia.views.HeaderMarginItemDecoration;
import org.wikipedia.views.ItemTouchHelperSwipeAdapter;
import org.wikipedia.views.MarginItemDecoration;
public class FeedView extends AutoFitRecyclerView {
private StaggeredGridLayoutManager recyclerLayoutManager;
@Nullable private ItemTouchHelper itemTouchHelper;
public FeedView(Context context) {
super(context);
init();
}
public FeedView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public FeedView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public void setCallback(@Nullable ItemTouchHelperSwipeAdapter.Callback callback) {
if (itemTouchHelper != null) {
itemTouchHelper.attachToRecyclerView(new DummyView(getContext()));
itemTouchHelper = null;
}
if (callback != null) {
itemTouchHelper = new ItemTouchHelper(new ItemTouchHelperSwipeAdapter(callback));
itemTouchHelper.attachToRecyclerView(this);
}
}
public int getFirstVisibleItemPosition() {
StaggeredGridLayoutManager manager = ((StaggeredGridLayoutManager) getLayoutManager());
int[] visibleItems = new int[manager.getSpanCount()];
manager.findFirstVisibleItemPositions(visibleItems);
return visibleItems[0];
}
private void init() {
setVerticalScrollBarEnabled(true);
recyclerLayoutManager = new StaggeredGridLayoutManager(getColumns(),
StaggeredGridLayoutManager.VERTICAL);
setLayoutManager(recyclerLayoutManager);
addItemDecoration(new MarginItemDecoration(getContext(),
R.dimen.view_list_card_margin_horizontal, R.dimen.view_list_card_margin_vertical,
R.dimen.view_list_card_margin_horizontal, R.dimen.view_list_card_margin_vertical));
addItemDecoration(new HeaderMarginItemDecoration(getContext(),
R.dimen.view_feed_padding_top));
setCallback(new RecyclerViewColumnCallback());
}
/* Workaround for https://code.google.com/p/android/issues/detail?id=205947.
ItemTouchHelper.attachToRecyclerView(null) should remove its gesture callback before nulling
its RecyclerView:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.support.v7.widget.RecyclerView.findChildViewUnder(float, float)' on a null object reference
at android.support.v7.widget.helper.ItemTouchHelper.findChildView(ItemTouchHelper.java:1024)
at android.support.v7.widget.helper.ItemTouchHelper.access$2400(ItemTouchHelper.java:76)
at android.support.v7.widget.helper.ItemTouchHelper$ItemTouchHelperGestureListener.onLongPress(ItemTouchHelper.java:2265)
at android.view.GestureDetector.dispatchLongPress(GestureDetector.java:770)
at android.view.GestureDetector.-wrap0(GestureDetector.java)
at android.view.GestureDetector$GestureHandler.handleMessage(GestureDetector.java:293)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
*/
private static class DummyView extends RecyclerView {
DummyView(Context context) {
super(context);
}
@Override public View findChildViewUnder(float x, float y) {
L.logRemoteError(new RemoteLogException("ItemTouchHelper.attachToRecyclerView(null)"));
return super.findChildViewUnder(x, y);
}
}
private class RecyclerViewColumnCallback implements AutoFitRecyclerView.Callback {
@Override public void onColumns(int columns) {
// todo: when there is only one element, should we setSpanCount to 1? e.g.:
// adapter.getItemCount() <= 1 ? 1 : columns;
// we would need to also notify the layout manager when the data set changes
// though.
recyclerLayoutManager.setSpanCount(columns);
}
}
}