Allow to display manga from catalogue as a simple list (#35)

This commit is contained in:
inorichi 2016-01-22 17:37:23 +01:00
parent 75a77566cf
commit e1aa460106
29 changed files with 286 additions and 62 deletions

View file

@ -116,6 +116,10 @@ public class PreferencesHelper {
return rxPrefs.getInteger(getKey(R.string.pref_reader_theme_key), 0); return rxPrefs.getInteger(getKey(R.string.pref_reader_theme_key), 0);
} }
public Preference<Boolean> catalogueAsList() {
return rxPrefs.getBoolean(getKey(R.string.pref_display_catalogue_as_list), false);
}
public String getSourceUsername(Source source) { public String getSourceUsername(Source source) {
return prefs.getString(SOURCE_ACCOUNT_USERNAME + source.getId(), ""); return prefs.getString(SOURCE_ACCOUNT_USERNAME + source.getId(), "");
} }

View file

@ -31,6 +31,10 @@ public class CatalogueAdapter extends FlexibleAdapter<CatalogueHolder, Manga> {
notifyDataSetChanged(); notifyDataSetChanged();
} }
public List<Manga> getItems() {
return mItems;
}
@Override @Override
public long getItemId(int position) { public long getItemId(int position) {
return mItems.get(position).id; return mItems.get(position).id;
@ -44,8 +48,13 @@ public class CatalogueAdapter extends FlexibleAdapter<CatalogueHolder, Manga> {
@Override @Override
public CatalogueHolder onCreateViewHolder(ViewGroup parent, int viewType) { public CatalogueHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = fragment.getActivity().getLayoutInflater(); LayoutInflater inflater = fragment.getActivity().getLayoutInflater();
View v = inflater.inflate(R.layout.item_catalogue, parent, false); if (parent.getId() == R.id.catalogue_grid) {
return new CatalogueHolder(v, this, fragment); View v = inflater.inflate(R.layout.item_catalogue_grid, parent, false);
return new CatalogueGridHolder(v, this, fragment);
} else {
View v = inflater.inflate(R.layout.item_catalogue_list, parent, false);
return new CatalogueListHolder(v, this, fragment);
}
} }
@Override @Override

View file

@ -4,7 +4,10 @@ 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.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
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,9 +17,12 @@ import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.Spinner; import android.widget.Spinner;
import android.widget.ViewSwitcher;
import com.afollestad.materialdialogs.MaterialDialog; import com.afollestad.materialdialogs.MaterialDialog;
@ -30,11 +36,13 @@ import eu.kanade.tachiyomi.data.database.models.Manga;
import eu.kanade.tachiyomi.data.source.base.Source; import eu.kanade.tachiyomi.data.source.base.Source;
import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder; import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder;
import eu.kanade.tachiyomi.ui.base.fragment.BaseRxFragment; import eu.kanade.tachiyomi.ui.base.fragment.BaseRxFragment;
import eu.kanade.tachiyomi.ui.decoration.DividerItemDecoration;
import eu.kanade.tachiyomi.ui.main.MainActivity; import eu.kanade.tachiyomi.ui.main.MainActivity;
import eu.kanade.tachiyomi.ui.manga.MangaActivity; import eu.kanade.tachiyomi.ui.manga.MangaActivity;
import eu.kanade.tachiyomi.util.ToastUtil; import eu.kanade.tachiyomi.util.ToastUtil;
import eu.kanade.tachiyomi.widget.AutofitRecyclerView; import eu.kanade.tachiyomi.widget.AutofitRecyclerView;
import eu.kanade.tachiyomi.widget.EndlessRecyclerScrollListener; import eu.kanade.tachiyomi.widget.EndlessGridScrollListener;
import eu.kanade.tachiyomi.widget.EndlessListScrollListener;
import icepick.State; import icepick.State;
import nucleus.factory.RequiresPresenter; import nucleus.factory.RequiresPresenter;
import rx.Subscription; import rx.Subscription;
@ -45,14 +53,17 @@ import rx.subjects.PublishSubject;
public class CatalogueFragment extends BaseRxFragment<CataloguePresenter> public class CatalogueFragment extends BaseRxFragment<CataloguePresenter>
implements FlexibleViewHolder.OnListItemClickListener { implements FlexibleViewHolder.OnListItemClickListener {
@Bind(R.id.recycler) AutofitRecyclerView recycler; @Bind(R.id.switcher) ViewSwitcher switcher;
@Bind(R.id.catalogue_grid) AutofitRecyclerView catalogueGrid;
@Bind(R.id.catalogue_list) RecyclerView catalogueList;
@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 EndlessRecyclerScrollListener scrollListener; private EndlessGridScrollListener gridScrollListener;
private EndlessListScrollListener listScrollListener;
@State String query = ""; @State String query = "";
@State int selectedIndex = -1; @State int selectedIndex = -1;
@ -61,6 +72,8 @@ public class CatalogueFragment extends BaseRxFragment<CataloguePresenter>
private PublishSubject<String> queryDebouncerSubject; private PublishSubject<String> queryDebouncerSubject;
private Subscription queryDebouncerSubscription; private Subscription queryDebouncerSubscription;
private MenuItem displayMode;
public static CatalogueFragment newInstance() { public static CatalogueFragment newInstance() {
return new CatalogueFragment(); return new CatalogueFragment();
} }
@ -77,13 +90,32 @@ public class CatalogueFragment extends BaseRxFragment<CataloguePresenter>
View view = inflater.inflate(R.layout.fragment_catalogue, container, false); View view = inflater.inflate(R.layout.fragment_catalogue, container, false);
ButterKnife.bind(this, view); ButterKnife.bind(this, view);
// Initialize adapter and scroll listener // Initialize adapter, scroll listener and recycler views
GridLayoutManager layoutManager = (GridLayoutManager) recycler.getLayoutManager();
adapter = new CatalogueAdapter(this); adapter = new CatalogueAdapter(this);
scrollListener = new EndlessRecyclerScrollListener(layoutManager, this::requestNextPage);
recycler.setHasFixedSize(true); GridLayoutManager glm = (GridLayoutManager) catalogueGrid.getLayoutManager();
recycler.setAdapter(adapter); gridScrollListener = new EndlessGridScrollListener(glm, this::requestNextPage);
recycler.addOnScrollListener(scrollListener); catalogueGrid.setHasFixedSize(true);
catalogueGrid.setAdapter(adapter);
catalogueGrid.addOnScrollListener(gridScrollListener);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
listScrollListener = new EndlessListScrollListener(llm, this::requestNextPage);
catalogueList.setHasFixedSize(true);
catalogueList.setAdapter(adapter);
catalogueList.setLayoutManager(llm);
catalogueList.addOnScrollListener(listScrollListener);
catalogueList.addItemDecoration(new DividerItemDecoration(
ContextCompat.getDrawable(getContext(), R.drawable.line_divider)));
if (getPresenter().isListMode()) {
switcher.showNext();
}
Animation inAnim = AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_in);
Animation outAnim = AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_out);
switcher.setInAnimation(inAnim);
switcher.setOutAnimation(outAnim);
// Create toolbar spinner // Create toolbar spinner
Context themedContext = getBaseActivity().getSupportActionBar() != null ? Context themedContext = getBaseActivity().getSupportActionBar() != null ?
@ -109,7 +141,8 @@ public class CatalogueFragment extends BaseRxFragment<CataloguePresenter>
} else { } else {
selectedIndex = position; selectedIndex = position;
showProgressBar(); showProgressBar();
recycler.setAdapter(adapter); glm.scrollToPositionWithOffset(0, 0);
llm.scrollToPositionWithOffset(0, 0);
getPresenter().startRequesting(source); getPresenter().startRequesting(source);
} }
} }
@ -152,6 +185,22 @@ public class CatalogueFragment extends BaseRxFragment<CataloguePresenter>
return true; return true;
} }
}); });
// Show next display mode
displayMode = menu.findItem(R.id.action_display_mode);
int icon = getPresenter().isListMode() ?
R.drawable.ic_view_module_white_24dp : R.drawable.ic_view_list_white_24dp;
displayMode.setIcon(icon);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_display_mode:
swapDisplayMode();
break;
}
return super.onOptionsItemSelected(item);
} }
@Override @Override
@ -198,7 +247,8 @@ public class CatalogueFragment extends BaseRxFragment<CataloguePresenter>
query = newQuery; query = newQuery;
showProgressBar(); showProgressBar();
recycler.getLayoutManager().scrollToPosition(0); catalogueGrid.getLayoutManager().scrollToPosition(0);
catalogueList.getLayoutManager().scrollToPosition(0);
getPresenter().restartRequest(query); getPresenter().restartRequest(query);
} }
@ -214,7 +264,8 @@ public class CatalogueFragment extends BaseRxFragment<CataloguePresenter>
hideProgressBar(); hideProgressBar();
if (page == 0) { if (page == 0) {
adapter.clear(); adapter.clear();
scrollListener.resetScroll(); gridScrollListener.resetScroll();
listScrollListener.resetScroll();
} }
adapter.addItems(mangas); adapter.addItems(mangas);
} }
@ -224,15 +275,28 @@ public class CatalogueFragment extends BaseRxFragment<CataloguePresenter>
} }
public void updateImage(Manga manga) { public void updateImage(Manga manga) {
CatalogueHolder holder = getHolder(manga); CatalogueGridHolder holder = getHolder(manga);
if (holder != null) { if (holder != null) {
holder.setImage(manga, getPresenter()); holder.setImage(manga, getPresenter());
} }
} }
public void swapDisplayMode() {
getPresenter().swapDisplayMode();
boolean isListMode = getPresenter().isListMode();
int icon = isListMode ?
R.drawable.ic_view_module_white_24dp : R.drawable.ic_view_list_white_24dp;
displayMode.setIcon(icon);
switcher.showNext();
if (!isListMode) {
// Initialize mangas if going to grid view
getPresenter().initializeMangas(adapter.getItems());
}
}
@Nullable @Nullable
private CatalogueHolder getHolder(Manga manga) { private CatalogueGridHolder getHolder(Manga manga) {
return (CatalogueHolder) recycler.findViewHolderForItemId(manga.id); return (CatalogueGridHolder) catalogueGrid.findViewHolderForItemId(manga.id);
} }
private void showProgressBar() { private void showProgressBar() {

View file

@ -0,0 +1,38 @@
package eu.kanade.tachiyomi.ui.catalogue;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import butterknife.Bind;
import butterknife.ButterKnife;
import eu.kanade.tachiyomi.R;
import eu.kanade.tachiyomi.data.database.models.Manga;
public class CatalogueGridHolder extends CatalogueHolder {
@Bind(R.id.title) TextView title;
@Bind(R.id.thumbnail) ImageView thumbnail;
@Bind(R.id.favorite_sticker) ImageView favoriteSticker;
public CatalogueGridHolder(View view, CatalogueAdapter adapter, OnListItemClickListener listener) {
super(view, adapter, listener);
ButterKnife.bind(this, view);
}
@Override
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);
}
}
}

View file

@ -1,38 +1,15 @@
package eu.kanade.tachiyomi.ui.catalogue; package eu.kanade.tachiyomi.ui.catalogue;
import android.view.View; import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import butterknife.Bind;
import butterknife.ButterKnife;
import eu.kanade.tachiyomi.R;
import eu.kanade.tachiyomi.data.database.models.Manga; import eu.kanade.tachiyomi.data.database.models.Manga;
import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder; import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder;
public class CatalogueHolder extends FlexibleViewHolder { public abstract 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) { public CatalogueHolder(View view, CatalogueAdapter adapter, OnListItemClickListener listener) {
super(view, adapter, listener); super(view, adapter, listener);
ButterKnife.bind(this, view);
} }
public void onSetValues(Manga manga, CataloguePresenter presenter) { abstract 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);
}
}
}

View file

@ -0,0 +1,24 @@
package eu.kanade.tachiyomi.ui.catalogue;
import android.view.View;
import android.widget.TextView;
import butterknife.Bind;
import butterknife.ButterKnife;
import eu.kanade.tachiyomi.R;
import eu.kanade.tachiyomi.data.database.models.Manga;
public class CatalogueListHolder extends CatalogueHolder {
@Bind(R.id.title) TextView title;
public CatalogueListHolder(View view, CatalogueAdapter adapter, OnListItemClickListener listener) {
super(view, adapter, listener);
ButterKnife.bind(this, view);
}
@Override
public void onSetValues(Manga manga, CataloguePresenter presenter) {
title.setText(manga.title);
}
}

View file

@ -42,6 +42,8 @@ public class CataloguePresenter extends BasePresenter<CatalogueFragment> {
private PublishSubject<List<Manga>> mangaDetailSubject; private PublishSubject<List<Manga>> mangaDetailSubject;
private boolean isListMode;
private static final int GET_MANGA_LIST = 1; private static final int GET_MANGA_LIST = 1;
private static final int GET_MANGA_DETAIL = 2; private static final int GET_MANGA_DETAIL = 2;
private static final int GET_MANGA_PAGE = 3; private static final int GET_MANGA_PAGE = 3;
@ -72,12 +74,14 @@ public class CataloguePresenter extends BasePresenter<CatalogueFragment> {
.observeOn(Schedulers.io()) .observeOn(Schedulers.io())
.flatMap(Observable::from) .flatMap(Observable::from)
.filter(manga -> !manga.initialized) .filter(manga -> !manga.initialized)
.window(3) .concatMap(this::getMangaDetails)
.concatMap(pack -> pack.concatMap(this::getMangaDetails))
.onBackpressureBuffer() .onBackpressureBuffer()
.observeOn(AndroidSchedulers.mainThread()), .observeOn(AndroidSchedulers.mainThread()),
CatalogueFragment::updateImage, CatalogueFragment::updateImage,
(view, error) -> Timber.e(error.getMessage())); (view, error) -> Timber.e(error.getMessage()));
add(prefs.catalogueAsList().asObservable()
.subscribe(this::setDisplayMode));
} }
private void onProcessRestart() { private void onProcessRestart() {
@ -87,6 +91,15 @@ public class CataloguePresenter extends BasePresenter<CatalogueFragment> {
stop(GET_MANGA_PAGE); stop(GET_MANGA_PAGE);
} }
private void setDisplayMode(boolean asList) {
this.isListMode = asList;
if (asList) {
stop(GET_MANGA_DETAIL);
} else {
start(GET_MANGA_DETAIL);
}
}
public void startRequesting(Source source) { public void startRequesting(Source source) {
this.source = source; this.source = source;
sourceId = source.getId(); sourceId = source.getId();
@ -98,7 +111,9 @@ public class CataloguePresenter extends BasePresenter<CatalogueFragment> {
stop(GET_MANGA_PAGE); stop(GET_MANGA_PAGE);
lastMangasPage = null; lastMangasPage = null;
start(GET_MANGA_DETAIL); if (!isListMode) {
start(GET_MANGA_DETAIL);
}
start(GET_MANGA_LIST); start(GET_MANGA_LIST);
start(GET_MANGA_PAGE); start(GET_MANGA_PAGE);
} }
@ -124,10 +139,7 @@ public class CataloguePresenter extends BasePresenter<CatalogueFragment> {
.flatMap(mangasPage -> Observable.from(mangasPage.mangas)) .flatMap(mangasPage -> Observable.from(mangasPage.mangas))
.map(this::networkToLocalManga) .map(this::networkToLocalManga)
.toList() .toList()
.doOnNext(mangas -> { .doOnNext(this::initializeMangas)
if (mangaDetailSubject != null)
mangaDetailSubject.onNext(mangas);
})
.observeOn(AndroidSchedulers.mainThread()); .observeOn(AndroidSchedulers.mainThread());
} }
@ -141,9 +153,12 @@ public class CataloguePresenter extends BasePresenter<CatalogueFragment> {
return localManga; return localManga;
} }
public void initializeMangas(List<Manga> mangas) {
mangaDetailSubject.onNext(mangas);
}
private Observable<Manga> getMangaDetails(final Manga manga) { private Observable<Manga> getMangaDetails(final Manga manga) {
return source.pullMangaFromNetwork(manga.url) return source.pullMangaFromNetwork(manga.url)
.subscribeOn(Schedulers.io())
.flatMap(networkManga -> { .flatMap(networkManga -> {
manga.copyFrom(networkManga); manga.copyFrom(networkManga);
db.insertManga(manga).executeAsBlocking(); db.insertManga(manga).executeAsBlocking();
@ -181,4 +196,13 @@ public class CataloguePresenter extends BasePresenter<CatalogueFragment> {
manga.favorite = !manga.favorite; manga.favorite = !manga.favorite;
db.insertManga(manga).executeAsBlocking(); db.insertManga(manga).executeAsBlocking();
} }
public boolean isListMode() {
return isListMode;
}
public void swapDisplayMode() {
prefs.catalogueAsList().set(!isListMode);
}
} }

View file

@ -52,7 +52,7 @@ public class LibraryCategoryAdapter extends FlexibleAdapter<LibraryHolder, Manga
@Override @Override
public LibraryHolder onCreateViewHolder(ViewGroup parent, int viewType) { public LibraryHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(fragment.getActivity()).inflate(R.layout.item_catalogue, parent, false); View v = LayoutInflater.from(fragment.getActivity()).inflate(R.layout.item_catalogue_grid, parent, false);
return new LibraryHolder(v, this, fragment); return new LibraryHolder(v, this, fragment);
} }

View file

@ -5,7 +5,7 @@ import android.support.v7.widget.RecyclerView;
import rx.functions.Action0; import rx.functions.Action0;
public class EndlessRecyclerScrollListener extends RecyclerView.OnScrollListener { public class EndlessGridScrollListener extends RecyclerView.OnScrollListener {
private int previousTotal = 0; // The total number of items in the dataset after the last load 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 boolean loading = true; // True if we are still waiting for the last set of data to load.
@ -16,7 +16,7 @@ public class EndlessRecyclerScrollListener extends RecyclerView.OnScrollListener
private Action0 requestNext; private Action0 requestNext;
public EndlessRecyclerScrollListener(GridLayoutManager layoutManager, Action0 requestNext) { public EndlessGridScrollListener(GridLayoutManager layoutManager, Action0 requestNext) {
this.layoutManager = layoutManager; this.layoutManager = layoutManager;
this.requestNext = requestNext; this.requestNext = requestNext;
} }

View file

@ -0,0 +1,49 @@
package eu.kanade.tachiyomi.widget;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import rx.functions.Action0;
public class EndlessListScrollListener 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 LinearLayoutManager layoutManager;
private Action0 requestNext;
public EndlessListScrollListener(LinearLayoutManager 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;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

View file

@ -11,17 +11,28 @@
android:id="@+id/progress" android:id="@+id/progress"
style="?android:attr/progressBarStyleLarge" style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="fill_parent" android:layout_height="match_parent"
android:layout_gravity="center_vertical|center_horizontal" android:layout_gravity="center_vertical|center_horizontal"
android:visibility="gone"/> android:visibility="gone"/>
<eu.kanade.tachiyomi.widget.AutofitRecyclerView <ViewSwitcher
android:id="@+id/recycler" android:layout_width="match_parent"
style="@style/AppTheme.GridView"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_weight="1" android:layout_weight="1"
android:columnWidth="140dp" android:id="@+id/switcher">
tools:listitem="@layout/item_catalogue" />
<eu.kanade.tachiyomi.widget.AutofitRecyclerView
android:id="@+id/catalogue_grid"
style="@style/AppTheme.GridView"
android:columnWidth="140dp"
tools:listitem="@layout/item_catalogue_grid" />
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/catalogue_list"/>
</ViewSwitcher>
<ProgressBar <ProgressBar
android:id="@+id/progress_grid" android:id="@+id/progress_grid"

View file

@ -8,6 +8,6 @@
android:id="@+id/library_mangas" android:id="@+id/library_mangas"
style="@style/AppTheme.GridView" style="@style/AppTheme.GridView"
android:columnWidth="140dp" android:columnWidth="140dp"
tools:listitem="@layout/item_catalogue" /> tools:listitem="@layout/item_catalogue_grid" />
</FrameLayout> </FrameLayout>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="?android:listPreferredItemHeightSmall"
android:background="@drawable/selector_chapter_light">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingLeft="?android:listPreferredItemPaddingLeft"
android:paddingRight="?android:listPreferredItemPaddingLeft"
android:id="@+id/title"/>
</FrameLayout>

View file

@ -1,11 +1,16 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android" <menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" tools:context=".CatalogueListActivity"> xmlns:tools="http://schemas.android.com/tools" tools:context=".CatalogueListActivity">
<item <item
android:id="@+id/action_search" android:id="@+id/action_search"
android:title="@string/action_search" android:title="@string/action_search"
android:icon="@drawable/ic_action_search" android:icon="@drawable/ic_action_search"
android:orderInCategory="100"
app:showAsAction="collapseActionView|ifRoom" app:showAsAction="collapseActionView|ifRoom"
app:actionViewClass="android.support.v7.widget.SearchView"/> app:actionViewClass="android.support.v7.widget.SearchView"/>
<item
android:id="@+id/action_display_mode"
android:title="@string/action_display_mode"
app:showAsAction="ifRoom"/>
</menu> </menu>

View file

@ -35,4 +35,6 @@
<string name="pref_version">pref_version</string> <string name="pref_version">pref_version</string>
<string name="pref_build_time">pref_build_time</string> <string name="pref_build_time">pref_build_time</string>
<string name="pref_display_catalogue_as_list">pref_display_catalogue_as_list</string>
</resources> </resources>

View file

@ -38,6 +38,7 @@
<string name="action_previous_chapter">Previous chapter</string> <string name="action_previous_chapter">Previous chapter</string>
<string name="action_next_chapter">Next chapter</string> <string name="action_next_chapter">Next chapter</string>
<string name="action_retry">Retry</string> <string name="action_retry">Retry</string>
<string name="action_display_mode">Change display mode</string>
<!-- Buttons --> <!-- Buttons -->