Jelajahi Sumber

Category improvements

inorichi 9 tahun lalu
induk
melakukan
384bc3c690

+ 5 - 0
app/src/main/AndroidManifest.xml

@@ -38,6 +38,11 @@
             android:label="@string/label_settings"
             android:parentActivityName=".ui.main.MainActivity" >
         </activity>
+        <activity
+            android:name=".ui.library.category.CategoryActivity"
+            android:label="@string/label_categories"
+            android:parentActivityName=".ui.main.MainActivity">
+        </activity>
 
         <activity
             android:name=".ui.setting.SettingsDownloadsFragment$CustomLayoutPickerActivity"

+ 51 - 0
app/src/main/java/eu/kanade/mangafeed/ui/base/fab/ScrollAwareFABBehavior.java

@@ -0,0 +1,51 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package eu.kanade.mangafeed.ui.base.fab;
+
+import android.content.Context;
+import android.support.design.widget.CoordinatorLayout;
+import android.support.design.widget.FloatingActionButton;
+import android.support.v4.view.ViewCompat;
+import android.util.AttributeSet;
+import android.view.View;
+
+public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior {
+    public ScrollAwareFABBehavior(Context context, AttributeSet attrs) {
+        super();
+    }
+
+    @Override
+    public boolean onStartNestedScroll(final CoordinatorLayout coordinatorLayout, final FloatingActionButton child,
+                                       final View directTargetChild, final View target, final int nestedScrollAxes) {
+        // Ensure we react to vertical scrolling
+        return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL
+                || super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
+    }
+
+    @Override
+    public void onNestedScroll(final CoordinatorLayout coordinatorLayout, final FloatingActionButton child,
+                               final View target, final int dxConsumed, final int dyConsumed,
+                               final int dxUnconsumed, final int dyUnconsumed) {
+        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
+        if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) {
+            // User scrolled down and the FAB is currently visible -> hide the FAB
+            child.hide();
+        } else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) {
+            // User scrolled up and the FAB is currently not visible -> show the FAB
+            child.show();
+        }
+    }
+}

+ 14 - 0
app/src/main/java/eu/kanade/mangafeed/ui/base/fragment/BaseFragment.java

@@ -1,12 +1,26 @@
 package eu.kanade.mangafeed.ui.base.fragment;
 
+import android.os.Bundle;
 import android.support.v4.app.Fragment;
 
 import de.greenrobot.event.EventBus;
 import eu.kanade.mangafeed.ui.base.activity.BaseActivity;
+import icepick.Icepick;
 
 public class BaseFragment extends Fragment {
 
+    @Override
+    public void onCreate(Bundle savedState) {
+        super.onCreate(savedState);
+        Icepick.restoreInstanceState(this, savedState);
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        Icepick.saveInstanceState(this, outState);
+    }
+
     public void setToolbarTitle(String title) {
         getBaseActivity().setToolbarTitle(title);
     }

+ 0 - 8
app/src/main/java/eu/kanade/mangafeed/ui/catalogue/CatalogueFragment.java

@@ -33,7 +33,6 @@ import eu.kanade.mangafeed.ui.main.MainActivity;
 import eu.kanade.mangafeed.ui.manga.MangaActivity;
 import eu.kanade.mangafeed.util.ToastUtil;
 import eu.kanade.mangafeed.widget.EndlessScrollListener;
-import icepick.Icepick;
 import icepick.State;
 import nucleus.factory.RequiresPresenter;
 import rx.Subscription;
@@ -66,7 +65,6 @@ public class CatalogueFragment extends BaseRxFragment<CataloguePresenter> {
     @Override
     public void onCreate(Bundle savedState) {
         super.onCreate(savedState);
-        Icepick.restoreInstanceState(this, savedState);
         setHasOptionsMenu(true);
     }
 
@@ -168,12 +166,6 @@ public class CatalogueFragment extends BaseRxFragment<CataloguePresenter> {
         super.onDestroyView();
     }
 
-    @Override
-    public void onSaveInstanceState(Bundle outState) {
-        Icepick.saveInstanceState(this, outState);
-        super.onSaveInstanceState(outState);
-    }
-
     private void initializeSearchSubscription() {
         queryDebouncerSubject = PublishSubject.create();
         queryDebouncerSubscription = queryDebouncerSubject

+ 0 - 3
app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryCategoryFragment.java

@@ -24,7 +24,6 @@ import eu.kanade.mangafeed.ui.base.fragment.BaseFragment;
 import eu.kanade.mangafeed.ui.manga.MangaActivity;
 import eu.kanade.mangafeed.util.EventBusHook;
 import eu.kanade.mangafeed.widget.AutofitRecyclerView;
-import icepick.Icepick;
 import icepick.State;
 import rx.Subscription;
 
@@ -49,7 +48,6 @@ public class LibraryCategoryFragment extends BaseFragment
         // Inflate the layout for this fragment
         View view = inflater.inflate(R.layout.fragment_library_category, container, false);
         ButterKnife.bind(this, view);
-        Icepick.restoreInstanceState(this, savedState);
 
         adapter = new LibraryCategoryAdapter(this);
         recycler.setHasFixedSize(true);
@@ -98,7 +96,6 @@ public class LibraryCategoryFragment extends BaseFragment
 
     @Override
     public void onSaveInstanceState(Bundle outState) {
-        Icepick.saveInstanceState(this, outState);
         adapter.onSaveInstanceState(outState);
         super.onSaveInstanceState(outState);
     }

+ 25 - 13
app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryFragment.java

@@ -5,7 +5,6 @@ import android.os.Bundle;
 import android.support.annotation.Nullable;
 import android.support.design.widget.AppBarLayout;
 import android.support.design.widget.TabLayout;
-import android.support.v4.app.Fragment;
 import android.support.v4.view.ViewPager;
 import android.support.v7.view.ActionMode;
 import android.util.Pair;
@@ -31,24 +30,26 @@ import eu.kanade.mangafeed.data.database.models.Category;
 import eu.kanade.mangafeed.data.database.models.Manga;
 import eu.kanade.mangafeed.data.sync.LibraryUpdateService;
 import eu.kanade.mangafeed.event.LibraryMangasEvent;
-import eu.kanade.mangafeed.ui.base.activity.BaseActivity;
 import eu.kanade.mangafeed.ui.base.fragment.BaseRxFragment;
-import eu.kanade.mangafeed.ui.library.category.CategoryFragment;
+import eu.kanade.mangafeed.ui.library.category.CategoryActivity;
 import eu.kanade.mangafeed.ui.main.MainActivity;
+import icepick.State;
 import nucleus.factory.RequiresPresenter;
 
 @RequiresPresenter(LibraryPresenter.class)
 public class LibraryFragment extends BaseRxFragment<LibraryPresenter>
         implements ActionMode.Callback {
 
-    TabLayout tabs;
-    AppBarLayout appBar;
-
     @Bind(R.id.view_pager) ViewPager viewPager;
+    private TabLayout tabs;
+    private AppBarLayout appBar;
+
     protected LibraryAdapter adapter;
 
     private ActionMode actionMode;
 
+    @State int activeCategory;
+
     public static LibraryFragment newInstance() {
         return new LibraryFragment();
     }
@@ -68,12 +69,12 @@ public class LibraryFragment extends BaseRxFragment<LibraryPresenter>
         ButterKnife.bind(this, view);
 
         appBar = ((MainActivity) getActivity()).getAppBar();
-        tabs = (TabLayout) inflater.inflate(R.layout.tab_layout, appBar, false);
+        tabs = (TabLayout) inflater.inflate(R.layout.library_tab_layout, appBar, false);
         appBar.addView(tabs);
 
-
         adapter = new LibraryAdapter(getChildFragmentManager());
         viewPager.setAdapter(adapter);
+        tabs.setupWithViewPager(viewPager);
 
         return view;
     }
@@ -81,9 +82,16 @@ public class LibraryFragment extends BaseRxFragment<LibraryPresenter>
     @Override
     public void onDestroyView() {
         appBar.removeView(tabs);
+        EventBus.getDefault().removeStickyEvent(LibraryMangasEvent.class);
         super.onDestroyView();
     }
 
+    @Override
+    public void onSaveInstanceState(Bundle bundle) {
+        activeCategory = viewPager.getCurrentItem();
+        super.onSaveInstanceState(bundle);
+    }
+
     @Override
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
         inflater.inflate(R.menu.library, menu);
@@ -107,8 +115,8 @@ public class LibraryFragment extends BaseRxFragment<LibraryPresenter>
     }
 
     private void onEditCategories() {
-        Fragment fragment = CategoryFragment.newInstance();
-        ((MainActivity) getActivity()).pushFragment(fragment);
+        Intent intent = CategoryActivity.newIntent(getActivity());
+        startActivity(intent);
     }
 
     public void onNextLibraryUpdate(Pair<List<Category>, Map<Integer, List<Manga>>> pair) {
@@ -125,6 +133,10 @@ public class LibraryFragment extends BaseRxFragment<LibraryPresenter>
         else if (!mangasInDefaultCategory && (!initialized || adapter.hasDefaultCategory())) {
             setCategories(pair.first);
         }
+        // Restore active category
+        if (!initialized) {
+            viewPager.setCurrentItem(activeCategory, false);
+        }
         // Send the mangas to child fragments after the adapter is updated
         EventBus.getDefault().postSticky(new LibraryMangasEvent(pair.second));
     }
@@ -139,8 +151,8 @@ public class LibraryFragment extends BaseRxFragment<LibraryPresenter>
 
     private void setCategories(List<Category> categories) {
         adapter.setCategories(categories);
-        tabs.setupWithViewPager(viewPager);
-        tabs.setVisibility(categories.size() == 1 ? View.GONE : View.VISIBLE);
+        tabs.setTabsFromPagerAdapter(adapter);
+        tabs.setVisibility(categories.size() <= 1 ? View.GONE : View.VISIBLE);
     }
 
     public void setContextTitle(int count) {
@@ -211,7 +223,7 @@ public class LibraryFragment extends BaseRxFragment<LibraryPresenter>
 
     public void createActionModeIfNeeded() {
         if (actionMode == null) {
-            actionMode = ((BaseActivity) getActivity()).startSupportActionMode(this);
+            actionMode = getBaseActivity().startSupportActionMode(this);
         }
     }
 

+ 1 - 1
app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryPresenter.java

@@ -59,7 +59,7 @@ public class LibraryPresenter extends BasePresenter<LibraryFragment> {
                 .observeOn(AndroidSchedulers.mainThread());
     }
 
-    public Observable<List<Category>> getCategoriesObservable() {
+    private Observable<List<Category>> getCategoriesObservable() {
         return db.getCategories().createObservable()
                 .doOnNext(categories -> this.categories = categories);
     }

+ 17 - 18
app/src/main/java/eu/kanade/mangafeed/ui/library/category/CategoryFragment.java → app/src/main/java/eu/kanade/mangafeed/ui/library/category/CategoryActivity.java

@@ -1,17 +1,17 @@
 package eu.kanade.mangafeed.ui.library.category;
 
+import android.content.Context;
+import android.content.Intent;
 import android.os.Bundle;
 import android.support.design.widget.FloatingActionButton;
 import android.support.v4.content.res.ResourcesCompat;
 import android.support.v7.view.ActionMode;
 import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.Toolbar;
 import android.support.v7.widget.helper.ItemTouchHelper;
-import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
 
 import com.afollestad.materialdialogs.MaterialDialog;
 
@@ -21,19 +21,19 @@ import butterknife.Bind;
 import butterknife.ButterKnife;
 import eu.kanade.mangafeed.R;
 import eu.kanade.mangafeed.data.database.models.Category;
-import eu.kanade.mangafeed.ui.base.activity.BaseActivity;
+import eu.kanade.mangafeed.ui.base.activity.BaseRxActivity;
 import eu.kanade.mangafeed.ui.base.adapter.FlexibleViewHolder;
 import eu.kanade.mangafeed.ui.base.adapter.OnStartDragListener;
-import eu.kanade.mangafeed.ui.base.fragment.BaseRxFragment;
 import eu.kanade.mangafeed.ui.decoration.DividerItemDecoration;
 import eu.kanade.mangafeed.ui.library.LibraryCategoryAdapter;
 import nucleus.factory.RequiresPresenter;
 import rx.Observable;
 
 @RequiresPresenter(CategoryPresenter.class)
-public class CategoryFragment extends BaseRxFragment<CategoryPresenter> implements
+public class CategoryActivity extends BaseRxActivity<CategoryPresenter> implements
         ActionMode.Callback, FlexibleViewHolder.OnListItemClickListener, OnStartDragListener {
 
+    @Bind(R.id.toolbar) Toolbar toolbar;
     @Bind(R.id.categories_list) RecyclerView recycler;
     @Bind(R.id.fab) FloatingActionButton fab;
 
@@ -41,19 +41,20 @@ public class CategoryFragment extends BaseRxFragment<CategoryPresenter> implemen
     private ActionMode actionMode;
     private ItemTouchHelper touchHelper;
 
-    public static CategoryFragment newInstance() {
-        return new CategoryFragment();
+    public static Intent newIntent(Context context) {
+        return new Intent(context, CategoryActivity.class);
     }
 
     @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
-        View view = inflater.inflate(R.layout.fragment_edit_categories, container, false);
-        ButterKnife.bind(this, view);
+    protected void onCreate(Bundle savedState) {
+        super.onCreate(savedState);
+        setContentView(R.layout.activity_edit_categories);
+        ButterKnife.bind(this);
 
-        setToolbarTitle(R.string.action_edit_categories);
+        setupToolbar(toolbar);
 
         adapter = new CategoryAdapter(this);
-        recycler.setLayoutManager(new LinearLayoutManager(getActivity()));
+        recycler.setLayoutManager(new LinearLayoutManager(this));
         recycler.setHasFixedSize(true);
         recycler.setAdapter(adapter);
         recycler.addItemDecoration(new DividerItemDecoration(
@@ -64,15 +65,13 @@ public class CategoryFragment extends BaseRxFragment<CategoryPresenter> implemen
         touchHelper.attachToRecyclerView(recycler);
 
         fab.setOnClickListener(v -> {
-            new MaterialDialog.Builder(getActivity())
+            new MaterialDialog.Builder(this)
                     .title(R.string.action_add_category)
                     .input(R.string.name, 0, false, (dialog, input) -> {
                         getPresenter().createCategory(input.toString());
                     })
                     .show();
         });
-
-        return view;
     }
 
     public void setCategories(List<Category> categories) {
@@ -99,7 +98,7 @@ public class CategoryFragment extends BaseRxFragment<CategoryPresenter> implemen
     @Override
     public void onListItemLongClick(int position) {
         if (actionMode == null)
-            actionMode = ((BaseActivity) getActivity()).startSupportActionMode(this);
+            actionMode = startSupportActionMode(this);
 
         toggleSelection(position);
     }
@@ -165,7 +164,7 @@ public class CategoryFragment extends BaseRxFragment<CategoryPresenter> implemen
     }
 
     private void editCategory(Category category) {
-        new MaterialDialog.Builder(getActivity())
+        new MaterialDialog.Builder(this)
                 .title(R.string.action_rename_category)
                 .input(getString(R.string.name), category.name, false, (dialog, input) -> {
                     getPresenter().renameCategory(category, input.toString());

+ 6 - 6
app/src/main/java/eu/kanade/mangafeed/ui/library/category/CategoryAdapter.java

@@ -18,11 +18,11 @@ import eu.kanade.mangafeed.ui.base.adapter.ItemTouchHelperAdapter;
 public class CategoryAdapter extends FlexibleAdapter<CategoryHolder, Category> implements
         ItemTouchHelperAdapter {
 
-    private final CategoryFragment fragment;
+    private final CategoryActivity activity;
     private final ColorGenerator generator;
 
-    public CategoryAdapter(CategoryFragment fragment) {
-        this.fragment = fragment;
+    public CategoryAdapter(CategoryActivity activity) {
+        this.activity = activity;
         generator = ColorGenerator.DEFAULT;
         setHasStableIds(true);
     }
@@ -44,9 +44,9 @@ public class CategoryAdapter extends FlexibleAdapter<CategoryHolder, Category> i
 
     @Override
     public CategoryHolder onCreateViewHolder(ViewGroup parent, int viewType) {
-        LayoutInflater inflater = LayoutInflater.from(fragment.getActivity());
+        LayoutInflater inflater = activity.getLayoutInflater();
         View v = inflater.inflate(R.layout.item_edit_categories, parent, false);
-        return new CategoryHolder(v, this, fragment, fragment);
+        return new CategoryHolder(v, this, activity, activity);
     }
 
     @Override
@@ -70,7 +70,7 @@ public class CategoryAdapter extends FlexibleAdapter<CategoryHolder, Category> i
             }
         }
 
-        fragment.getPresenter().reorderCategories(mItems);
+        activity.getPresenter().reorderCategories(mItems);
     }
 
     @Override

+ 2 - 2
app/src/main/java/eu/kanade/mangafeed/ui/library/category/CategoryPresenter.java

@@ -11,7 +11,7 @@ import eu.kanade.mangafeed.data.database.models.Category;
 import eu.kanade.mangafeed.ui.base.presenter.BasePresenter;
 import rx.android.schedulers.AndroidSchedulers;
 
-public class CategoryPresenter extends BasePresenter<CategoryFragment> {
+public class CategoryPresenter extends BasePresenter<CategoryActivity> {
 
     @Inject DatabaseHelper db;
 
@@ -27,7 +27,7 @@ public class CategoryPresenter extends BasePresenter<CategoryFragment> {
                 () -> db.getCategories().createObservable()
                         .doOnNext(categories -> this.categories = categories)
                         .observeOn(AndroidSchedulers.mainThread()),
-                CategoryFragment::setCategories);
+                CategoryActivity::setCategories);
 
         start(GET_CATEGORIES);
     }

+ 1 - 2
app/src/main/java/eu/kanade/mangafeed/ui/manga/chapter/ChaptersFragment.java

@@ -27,7 +27,6 @@ import eu.kanade.mangafeed.R;
 import eu.kanade.mangafeed.data.database.models.Chapter;
 import eu.kanade.mangafeed.data.download.DownloadService;
 import eu.kanade.mangafeed.data.download.model.Download;
-import eu.kanade.mangafeed.ui.base.activity.BaseActivity;
 import eu.kanade.mangafeed.ui.base.adapter.FlexibleViewHolder;
 import eu.kanade.mangafeed.ui.base.fragment.BaseRxFragment;
 import eu.kanade.mangafeed.ui.decoration.DividerItemDecoration;
@@ -329,7 +328,7 @@ public class ChaptersFragment extends BaseRxFragment<ChaptersPresenter> implemen
     @Override
     public void onListItemLongClick(int position) {
         if (actionMode == null)
-            actionMode = ((BaseActivity) getActivity()).startSupportActionMode(this);
+            actionMode = getBaseActivity().startSupportActionMode(this);
 
         toggleSelection(position);
     }

+ 10 - 6
app/src/main/res/layout/fragment_edit_categories.xml → app/src/main/res/layout/activity_edit_categories.xml

@@ -2,13 +2,16 @@
 <android.support.design.widget.CoordinatorLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:orientation="vertical"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:gravity="center">
+
+    <include layout="@layout/toolbar"/>
 
     <android.support.v7.widget.RecyclerView
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_marginTop="?attr/actionBarSize"
         android:id="@+id/categories_list"
         android:choiceMode="multipleChoice"
         android:listSelector="@color/list_choice_pressed_bg_light" />
@@ -17,10 +20,11 @@
         android:id="@+id/fab"
         android:layout_height="wrap_content"
         android:layout_width="wrap_content"
-        android:layout_gravity="end|bottom"
+        android:layout_gravity="bottom|right"
         android:layout_margin="@dimen/fab_margin"
-        android:clickable="true"
         android:src="@drawable/ic_action_add_18dp"
-        app:borderWidth="0dp"/>
+        app:layout_anchor="@id/categories_list"
+        app:layout_anchorGravity="bottom|right|end"
+        app:layout_behavior="eu.kanade.mangafeed.ui.base.fab.ScrollAwareFABBehavior"/>
 
 </android.support.design.widget.CoordinatorLayout>

+ 5 - 3
app/src/main/res/layout/activity_main.xml

@@ -1,4 +1,6 @@
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<android.support.design.widget.CoordinatorLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:gravity="center">
@@ -18,7 +20,7 @@
         android:id="@+id/drawer_container"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:layout_below="@id/appbar">
+        app:layout_behavior="@string/appbar_scrolling_view_behavior">
 
         <!-- the layout which will be the content of the activity (which will be hosted inside the drawer (NOT the list of the drawer)) -->
         <FrameLayout
@@ -28,4 +30,4 @@
 
         </FrameLayout>
     </FrameLayout>
-</RelativeLayout>
+</android.support.design.widget.CoordinatorLayout>

+ 14 - 0
app/src/main/res/layout/library_tab_layout.xml

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.design.widget.TabLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/tabs"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:theme="@style/ThemeOverlay.AppTheme.Dark"
+    android:background="@color/colorPrimary"
+    android:elevation="4dp"
+    app:tabGravity="center"
+    app:tabMode="scrollable"
+    app:tabMinWidth="75dp"
+    app:tabIndicatorColor="@color/white"/>

+ 1 - 0
app/src/main/res/layout/toolbar.xml

@@ -7,4 +7,5 @@
     android:background="@color/colorPrimary"
     android:elevation="4dp"
     android:theme="@style/ThemeOverlay.AppTheme.Dark"
+    app:layout_scrollFlags="scroll|enterAlways"
     app:popupTheme="@style/AppTheme.Popup" />

+ 1 - 0
app/src/main/res/values/strings.xml

@@ -9,6 +9,7 @@
     <string name="label_library">My library</string>
     <string name="label_recent_updates">Recent updates</string>
     <string name="label_catalogues">Catalogues</string>
+    <string name="label_categories">Categories</string>
     <string name="label_selected">Selected: %1$d</string>
 
     <!-- Actions -->