Add MangaDetailActivity with two fragments, info and chapters

This commit is contained in:
inorichi 2015-10-17 13:51:54 +02:00
parent 07395892a0
commit 0e52c81970
16 changed files with 508 additions and 81 deletions

View file

@ -9,7 +9,9 @@ import eu.kanade.mangafeed.data.DataModule;
import eu.kanade.mangafeed.presenter.CataloguePresenter;
import eu.kanade.mangafeed.presenter.LibraryPresenter;
import eu.kanade.mangafeed.presenter.MangaCataloguePresenter;
import eu.kanade.mangafeed.presenter.MangaChaptersPresenter;
import eu.kanade.mangafeed.presenter.MangaDetailPresenter;
import eu.kanade.mangafeed.presenter.MangaInfoPresenter;
import eu.kanade.mangafeed.presenter.SourcePresenter;
@Singleton
@ -26,6 +28,8 @@ public interface AppComponent {
void inject(SourcePresenter sourcePresenter);
void inject(CataloguePresenter cataloguePresenter);
void inject(MangaCataloguePresenter mangaCataloguePresenter);
void inject(MangaInfoPresenter mangaInfoPresenter);
void inject(MangaChaptersPresenter mangaChaptersPresenter);
Application application();

View file

@ -98,7 +98,7 @@ public class DatabaseHelper implements MangaManager, ChapterManager {
}
@Override
public Observable<List<Manga>> getManga(int id) {
public Observable<List<Manga>> getManga(long id) {
return mMangaManager.getManga(id);
}

View file

@ -18,7 +18,7 @@ public interface MangaManager {
Observable<List<Manga>> getManga(String url);
Observable<List<Manga>> getManga(int id);
Observable<List<Manga>> getManga(long id);
Manga getMangaBlock(String url);

View file

@ -66,8 +66,16 @@ public class MangaManagerImpl extends BaseManager implements MangaManager {
.createObservable();
}
public Observable<List<Manga>> getManga(int id) {
return null;
public Observable<List<Manga>> getManga(long id) {
return db.get()
.listOfObjects(Manga.class)
.withQuery(Query.builder()
.table(MangasTable.TABLE)
.where(MangasTable.COLUMN_ID + "=?")
.whereArgs(id)
.build())
.prepare()
.createObservable();
}
@Override

View file

@ -1,6 +1,5 @@
package eu.kanade.mangafeed.presenter;
import android.content.Intent;
import android.os.Bundle;
import android.util.SparseBooleanArray;
@ -9,7 +8,6 @@ import javax.inject.Inject;
import eu.kanade.mangafeed.data.helpers.DatabaseHelper;
import eu.kanade.mangafeed.data.helpers.PreferencesHelper;
import eu.kanade.mangafeed.data.models.Manga;
import eu.kanade.mangafeed.ui.activity.MangaDetailActivity;
import eu.kanade.mangafeed.ui.fragment.LibraryFragment;
import rx.Observable;
import rx.Subscription;
@ -36,14 +34,6 @@ public class LibraryPresenter extends BasePresenter2<LibraryFragment> {
getFavoriteMangas();
}
public void onMangaClick(LibraryFragment view, int position) {
Intent intent = MangaDetailActivity.newIntent(
view.getActivity(),
view.getAdapter().getItem(position)
);
view.getActivity().startActivity(intent);
}
public void getFavoriteMangas() {
if (mFavoriteMangasSubscription != null)
remove(mFavoriteMangasSubscription);

View file

@ -0,0 +1,6 @@
package eu.kanade.mangafeed.presenter;
import eu.kanade.mangafeed.ui.fragment.MangaChaptersFragment;
public class MangaChaptersPresenter extends BasePresenter2<MangaChaptersFragment> {
}

View file

@ -2,33 +2,23 @@ package eu.kanade.mangafeed.presenter;
import javax.inject.Inject;
import de.greenrobot.event.EventBus;
import eu.kanade.mangafeed.App;
import eu.kanade.mangafeed.data.helpers.DatabaseHelper;
import eu.kanade.mangafeed.data.models.Manga;
import eu.kanade.mangafeed.ui.activity.MangaDetailActivity;
import eu.kanade.mangafeed.view.MangaDetailView;
public class MangaDetailPresenter extends BasePresenter {
public class MangaDetailPresenter extends BasePresenter2<MangaDetailActivity> {
private MangaDetailView view;
@Inject
DatabaseHelper db;
public MangaDetailPresenter(MangaDetailView view) {
this.view = view;
App.getComponent(view.getActivity()).inject(this);
}
public void onEventMainThread(Manga manga) {
view.loadManga(manga);
initializeChapters(manga);
}
public static void newIntent(Manga manga) {
EventBus.getDefault().postSticky(manga);
}
public void initializeChapters(Manga manga) {
db.getChapters(manga)
.subscribe(view::setChapters);

View file

@ -0,0 +1,36 @@
package eu.kanade.mangafeed.presenter;
import javax.inject.Inject;
import eu.kanade.mangafeed.data.helpers.DatabaseHelper;
import eu.kanade.mangafeed.ui.fragment.MangaInfoFragment;
import rx.Observable;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
public class MangaInfoPresenter extends BasePresenter2<MangaInfoFragment> {
@Inject DatabaseHelper db;
private Subscription mangaInfoSubscription;
@Override
protected void onTakeView(MangaInfoFragment view) {
super.onTakeView(view);
getMangaInfo(view);
}
private void getMangaInfo(MangaInfoFragment view) {
if (mangaInfoSubscription != null)
remove(mangaInfoSubscription);
mangaInfoSubscription = db.getManga(view.getMangaId())
.observeOn(AndroidSchedulers.mainThread())
.take(1)
.flatMap(Observable::from)
.subscribe(view::setMangaInfo);
add(mangaInfoSubscription);
}
}

View file

@ -2,37 +2,45 @@ package eu.kanade.mangafeed.ui.activity;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.widget.Toolbar;
import android.widget.ListView;
import java.util.List;
import butterknife.Bind;
import butterknife.ButterKnife;
import eu.kanade.mangafeed.R;
import eu.kanade.mangafeed.data.models.Chapter;
import eu.kanade.mangafeed.data.models.Manga;
import eu.kanade.mangafeed.presenter.MangaDetailPresenter;
import eu.kanade.mangafeed.ui.adapter.ChapterListHolder;
import eu.kanade.mangafeed.view.MangaDetailView;
import uk.co.ribot.easyadapter.EasyAdapter;
import eu.kanade.mangafeed.ui.fragment.MangaChaptersFragment;
import eu.kanade.mangafeed.ui.fragment.MangaInfoFragment;
import nucleus.factory.RequiresPresenter;
public class MangaDetailActivity extends BaseActivity implements MangaDetailView {
Manga manga;
MangaDetailPresenter presenter;
EasyAdapter<Chapter> adapter;
@RequiresPresenter(MangaDetailPresenter.class)
public class MangaDetailActivity extends BaseActivity2<MangaDetailPresenter> {
@Bind(R.id.toolbar)
Toolbar toolbar;
@Bind(R.id.manga_chapters_list)
ListView list_chapters;
@Bind(R.id.tabs)
TabLayout tabs;
@Bind(R.id.viewpager)
ViewPager view_pager;
long manga_id;
public final static String MANGA_ID = "manga_id";
public final static String MANGA_TITLE = "manga_title";
public static Intent newIntent(Context context, Manga manga) {
Intent intent = new Intent(context, MangaDetailActivity.class);
MangaDetailPresenter.newIntent(manga);
intent.putExtra(MANGA_ID, manga.id);
intent.putExtra(MANGA_TITLE, manga.title);
return intent;
}
@ -41,38 +49,71 @@ public class MangaDetailActivity extends BaseActivity implements MangaDetailView
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manga_detail);
ButterKnife.bind(this);
presenter = new MangaDetailPresenter(this);
setupToolbar(toolbar);
disableToolbarElevation();
String manga_title = getIntent().getStringExtra(MANGA_TITLE);
setToolbarTitle(manga_title);
manga_id = getIntent().getLongExtra(MANGA_ID, -1);
setupViewPager();
}
@Override
public void onStart() {
super.onStart();
presenter.registerForStickyEvents();
}
@Override
public void onStop() {
presenter.unregisterForEvents();
super.onStop();
}
public void loadManga(Manga manga) {
setToolbarTitle(manga.title);
}
public void setChapters(List<Chapter> chapters) {
if (adapter == null) {
adapter = new EasyAdapter<Chapter>(
getActivity(),
ChapterListHolder.class,
chapters
);
list_chapters.setAdapter(adapter);
} else {
adapter.setItems(chapters);
private void disableToolbarElevation() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
toolbar.setElevation(0);
}
}
private void setupViewPager() {
view_pager.setAdapter(new MangaDetailAdapter(
getSupportFragmentManager(),
getActivity(),
manga_id));
tabs.setupWithViewPager(view_pager);
}
}
class MangaDetailAdapter extends FragmentPagerAdapter {
final int PAGE_COUNT = 2;
private String tab_titles[];
private Context context;
private long manga_id;
public MangaDetailAdapter(FragmentManager fm, Context context, long manga_id) {
super(fm);
this.context = context;
tab_titles = new String[]{
context.getString(R.string.manga_detail_tab),
context.getString(R.string.manga_chapters_tab)
};
this.manga_id = manga_id;
}
@Override
public int getCount() {
return PAGE_COUNT;
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return MangaInfoFragment.newInstance(manga_id);
case 1:
return MangaChaptersFragment.newInstance(manga_id);
default: return null;
}
}
@Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return tab_titles[position];
}
}

View file

@ -1,5 +1,6 @@
package eu.kanade.mangafeed.ui.fragment;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.widget.SearchView;
import android.view.ActionMode;
@ -17,6 +18,7 @@ import eu.kanade.mangafeed.R;
import eu.kanade.mangafeed.data.models.Manga;
import eu.kanade.mangafeed.presenter.LibraryPresenter;
import eu.kanade.mangafeed.ui.activity.MainActivity;
import eu.kanade.mangafeed.ui.activity.MangaDetailActivity;
import eu.kanade.mangafeed.ui.adapter.LibraryAdapter;
import nucleus.factory.RequiresPresenter;
@ -90,7 +92,7 @@ public class LibraryFragment extends BaseFragment2<LibraryPresenter> {
public void setMangaClickListener() {
grid.setOnItemClickListener(
(parent, view, position, id) ->
getPresenter().onMangaClick(this, position)
onMangaClick(position)
);
grid.setMultiChoiceModeListener(new GridView.MultiChoiceModeListener() {
@Override
@ -129,4 +131,12 @@ public class LibraryFragment extends BaseFragment2<LibraryPresenter> {
});
}
private void onMangaClick(int position) {
Intent intent = MangaDetailActivity.newIntent(
getActivity(),
adapter.getItem(position)
);
getActivity().startActivity(intent);
}
}

View file

@ -0,0 +1,43 @@
package eu.kanade.mangafeed.ui.fragment;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import butterknife.ButterKnife;
import eu.kanade.mangafeed.R;
import eu.kanade.mangafeed.presenter.MangaChaptersPresenter;
import eu.kanade.mangafeed.ui.activity.MangaDetailActivity;
import nucleus.factory.RequiresPresenter;
@RequiresPresenter(MangaChaptersPresenter.class)
public class MangaChaptersFragment extends BaseFragment2<MangaChaptersPresenter> {
private long manga_id;
public static Fragment newInstance(long manga_id) {
MangaChaptersFragment fragment = new MangaChaptersFragment();
Bundle args = new Bundle();
args.putLong(MangaDetailActivity.MANGA_ID, manga_id);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
manga_id = getArguments().getLong(MangaDetailActivity.MANGA_ID);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_manga_chapters, container, false);
ButterKnife.bind(this, view);
return view;
}
}

View file

@ -0,0 +1,76 @@
package eu.kanade.mangafeed.ui.fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import butterknife.Bind;
import butterknife.ButterKnife;
import eu.kanade.mangafeed.R;
import eu.kanade.mangafeed.data.models.Manga;
import eu.kanade.mangafeed.presenter.MangaInfoPresenter;
import eu.kanade.mangafeed.ui.activity.MangaDetailActivity;
import nucleus.factory.RequiresPresenter;
@RequiresPresenter(MangaInfoPresenter.class)
public class MangaInfoFragment extends BaseFragment2<MangaInfoPresenter> {
@Bind(R.id.manga_artist) TextView mArtist;
@Bind(R.id.manga_author) TextView mAuthor;
@Bind(R.id.manga_chapters) TextView mChapters;
@Bind(R.id.manga_genres) TextView mGenres;
@Bind(R.id.manga_status) TextView mStatus;
@Bind(R.id.manga_summary) TextView mDescription;
@Bind(R.id.manga_cover) ImageView mCover;
private long manga_id;
public static MangaInfoFragment newInstance(long manga_id) {
MangaInfoFragment fragment = new MangaInfoFragment();
Bundle args = new Bundle();
args.putLong(MangaDetailActivity.MANGA_ID, manga_id);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
manga_id = getArguments().getLong(MangaDetailActivity.MANGA_ID);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_manga_info, container, false);
ButterKnife.bind(this, view);
return view;
}
public long getMangaId() {
return manga_id;
}
public void setMangaInfo(Manga manga) {
mArtist.setText(manga.artist);
mAuthor.setText(manga.author);
mChapters.setText("0"); // TODO
mGenres.setText(manga.genre);
mStatus.setText("Ongoing"); //TODO
mDescription.setText(manga.description);
Glide.with(getActivity())
.load(manga.thumbnail_url)
.diskCacheStrategy(DiskCacheStrategy.RESULT)
.centerCrop()
.into(mCover);
}
}

View file

@ -1,19 +1,37 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="wrap_content"
tools:context="eu.kanade.mangafeed.ui.activity.MangaDetailActivity"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:orientation="vertical">
<include
android:id="@+id/toolbar"
layout="@layout/toolbar"/>
<ListView
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/manga_chapters_list"
tools:listitem="@layout/item_chapter"
android:height="?android:listPreferredItemHeight"/>
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
</LinearLayout>
<include
android:id="@+id/toolbar"
layout="@layout/toolbar" />
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabIndicatorColor="@android:color/white"
app:tabGravity="fill" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1"
android:background="@android:color/white" />
</LinearLayout>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
</LinearLayout>

View file

@ -0,0 +1,197 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" android:fitsSystemWindows="true"
tools:context="eu.kanade.mangafeed.ui.activity.CatalogueActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bkg_shadow_img"
android:focusable="false"
android:focusableInTouchMode="false"
android:gravity="center"
android:padding="4dp">
<ImageView
android:id="@+id/manga_cover"
android:layout_width="138dp"
android:layout_height="190dp"
android:focusable="false"
android:focusableInTouchMode="false"
android:scaleType="fitXY"
android:visibility="visible" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/grid_item_description"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:focusable="false"
android:focusableInTouchMode="false"
android:paddingLeft="15.0dip">
<TextView
android:id="@+id/manga_author_label"
style="@style/manga_detail_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignRight="@+id/manga_genres_label"
android:layout_marginTop="5dp"
android:focusable="false"
android:focusableInTouchMode="false"
android:text="@string/author" />
<TextView
android:id="@+id/manga_author"
style="@style/manga_detail_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignBaseline="@id/manga_author_label"
android:layout_toRightOf="@id/manga_author_label"
android:ellipsize="end"
android:focusable="false"
android:focusableInTouchMode="false"
android:maxLines="1"
android:singleLine="true" />
<TextView
android:id="@+id/manga_artist_label"
style="@style/manga_detail_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignRight="@id/manga_genres_label"
android:layout_below="@id/manga_author_label"
android:focusable="false"
android:focusableInTouchMode="false"
android:text="@string/artist" />
<TextView
android:id="@+id/manga_artist"
style="@style/manga_detail_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignBaseline="@id/manga_artist_label"
android:layout_toRightOf="@id/manga_artist_label"
android:ellipsize="end"
android:focusable="false"
android:focusableInTouchMode="false"
android:maxLines="1"
android:singleLine="true" />
<TextView
android:id="@+id/manga_chapters_label"
style="@style/manga_detail_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignRight="@id/manga_genres_label"
android:layout_below="@id/manga_artist_label"
android:focusable="false"
android:focusableInTouchMode="false"
android:text="@string/chapters" />
<TextView
android:id="@+id/manga_chapters"
style="@style/manga_detail_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignBaseline="@id/manga_chapters_label"
android:layout_toRightOf="@id/manga_chapters_label"
android:ellipsize="end"
android:focusable="false"
android:focusableInTouchMode="false"
android:maxLines="1"
android:singleLine="true" />
<TextView
android:id="@+id/manga_status_label"
style="@style/manga_detail_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignRight="@id/manga_genres_label"
android:layout_below="@id/manga_chapters_label"
android:focusable="false"
android:focusableInTouchMode="false"
android:text="@string/status" />
<TextView
android:id="@+id/manga_status"
style="@style/manga_detail_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignBaseline="@id/manga_status_label"
android:layout_toRightOf="@id/manga_chapters_label"
android:ellipsize="end"
android:focusable="false"
android:focusableInTouchMode="false"
android:maxLines="1"
android:singleLine="true" />
<TextView
android:id="@+id/manga_genres_label"
style="@style/manga_detail_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@id/manga_status_label"
android:focusable="false"
android:focusableInTouchMode="false"
android:text="@string/genres" />
<TextView
android:id="@+id/manga_genres"
style="@style/manga_detail_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/manga_genres_label"
android:singleLine="false"
android:focusable="false"
android:focusableInTouchMode="false"
/>
</RelativeLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
android:orientation="vertical">
<TextView
android:id="@+id/manga_summary_label"
style="@style/manga_detail_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="false"
android:focusableInTouchMode="false"
android:singleLine="false"
android:text="@string/description" />
<TextView
android:id="@+id/manga_summary"
style="@style/manga_detail_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="false"
android:focusableInTouchMode="false"
android:singleLine="false" />
</LinearLayout>
</LinearLayout>

View file

@ -43,5 +43,7 @@
<string name="artist">Artist</string>
<string name="status">Status</string>
<string name="description">Description</string>
<string name="manga_detail_tab">Info</string>
<string name="manga_chapters_tab">Chapters</string>
</resources>