Use RecyclerView for catalogue
This commit is contained in:
parent
453a187938
commit
868058a50b
8 changed files with 186 additions and 123 deletions
|
@ -77,32 +77,31 @@ public class Manga implements Serializable {
|
||||||
this.url = UrlUtil.getPath(url);
|
this.url = UrlUtil.getPath(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void copyFromNetwork(Manga local, Manga network) {
|
public void copyFrom(Manga other) {
|
||||||
if (network.title != null)
|
if (other.title != null)
|
||||||
local.title = network.title;
|
title = other.title;
|
||||||
|
|
||||||
if (network.author != null)
|
if (other.author != null)
|
||||||
local.author = network.author;
|
author = other.author;
|
||||||
|
|
||||||
if (network.artist != null)
|
if (other.artist != null)
|
||||||
local.artist = network.artist;
|
artist = other.artist;
|
||||||
|
|
||||||
if (network.url != null)
|
if (other.url != null)
|
||||||
local.url = network.url;
|
url = other.url;
|
||||||
|
|
||||||
if (network.description != null)
|
if (other.description != null)
|
||||||
local.description = network.description;
|
description = other.description;
|
||||||
|
|
||||||
if (network.genre != null)
|
if (other.genre != null)
|
||||||
local.genre = network.genre;
|
genre = other.genre;
|
||||||
|
|
||||||
if (network.thumbnail_url != null)
|
if (other.thumbnail_url != null)
|
||||||
local.thumbnail_url = network.thumbnail_url;
|
thumbnail_url = other.thumbnail_url;
|
||||||
|
|
||||||
local.status = network.status;
|
status = other.status;
|
||||||
|
|
||||||
local.initialized = true;
|
|
||||||
|
|
||||||
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -3,71 +3,58 @@ package eu.kanade.mangafeed.ui.catalogue;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import butterknife.Bind;
|
import eu.davidea.flexibleadapter.FlexibleAdapter;
|
||||||
import butterknife.ButterKnife;
|
|
||||||
import eu.kanade.mangafeed.R;
|
import eu.kanade.mangafeed.R;
|
||||||
import eu.kanade.mangafeed.data.database.models.Manga;
|
import eu.kanade.mangafeed.data.database.models.Manga;
|
||||||
|
|
||||||
public class CatalogueAdapter extends ArrayAdapter<Manga> {
|
public class CatalogueAdapter extends FlexibleAdapter<CatalogueHolder, Manga> {
|
||||||
|
|
||||||
private CatalogueFragment fragment;
|
private CatalogueFragment fragment;
|
||||||
private LayoutInflater inflater;
|
|
||||||
|
|
||||||
public CatalogueAdapter(CatalogueFragment fragment) {
|
public CatalogueAdapter(CatalogueFragment fragment) {
|
||||||
super(fragment.getActivity(), 0, new ArrayList<>());
|
|
||||||
this.fragment = fragment;
|
this.fragment = fragment;
|
||||||
inflater = fragment.getActivity().getLayoutInflater();
|
mItems = new ArrayList<>();
|
||||||
|
setHasStableIds(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addItems(List<Manga> list) {
|
||||||
|
mItems.addAll(list);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
mItems.clear();
|
||||||
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View getView(int position, View view, ViewGroup parent) {
|
public long getItemId(int position) {
|
||||||
Manga manga = getItem(position);
|
return mItems.get(position).id;
|
||||||
|
|
||||||
ViewHolder holder;
|
|
||||||
if (view != null) {
|
|
||||||
holder = (ViewHolder) view.getTag();
|
|
||||||
} else {
|
|
||||||
view = inflater.inflate(R.layout.item_catalogue, parent, false);
|
|
||||||
holder = new ViewHolder(view, fragment);
|
|
||||||
view.setTag(holder);
|
|
||||||
}
|
|
||||||
holder.onSetValues(manga);
|
|
||||||
return view;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class ViewHolder {
|
@Override
|
||||||
@Bind(R.id.title) TextView title;
|
public void updateDataSet(String param) {
|
||||||
@Bind(R.id.thumbnail) ImageView thumbnail;
|
|
||||||
@Bind(R.id.favorite_sticker) ImageView favorite_sticker;
|
|
||||||
|
|
||||||
CataloguePresenter presenter;
|
|
||||||
|
|
||||||
public ViewHolder(View view, CatalogueFragment fragment) {
|
|
||||||
ButterKnife.bind(this, view);
|
|
||||||
presenter = fragment.getPresenter();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onSetValues(Manga manga) {
|
|
||||||
title.setText(manga.title);
|
|
||||||
|
|
||||||
if (manga.thumbnail_url != null) {
|
|
||||||
presenter.coverCache.loadFromCacheOrNetwork(thumbnail, manga.thumbnail_url,
|
|
||||||
presenter.getSource().getGlideHeaders());
|
|
||||||
} else {
|
|
||||||
thumbnail.setImageResource(android.R.color.transparent);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (manga.favorite) {
|
|
||||||
favorite_sticker.setVisibility(View.VISIBLE);
|
|
||||||
} else {
|
|
||||||
favorite_sticker.setVisibility(View.INVISIBLE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CatalogueHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
|
LayoutInflater inflater = fragment.getActivity().getLayoutInflater();
|
||||||
|
View v = inflater.inflate(R.layout.item_catalogue, parent, false);
|
||||||
|
return new CatalogueHolder(v, this, fragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(CatalogueHolder holder, int position) {
|
||||||
|
final Manga manga = getItem(position);
|
||||||
|
holder.onSetValues(manga, fragment.getPresenter());
|
||||||
|
|
||||||
|
//When user scrolls this bind the correct selection status
|
||||||
|
//holder.itemView.setActivated(isSelected(position));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@ package eu.kanade.mangafeed.ui.catalogue;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.support.v7.widget.GridLayoutManager;
|
||||||
import android.support.v7.widget.SearchView;
|
import android.support.v7.widget.SearchView;
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
@ -14,8 +16,6 @@ import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.GridView;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.Spinner;
|
import android.widget.Spinner;
|
||||||
|
|
||||||
|
@ -24,15 +24,16 @@ import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import butterknife.Bind;
|
import butterknife.Bind;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import butterknife.OnItemClick;
|
|
||||||
import eu.kanade.mangafeed.R;
|
import eu.kanade.mangafeed.R;
|
||||||
import eu.kanade.mangafeed.data.database.models.Manga;
|
import eu.kanade.mangafeed.data.database.models.Manga;
|
||||||
import eu.kanade.mangafeed.data.source.base.Source;
|
import eu.kanade.mangafeed.data.source.base.Source;
|
||||||
|
import eu.kanade.mangafeed.ui.base.adapter.FlexibleViewHolder;
|
||||||
import eu.kanade.mangafeed.ui.base.fragment.BaseRxFragment;
|
import eu.kanade.mangafeed.ui.base.fragment.BaseRxFragment;
|
||||||
import eu.kanade.mangafeed.ui.main.MainActivity;
|
import eu.kanade.mangafeed.ui.main.MainActivity;
|
||||||
import eu.kanade.mangafeed.ui.manga.MangaActivity;
|
import eu.kanade.mangafeed.ui.manga.MangaActivity;
|
||||||
import eu.kanade.mangafeed.util.ToastUtil;
|
import eu.kanade.mangafeed.util.ToastUtil;
|
||||||
import eu.kanade.mangafeed.widget.EndlessScrollListener;
|
import eu.kanade.mangafeed.widget.AutofitRecyclerView;
|
||||||
|
import eu.kanade.mangafeed.widget.EndlessRecyclerScrollListener;
|
||||||
import icepick.State;
|
import icepick.State;
|
||||||
import nucleus.factory.RequiresPresenter;
|
import nucleus.factory.RequiresPresenter;
|
||||||
import rx.Subscription;
|
import rx.Subscription;
|
||||||
|
@ -40,16 +41,16 @@ import rx.android.schedulers.AndroidSchedulers;
|
||||||
import rx.subjects.PublishSubject;
|
import rx.subjects.PublishSubject;
|
||||||
|
|
||||||
@RequiresPresenter(CataloguePresenter.class)
|
@RequiresPresenter(CataloguePresenter.class)
|
||||||
public class CatalogueFragment extends BaseRxFragment<CataloguePresenter> {
|
public class CatalogueFragment extends BaseRxFragment<CataloguePresenter> implements FlexibleViewHolder.OnListItemClickListener {
|
||||||
|
|
||||||
@Bind(R.id.gridView) GridView gridView;
|
@Bind(R.id.recycler) AutofitRecyclerView recycler;
|
||||||
@Bind(R.id.progress) ProgressBar progress;
|
@Bind(R.id.progress) ProgressBar progress;
|
||||||
@Bind(R.id.progress_grid) ProgressBar progressGrid;
|
@Bind(R.id.progress_grid) ProgressBar progressGrid;
|
||||||
|
|
||||||
private Toolbar toolbar;
|
private Toolbar toolbar;
|
||||||
private Spinner spinner;
|
private Spinner spinner;
|
||||||
private CatalogueAdapter adapter;
|
private CatalogueAdapter adapter;
|
||||||
private EndlessScrollListener scrollListener;
|
private EndlessRecyclerScrollListener scrollListener;
|
||||||
|
|
||||||
@State String query = "";
|
@State String query = "";
|
||||||
@State int selectedIndex = -1;
|
@State int selectedIndex = -1;
|
||||||
|
@ -75,10 +76,12 @@ public class CatalogueFragment extends BaseRxFragment<CataloguePresenter> {
|
||||||
ButterKnife.bind(this, view);
|
ButterKnife.bind(this, view);
|
||||||
|
|
||||||
// Initialize adapter and scroll listener
|
// Initialize adapter and scroll listener
|
||||||
|
GridLayoutManager layoutManager = (GridLayoutManager) recycler.getLayoutManager();
|
||||||
adapter = new CatalogueAdapter(this);
|
adapter = new CatalogueAdapter(this);
|
||||||
scrollListener = new EndlessScrollListener(this::requestNextPage);
|
scrollListener = new EndlessRecyclerScrollListener(layoutManager, this::requestNextPage);
|
||||||
gridView.setAdapter(adapter);
|
recycler.setHasFixedSize(true);
|
||||||
gridView.setOnScrollListener(scrollListener);
|
recycler.setAdapter(adapter);
|
||||||
|
recycler.addOnScrollListener(scrollListener);
|
||||||
|
|
||||||
// Create toolbar spinner
|
// Create toolbar spinner
|
||||||
Context themedContext = getBaseActivity().getSupportActionBar() != null ?
|
Context themedContext = getBaseActivity().getSupportActionBar() != null ?
|
||||||
|
@ -192,9 +195,7 @@ public class CatalogueFragment extends BaseRxFragment<CataloguePresenter> {
|
||||||
|
|
||||||
query = newQuery;
|
query = newQuery;
|
||||||
showProgressBar();
|
showProgressBar();
|
||||||
// Set adapter again for scrolling to top: http://stackoverflow.com/a/17577981/3263582
|
recycler.getLayoutManager().scrollToPosition(0);
|
||||||
gridView.setAdapter(adapter);
|
|
||||||
gridView.setSelection(0);
|
|
||||||
|
|
||||||
getPresenter().restartRequest(query);
|
getPresenter().restartRequest(query);
|
||||||
}
|
}
|
||||||
|
@ -212,48 +213,23 @@ public class CatalogueFragment extends BaseRxFragment<CataloguePresenter> {
|
||||||
adapter.clear();
|
adapter.clear();
|
||||||
scrollListener.resetScroll();
|
scrollListener.resetScroll();
|
||||||
}
|
}
|
||||||
adapter.addAll(pair.second);
|
adapter.addItems(pair.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onAddPageError() {
|
public void onAddPageError() {
|
||||||
hideProgressBar();
|
hideProgressBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnItemClick(R.id.gridView)
|
|
||||||
public void onMangaClick(int position) {
|
|
||||||
Manga selectedManga = adapter.getItem(position);
|
|
||||||
|
|
||||||
Intent intent = MangaActivity.newIntent(getActivity(), selectedManga);
|
|
||||||
intent.putExtra(MangaActivity.MANGA_ONLINE, true);
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateImage(Manga manga) {
|
public void updateImage(Manga manga) {
|
||||||
ImageView imageView = getImageView(getMangaIndex(manga));
|
CatalogueHolder holder = getHolder(manga);
|
||||||
if (imageView != null && manga.thumbnail_url != null) {
|
if (holder != null) {
|
||||||
getPresenter().coverCache.loadFromNetwork(imageView, manga.thumbnail_url,
|
holder.setImage(manga, getPresenter());
|
||||||
getPresenter().getSource().getGlideHeaders());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ImageView getImageView(int position) {
|
@Nullable
|
||||||
if (position == -1) return null;
|
private CatalogueHolder getHolder(Manga manga) {
|
||||||
|
return (CatalogueHolder) recycler.findViewHolderForItemId(manga.id);
|
||||||
View v = gridView.getChildAt(position -
|
|
||||||
gridView.getFirstVisiblePosition());
|
|
||||||
|
|
||||||
if (v == null) return null;
|
|
||||||
|
|
||||||
return (ImageView) v.findViewById(R.id.thumbnail);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getMangaIndex(Manga manga) {
|
|
||||||
for (int i = adapter.getCount() - 1; i >= 0; i--) {
|
|
||||||
if (manga.id.equals(adapter.getItem(i).id)) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showProgressBar() {
|
private void showProgressBar() {
|
||||||
|
@ -269,4 +245,18 @@ public class CatalogueFragment extends BaseRxFragment<CataloguePresenter> {
|
||||||
progressGrid.setVisibility(ProgressBar.GONE);
|
progressGrid.setVisibility(ProgressBar.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onListItemClick(int position) {
|
||||||
|
final Manga selectedManga = adapter.getItem(position);
|
||||||
|
|
||||||
|
Intent intent = MangaActivity.newIntent(getActivity(), selectedManga);
|
||||||
|
intent.putExtra(MangaActivity.MANGA_ONLINE, true);
|
||||||
|
startActivity(intent);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onListItemLongClick(int position) {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
package eu.kanade.mangafeed.ui.catalogue;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import butterknife.Bind;
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
import eu.kanade.mangafeed.R;
|
||||||
|
import eu.kanade.mangafeed.data.database.models.Manga;
|
||||||
|
import eu.kanade.mangafeed.ui.base.adapter.FlexibleViewHolder;
|
||||||
|
|
||||||
|
public class CatalogueHolder extends FlexibleViewHolder {
|
||||||
|
|
||||||
|
@Bind(R.id.title) TextView title;
|
||||||
|
@Bind(R.id.thumbnail) ImageView thumbnail;
|
||||||
|
@Bind(R.id.favorite_sticker) ImageView favoriteSticker;
|
||||||
|
|
||||||
|
public CatalogueHolder(View view, CatalogueAdapter adapter, OnListItemClickListener listener) {
|
||||||
|
super(view, adapter, listener);
|
||||||
|
ButterKnife.bind(this, view);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onSetValues(Manga manga, CataloguePresenter presenter) {
|
||||||
|
title.setText(manga.title);
|
||||||
|
favoriteSticker.setVisibility(manga.favorite ? View.VISIBLE : View.GONE);
|
||||||
|
setImage(manga, presenter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setImage(Manga manga, CataloguePresenter presenter) {
|
||||||
|
if (manga.thumbnail_url != null) {
|
||||||
|
presenter.coverCache.loadFromNetwork(thumbnail, manga.thumbnail_url,
|
||||||
|
presenter.getSource().getGlideHeaders());
|
||||||
|
} else {
|
||||||
|
thumbnail.setImageResource(android.R.color.transparent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -60,12 +60,12 @@ public class CataloguePresenter extends BasePresenter<CatalogueFragment> {
|
||||||
() -> pager.pages().concatMap(
|
() -> pager.pages().concatMap(
|
||||||
page -> getMangaObs(page + 1)
|
page -> getMangaObs(page + 1)
|
||||||
.map(mangas -> Pair.create(page, mangas))
|
.map(mangas -> Pair.create(page, mangas))
|
||||||
|
.doOnNext(pair -> {
|
||||||
|
if (mangaDetailSubject != null)
|
||||||
|
mangaDetailSubject.onNext(pair.second);
|
||||||
|
})
|
||||||
.observeOn(AndroidSchedulers.mainThread())),
|
.observeOn(AndroidSchedulers.mainThread())),
|
||||||
(view, page) -> {
|
CatalogueFragment::onAddPage,
|
||||||
view.onAddPage(page);
|
|
||||||
if (mangaDetailSubject != null)
|
|
||||||
mangaDetailSubject.onNext(page.second);
|
|
||||||
},
|
|
||||||
(view, error) -> {
|
(view, error) -> {
|
||||||
view.onAddPageError();
|
view.onAddPageError();
|
||||||
Timber.e(error.getMessage());
|
Timber.e(error.getMessage());
|
||||||
|
@ -73,14 +73,14 @@ public class CataloguePresenter extends BasePresenter<CatalogueFragment> {
|
||||||
|
|
||||||
restartableLatestCache(GET_MANGA_DETAIL,
|
restartableLatestCache(GET_MANGA_DETAIL,
|
||||||
() -> mangaDetailSubject
|
() -> mangaDetailSubject
|
||||||
|
.observeOn(Schedulers.io())
|
||||||
.flatMap(Observable::from)
|
.flatMap(Observable::from)
|
||||||
.filter(manga -> !manga.initialized)
|
.filter(manga -> !manga.initialized)
|
||||||
.window(3)
|
.window(3)
|
||||||
.concatMap(pack -> pack.concatMap(this::getMangaDetails))
|
.concatMap(pack -> pack.concatMap(this::getMangaDetails))
|
||||||
.filter(manga -> manga.initialized)
|
|
||||||
.onBackpressureBuffer()
|
.onBackpressureBuffer()
|
||||||
.observeOn(AndroidSchedulers.mainThread()),
|
.observeOn(AndroidSchedulers.mainThread()),
|
||||||
(view, manga) -> view.updateImage(manga),
|
CatalogueFragment::updateImage,
|
||||||
(view, error) -> Timber.e(error.getMessage()));
|
(view, error) -> Timber.e(error.getMessage()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ public class CataloguePresenter extends BasePresenter<CatalogueFragment> {
|
||||||
return source.pullMangaFromNetwork(manga.url)
|
return source.pullMangaFromNetwork(manga.url)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.flatMap(networkManga -> {
|
.flatMap(networkManga -> {
|
||||||
Manga.copyFromNetwork(manga, networkManga);
|
manga.copyFrom(networkManga);
|
||||||
db.insertManga(manga).executeAsBlocking();
|
db.insertManga(manga).executeAsBlocking();
|
||||||
return Observable.just(manga);
|
return Observable.just(manga);
|
||||||
})
|
})
|
||||||
|
|
|
@ -93,7 +93,7 @@ public class MangaInfoPresenter extends BasePresenter<MangaInfoFragment> {
|
||||||
private Observable<Manga> fetchMangaObs() {
|
private Observable<Manga> fetchMangaObs() {
|
||||||
return source.pullMangaFromNetwork(manga.url)
|
return source.pullMangaFromNetwork(manga.url)
|
||||||
.flatMap(networkManga -> {
|
.flatMap(networkManga -> {
|
||||||
Manga.copyFromNetwork(manga, networkManga);
|
manga.copyFrom(networkManga);
|
||||||
db.insertManga(manga).executeAsBlocking();
|
db.insertManga(manga).executeAsBlocking();
|
||||||
return Observable.just(manga);
|
return Observable.just(manga);
|
||||||
})
|
})
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
package eu.kanade.mangafeed.widget;
|
||||||
|
|
||||||
|
import android.support.v7.widget.GridLayoutManager;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
|
||||||
|
import rx.functions.Action0;
|
||||||
|
|
||||||
|
public class EndlessRecyclerScrollListener extends RecyclerView.OnScrollListener {
|
||||||
|
|
||||||
|
private int previousTotal = 0; // The total number of items in the dataset after the last load
|
||||||
|
private boolean loading = true; // True if we are still waiting for the last set of data to load.
|
||||||
|
private int visibleThreshold = 5; // The minimum amount of items to have below your current scroll position before loading more.
|
||||||
|
int firstVisibleItem, visibleItemCount, totalItemCount;
|
||||||
|
|
||||||
|
private GridLayoutManager layoutManager;
|
||||||
|
|
||||||
|
private Action0 requestNext;
|
||||||
|
|
||||||
|
public EndlessRecyclerScrollListener(GridLayoutManager layoutManager, Action0 requestNext) {
|
||||||
|
this.layoutManager = layoutManager;
|
||||||
|
this.requestNext = requestNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetScroll() {
|
||||||
|
previousTotal = 0;
|
||||||
|
loading = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
|
||||||
|
super.onScrolled(recyclerView, dx, dy);
|
||||||
|
|
||||||
|
visibleItemCount = recyclerView.getChildCount();
|
||||||
|
totalItemCount = layoutManager.getItemCount();
|
||||||
|
firstVisibleItem = layoutManager.findFirstVisibleItemPosition();
|
||||||
|
|
||||||
|
if (loading && (totalItemCount > previousTotal)) {
|
||||||
|
loading = false;
|
||||||
|
previousTotal = totalItemCount;
|
||||||
|
}
|
||||||
|
if (!loading && (totalItemCount - visibleItemCount)
|
||||||
|
<= (firstVisibleItem + visibleThreshold)) {
|
||||||
|
// End has been reached
|
||||||
|
requestNext.call();
|
||||||
|
loading = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -15,8 +15,8 @@
|
||||||
android:layout_gravity="center_vertical|center_horizontal"
|
android:layout_gravity="center_vertical|center_horizontal"
|
||||||
android:visibility="gone"/>
|
android:visibility="gone"/>
|
||||||
|
|
||||||
<GridView
|
<eu.kanade.mangafeed.widget.AutofitRecyclerView
|
||||||
android:id="@+id/gridView"
|
android:id="@+id/recycler"
|
||||||
style="@style/AppTheme.GridView"
|
style="@style/AppTheme.GridView"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
|
Reference in a new issue