diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.java b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.java
index 713c05503..f182f2e4f 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.java
+++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.java
@@ -378,17 +378,21 @@ public class DownloadManager {
         savePageList(download.source, download.manga, download.chapter, download.pages);
     }
 
-    // Get the absolute path to the chapter directory
-    public File getAbsoluteChapterDirectory(Source source, Manga manga, Chapter chapter) {
+    public File getAbsoluteMangaDirectory(Source source, Manga manga) {
         String chapterRelativePath = source.getName() +
                 File.separator +
-                manga.title.replaceAll("[^\\sa-zA-Z0-9.-]", "_") +
-                File.separator +
-                chapter.name.replaceAll("[^\\sa-zA-Z0-9.-]", "_");
+                manga.title.replaceAll("[^\\sa-zA-Z0-9.-]", "_");
 
         return new File(preferences.getDownloadsDirectory(), chapterRelativePath);
     }
 
+    // Get the absolute path to the chapter directory
+    public File getAbsoluteChapterDirectory(Source source, Manga manga, Chapter chapter) {
+        String chapterRelativePath = chapter.name.replaceAll("[^\\sa-zA-Z0-9.-]", "_");
+
+        return new File(getAbsoluteMangaDirectory(source, manga), chapterRelativePath);
+    }
+
     // Shortcut for the method above
     private File getAbsoluteChapterDirectory(Download download) {
         return getAbsoluteChapterDirectory(download.source, download.manga, download.chapter);
diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt
index c5ee1cefc..c5adab461 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt
@@ -11,6 +11,10 @@ import eu.kanade.tachiyomi.data.source.base.Source
 import java.io.File
 import java.io.IOException
 
+fun <T> Preference<T>.getOrDefault(): T {
+    return get() ?: defaultValue()!!
+}
+
 class PreferencesHelper(private val context: Context) {
 
     private val prefs = PreferenceManager.getDefaultSharedPreferences(context)
@@ -182,4 +186,12 @@ class PreferencesHelper(private val context: Context) {
         return rxPrefs.getInteger(getKey(R.string.pref_library_update_interval_key), 0)
     }
 
+    fun filterDownloaded(): Preference<Boolean> {
+        return rxPrefs.getBoolean(getKey(R.string.pref_filter_downloaded), false)
+    }
+
+    fun filterUnread(): Preference<Boolean> {
+        return rxPrefs.getBoolean(getKey(R.string.pref_filter_unread), false)
+    }
+
 }
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryFragment.kt
index 50950803b..7a0403920 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryFragment.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryFragment.kt
@@ -74,6 +74,17 @@ class LibraryFragment : BaseRxFragment<LibraryPresenter>(), ActionMode.Callback
      */
     private var selectedCoverManga: Manga? = null
 
+
+    /**
+     * TODO
+     */
+    var isFilterDownloaded = false
+
+    /**
+     * TODO
+     */
+    var isFilterUnread = false
+
     companion object {
         /**
          * Key to change the cover of a manga in [onActivityResult].
@@ -104,6 +115,8 @@ class LibraryFragment : BaseRxFragment<LibraryPresenter>(), ActionMode.Callback
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         setHasOptionsMenu(true)
+        isFilterDownloaded = presenter.preferences.filterDownloaded().get() as Boolean
+        isFilterUnread = presenter.preferences.filterUnread().get() as Boolean
     }
 
     override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedState: Bundle?): View? {
@@ -116,6 +129,14 @@ class LibraryFragment : BaseRxFragment<LibraryPresenter>(), ActionMode.Callback
 
         appBar = (activity as MainActivity).appBar
         tabs = appBar.inflate(R.layout.library_tab_layout) as TabLayout
+
+        // Workaround to prevent: Tab belongs to a different TabLayout.
+        // Internal bug in Support library v23.2.0.
+        // See https://code.google.com/p/android/issues/detail?id=201827
+        for (j in 0..16) {
+            tabs.newTab()
+        }
+
         appBar.addView(tabs)
 
         adapter = LibraryAdapter(childFragmentManager)
@@ -144,6 +165,8 @@ class LibraryFragment : BaseRxFragment<LibraryPresenter>(), ActionMode.Callback
         inflater.inflate(R.menu.library, menu)
 
         // Initialize search menu
+        val filterDownloadedItem = menu.findItem(R.id.action_filter_downloaded)
+        val filterUnreadItem = menu.findItem(R.id.action_filter_unread)
         val searchItem = menu.findItem(R.id.action_search)
         val searchView = searchItem.actionView as SearchView
 
@@ -153,6 +176,9 @@ class LibraryFragment : BaseRxFragment<LibraryPresenter>(), ActionMode.Callback
             searchView.clearFocus()
         }
 
+        filterDownloadedItem.isChecked = isFilterDownloaded;
+        filterUnreadItem.isChecked = isFilterUnread;
+
         searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
             override fun onQueryTextSubmit(query: String): Boolean {
                 onSearchTextChange(query)
@@ -168,6 +194,32 @@ class LibraryFragment : BaseRxFragment<LibraryPresenter>(), ActionMode.Callback
 
     override fun onOptionsItemSelected(item: MenuItem): Boolean {
         when (item.itemId) {
+            R.id.action_filter_unread -> {
+                // Change unread filter status.
+                isFilterUnread = !isFilterUnread
+                // Update settings.
+                presenter.preferences.filterUnread().set(isFilterUnread)
+                // Apply filter.
+                onFilterCheckboxChanged()
+            }
+            R.id.action_filter_downloaded -> {
+                // Change downloaded filter status.
+                isFilterDownloaded = !isFilterDownloaded
+                // Update settings.
+                presenter.preferences.filterDownloaded().set(isFilterDownloaded)
+                // Apply filter.
+                onFilterCheckboxChanged()
+            }
+            R.id.action_filter_empty -> {
+                // Remove filter status.
+                isFilterUnread = false
+                isFilterDownloaded = false
+                // Update settings.
+                presenter.preferences.filterUnread().set(isFilterUnread)
+                presenter.preferences.filterDownloaded().set(isFilterDownloaded)
+                // Apply filter
+                onFilterCheckboxChanged()
+            }
             R.id.action_refresh -> LibraryUpdateService.start(activity)
             R.id.action_edit_categories -> {
                 val intent = CategoryActivity.newIntent(activity)
@@ -179,6 +231,16 @@ class LibraryFragment : BaseRxFragment<LibraryPresenter>(), ActionMode.Callback
         return true
     }
 
+    /**
+     * Applies filter change
+     */
+    private fun onFilterCheckboxChanged() {
+        presenter.updateLibrary()
+        adapter.notifyDataSetChanged()
+        adapter.refreshRegisteredAdapters()
+        activity.supportInvalidateOptionsMenu();
+    }
+
     /**
      * Updates the query.
      *
@@ -211,6 +273,10 @@ class LibraryFragment : BaseRxFragment<LibraryPresenter>(), ActionMode.Callback
         // Restore active category.
         view_pager.setCurrentItem(activeCat, false)
         if (tabs.tabCount > 0) {
+            // Prevent IndexOutOfBoundsException
+            if (tabs.tabCount <= view_pager.currentItem) {
+                view_pager.currentItem = (tabs.tabCount - 1)
+            }
             tabs.getTabAt(view_pager.currentItem)?.select()
         }
 
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt
index 23269398f..7e0bf1bf6 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt
@@ -7,7 +7,9 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper
 import eu.kanade.tachiyomi.data.database.models.Category
 import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.data.database.models.MangaCategory
+import eu.kanade.tachiyomi.data.download.DownloadManager
 import eu.kanade.tachiyomi.data.preference.PreferencesHelper
+import eu.kanade.tachiyomi.data.preference.getOrDefault
 import eu.kanade.tachiyomi.data.source.SourceManager
 import eu.kanade.tachiyomi.event.LibraryMangasEvent
 import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
@@ -60,6 +62,11 @@ class LibraryPresenter : BasePresenter<LibraryFragment>() {
      */
     @Inject lateinit var sourceManager: SourceManager
 
+    /**
+     * Download manager.
+     */
+    @Inject lateinit var downloadManager: DownloadManager
+
     companion object {
         /**
          * Id of the restartable that listens for library updates.
@@ -107,6 +114,13 @@ class LibraryPresenter : BasePresenter<LibraryFragment>() {
                 .observeOn(AndroidSchedulers.mainThread())
     }
 
+    /**
+     * Update the library information
+     */
+    fun updateLibrary() {
+        start(GET_LIBRARY)
+    }
+
     /**
      * Get the categories from the database.
      *
@@ -125,13 +139,64 @@ class LibraryPresenter : BasePresenter<LibraryFragment>() {
      */
     fun getLibraryMangasObservable(): Observable<Map<Int, List<Manga>>> {
         return db.libraryMangas.asRxObservable()
-                .flatMap { mangas -> Observable.from(mangas)
-                        .groupBy { it.category }
-                        .flatMap { group -> group.toList().map { Pair(group.key, it) } }
-                        .toMap({ it.first }, { it.second })
+                .flatMap { mangas ->
+                    Observable.from(mangas)
+                            .filter {
+                                // Filter library by options
+                                filterLibrary(it)
+                            }
+                            .groupBy { it.category }
+                            .flatMap { group -> group.toList().map { Pair(group.key, it) } }
+                            .toMap({ it.first }, { it.second })
                 }
     }
 
+    /**
+     * Filter library by preference
+     *
+     * @param manga from library
+     * @return filter status
+     */
+    fun filterLibrary(manga: Manga): Boolean {
+        val prefFilterDownloaded = preferences.filterDownloaded().getOrDefault()
+        val prefFilterUnread = preferences.filterUnread().getOrDefault()
+
+        // Check if filter option is selected
+        if (prefFilterDownloaded || prefFilterUnread) {
+
+            // Does it have downloaded chapters.
+            var hasDownloaded = false
+            var hasUnread = false
+
+            if (prefFilterUnread) {
+                // Does it have unread chapters.
+                hasUnread = manga.unread > 0
+            }
+
+            if (prefFilterDownloaded) {
+                val mangaDir = downloadManager.getAbsoluteMangaDirectory(sourceManager.get(manga.source), manga)
+
+                if (mangaDir.exists()) {
+                    for (file in mangaDir.listFiles()) {
+                        if (file.isDirectory && file.listFiles().isNotEmpty()) {
+                            hasDownloaded = true
+                            break
+                        }
+                    }
+                }
+            }
+
+            // Return correct filter status
+            if (prefFilterDownloaded && prefFilterUnread) {
+                return (hasDownloaded && hasUnread)
+            } else {
+                return (hasDownloaded || hasUnread)
+            }
+        } else {
+            return true
+        }
+    }
+
     /**
      * Called when a manga is opened.
      */
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaActivity.java b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaActivity.java
index a488a4cb2..d357b0503 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaActivity.java
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaActivity.java
@@ -77,6 +77,13 @@ public class MangaActivity extends BaseRxActivity<MangaPresenter> {
         adapter = new MangaDetailAdapter(getSupportFragmentManager(), this);
 
         viewPager.setAdapter(adapter);
+
+        // Workaround to prevent: Tab belongs to a different TabLayout.
+        // Internal bug in Support library v23.2.0.
+        // See https://code.google.com/p/android/issues/detail?id=201827
+        for (int j = 0; j < 17; j++)
+            tabs.newTab();
+
         tabs.setupWithViewPager(viewPager);
 
         if (!isOnline)
diff --git a/app/src/main/res/drawable/ic_filter_list.xml b/app/src/main/res/drawable/ic_filter_list.xml
new file mode 100644
index 000000000..7d435fa2b
--- /dev/null
+++ b/app/src/main/res/drawable/ic_filter_list.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M10,18h4v-2h-4v2zM3,6v2h18L21,6L3,6zM6,13h12v-2L6,11v2z"/>
+</vector>
diff --git a/app/src/main/res/menu/library.xml b/app/src/main/res/menu/library.xml
index 29639aa09..474a8f912 100644
--- a/app/src/main/res/menu/library.xml
+++ b/app/src/main/res/menu/library.xml
@@ -2,6 +2,26 @@
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
 
+    <item
+        android:id="@+id/action_filter"
+        android:title="@string/action_filter"
+        android:icon="@drawable/ic_filter_list"
+        app:showAsAction="ifRoom">
+        <menu>
+            <item
+                android:id="@+id/action_filter_downloaded"
+                android:checkable="true"
+                android:title="@string/action_filter_downloaded"/>
+            <item
+                android:id="@+id/action_filter_unread"
+                android:checkable="true"
+                android:title="@string/action_filter_unread"/>
+            <item
+                android:id="@+id/action_filter_empty"
+                android:title="@string/action_filter_empty"/>
+        </menu>
+    </item>
+
     <item
         android:id="@+id/action_search"
         android:title="@string/action_search"
diff --git a/app/src/main/res/values/keys.xml b/app/src/main/res/values/keys.xml
index c89ef298a..b1a061281 100644
--- a/app/src/main/res/values/keys.xml
+++ b/app/src/main/res/values/keys.xml
@@ -28,6 +28,8 @@
     <string name="pref_reader_theme_key">pref_reader_theme_key</string>
     <string name="pref_image_decoder_key">pref_image_decoder_key</string>
     <string name="pref_seamless_mode_key">pref_seamless_mode_key</string>
+    <string name="pref_filter_downloaded">pref_filter_downloaded</string>
+    <string name="pref_filter_unread">pref_filter_unread</string>
 
     <string name="pref_download_directory_key">pref_download_directory_key</string>
     <string name="pref_download_slots_key">pref_download_slots_key</string>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index a4c231ec3..fb6210728 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -14,6 +14,10 @@
 
     <!-- Actions -->
     <string name="action_settings">Settings</string>
+    <string name="action_filter">Filter</string>
+    <string name="action_filter_downloaded">Downloaded</string>
+    <string name="action_filter_unread">Unread</string>
+    <string name="action_filter_empty">Remove filter</string>
     <string name="action_search">Search</string>
     <string name="action_refresh">Refresh</string>
     <string name="action_select_all">Select all</string>
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index a86901edf..6023805e5 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -15,7 +15,7 @@
         <item name="actionModeBackground">@color/colorPrimarySuperDark</item>
         <item name="actionBarPopupTheme">@style/ThemeOverlay.AppCompat.Light</item>
         <item name="popupTheme">@style/ThemeOverlay.AppCompat.Light</item>
-        <item name="colorAccent">@color/white</item>
+        <item name="colorAccent">@color/colorAccent</item>
     </style>
 
     <style name="AppTheme.Overlay.Dark" parent="ThemeOverlay.AppCompat.Dark.ActionBar">