Downloads with conductor. Remove flexible adapter 4 dependency and unused classes.

This commit is contained in:
len 2017-05-23 20:03:16 +02:00
parent f521622d4d
commit 72ea256906
10 changed files with 306 additions and 397 deletions

View File

@ -100,17 +100,6 @@ android {
dependencies { dependencies {
compile "com.bluelinelabs:conductor:2.1.3"
compile 'com.github.inorichi:conductor-support-preference:master-SNAPSHOT'
final rxbindings_version = '1.0.1'
compile "com.jakewharton.rxbinding:rxbinding-kotlin:$rxbindings_version"
compile "com.jakewharton.rxbinding:rxbinding-appcompat-v7-kotlin:$rxbindings_version"
compile "com.jakewharton.rxbinding:rxbinding-support-v4-kotlin:$rxbindings_version"
compile "com.jakewharton.rxbinding:rxbinding-recyclerview-v7-kotlin:$rxbindings_version"
compile 'com.nightlynexus.viewstatepageradapter:viewstatepageradapter:1.0.4'
// Modified dependencies // Modified dependencies
compile 'com.github.inorichi:subsampling-scale-image-view:01e5385' compile 'com.github.inorichi:subsampling-scale-image-view:01e5385'
compile 'com.github.inorichi:junrar-android:634c1f5' compile 'com.github.inorichi:junrar-android:634c1f5'
@ -201,12 +190,23 @@ dependencies {
compile 'com.dmitrymalkovich.android:material-design-dimens:1.4' compile 'com.dmitrymalkovich.android:material-design-dimens:1.4'
compile 'com.github.dmytrodanylyk.android-process-button:library:1.0.4' compile 'com.github.dmytrodanylyk.android-process-button:library:1.0.4'
compile 'eu.davidea:flexible-adapter:5.0.0-rc1' compile 'eu.davidea:flexible-adapter:5.0.0-rc1'
compile 'com.github.inorichi:FlexibleAdapter:93985fe' // v4.2.0 to be removed
compile 'com.nononsenseapps:filepicker:2.5.2' compile 'com.nononsenseapps:filepicker:2.5.2'
compile 'com.github.amulyakhare:TextDrawable:558677e' compile 'com.github.amulyakhare:TextDrawable:558677e'
compile 'com.afollestad.material-dialogs:core:0.9.4.2' compile 'com.afollestad.material-dialogs:core:0.9.4.2'
compile 'me.zhanghai.android.systemuihelper:library:1.0.0' compile 'me.zhanghai.android.systemuihelper:library:1.0.0'
compile 'de.hdodenhof:circleimageview:2.1.0' compile 'de.hdodenhof:circleimageview:2.1.0'
compile 'com.nightlynexus.viewstatepageradapter:viewstatepageradapter:1.0.4'
// Conductor
compile "com.bluelinelabs:conductor:2.1.3"
compile 'com.github.inorichi:conductor-support-preference:9e36460'
// RxBindings
final rxbindings_version = '1.0.1'
compile "com.jakewharton.rxbinding:rxbinding-kotlin:$rxbindings_version"
compile "com.jakewharton.rxbinding:rxbinding-appcompat-v7-kotlin:$rxbindings_version"
compile "com.jakewharton.rxbinding:rxbinding-support-v4-kotlin:$rxbindings_version"
compile "com.jakewharton.rxbinding:rxbinding-recyclerview-v7-kotlin:$rxbindings_version"
// Tests // Tests
testCompile 'junit:junit:4.12' testCompile 'junit:junit:4.12'

View File

@ -53,9 +53,6 @@
android:scheme="tachiyomi" /> android:scheme="tachiyomi" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity
android:name=".ui.download.DownloadActivity"
android:launchMode="singleTop" />
<provider <provider
android:name="android.support.v4.content.FileProvider" android:name="android.support.v4.content.FileProvider"

View File

@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.data.notification
import android.app.PendingIntent import android.app.PendingIntent
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import eu.kanade.tachiyomi.ui.download.DownloadActivity import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.util.getUriCompat import eu.kanade.tachiyomi.util.getUriCompat
import java.io.File import java.io.File
@ -17,8 +17,9 @@ object NotificationHandler {
* @param context context of application * @param context context of application
*/ */
internal fun openDownloadManagerPendingActivity(context: Context): PendingIntent { internal fun openDownloadManagerPendingActivity(context: Context): PendingIntent {
val intent = Intent(context, DownloadActivity::class.java).apply { val intent = Intent(context, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_REORDER_TO_FRONT flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
action = MainActivity.SHORTCUT_DOWNLOADS
} }
return PendingIntent.getActivity(context, 0, intent, 0) return PendingIntent.getActivity(context, 0, intent, 0)
} }

View File

@ -1,39 +0,0 @@
package eu.kanade.tachiyomi.ui.base.adapter
import android.support.v7.widget.RecyclerView
import android.view.View
import eu.davidea.flexibleadapter4.FlexibleAdapter
abstract class FlexibleViewHolder(view: View,
private val adapter: FlexibleAdapter<*, *>,
private val itemClickListener: FlexibleViewHolder.OnListItemClickListener) :
RecyclerView.ViewHolder(view), View.OnClickListener, View.OnLongClickListener {
init {
view.setOnClickListener(this)
view.setOnLongClickListener(this)
}
override fun onClick(view: View) {
if (itemClickListener.onListItemClick(adapterPosition)) {
toggleActivation()
}
}
override fun onLongClick(view: View): Boolean {
itemClickListener.onListItemLongClick(adapterPosition)
toggleActivation()
return true
}
fun toggleActivation() {
itemView.isActivated = adapter.isSelected(adapterPosition)
}
interface OnListItemClickListener {
fun onListItemClick(position: Int): Boolean
fun onListItemLongClick(position: Int)
}
}

View File

@ -1,41 +0,0 @@
package eu.kanade.tachiyomi.ui.base.adapter
import android.support.v4.app.Fragment
import android.support.v4.app.FragmentManager
import android.support.v4.app.FragmentStatePagerAdapter
import android.util.SparseArray
import android.view.ViewGroup
import java.util.*
abstract class SmartFragmentStatePagerAdapter(fragmentManager: FragmentManager) :
FragmentStatePagerAdapter(fragmentManager) {
// Sparse array to keep track of registered fragments in memory
private val registeredFragments = SparseArray<Fragment>()
// Register the fragment when the item is instantiated
override fun instantiateItem(container: ViewGroup, position: Int): Any {
val fragment = super.instantiateItem(container, position) as Fragment
registeredFragments.put(position, fragment)
return fragment
}
// Unregister when the item is inactive
override fun destroyItem(container: ViewGroup?, position: Int, `object`: Any) {
registeredFragments.remove(position)
super.destroyItem(container, position, `object`)
}
// Returns the fragment for the position (if instantiated)
fun getRegisteredFragment(position: Int): Fragment {
return registeredFragments.get(position)
}
fun getRegisteredFragments(): List<Fragment> {
val fragments = ArrayList<Fragment>()
for (i in 0..registeredFragments.size() - 1) {
fragments.add(registeredFragments.valueAt(i))
}
return fragments
}
}

View File

@ -1,8 +1,7 @@
package eu.kanade.tachiyomi.ui.download package eu.kanade.tachiyomi.ui.download
import android.content.Context import android.support.v7.widget.RecyclerView
import android.view.ViewGroup import android.view.ViewGroup
import eu.davidea.flexibleadapter4.FlexibleAdapter
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.util.inflate import eu.kanade.tachiyomi.util.inflate
@ -12,7 +11,9 @@ import eu.kanade.tachiyomi.util.inflate
* *
* @param context the context of the fragment containing this adapter. * @param context the context of the fragment containing this adapter.
*/ */
class DownloadAdapter(private val context: Context) : FlexibleAdapter<DownloadHolder, Download>() { class DownloadAdapter : RecyclerView.Adapter<DownloadHolder>() {
private var items = emptyList<Download>()
init { init {
setHasStableIds(true) setHasStableIds(true)
@ -24,10 +25,17 @@ class DownloadAdapter(private val context: Context) : FlexibleAdapter<DownloadHo
* @param downloads the list to set. * @param downloads the list to set.
*/ */
fun setItems(downloads: List<Download>) { fun setItems(downloads: List<Download>) {
mItems = downloads items = downloads
notifyDataSetChanged() notifyDataSetChanged()
} }
/**
* Returns the number of downloads in the adapter
*/
override fun getItemCount(): Int {
return items.size
}
/** /**
* Returns the identifier for a download. * Returns the identifier for a download.
* *
@ -35,7 +43,7 @@ class DownloadAdapter(private val context: Context) : FlexibleAdapter<DownloadHo
* @return an identifier for the item. * @return an identifier for the item.
*/ */
override fun getItemId(position: Int): Long { override fun getItemId(position: Int): Long {
return getItem(position).chapter.id!! return items[position].chapter.id!!
} }
/** /**
@ -57,14 +65,8 @@ class DownloadAdapter(private val context: Context) : FlexibleAdapter<DownloadHo
* @param position the position to bind. * @param position the position to bind.
*/ */
override fun onBindViewHolder(holder: DownloadHolder, position: Int) { override fun onBindViewHolder(holder: DownloadHolder, position: Int) {
val download = getItem(position) val download = items[position]
holder.onSetValues(download) holder.onSetValues(download)
} }
/**
* Used to filter the list. Not used.
*/
override fun updateDataSet(param: String) {
}
} }

View File

@ -2,39 +2,29 @@ package eu.kanade.tachiyomi.ui.download
import android.os.Bundle import android.os.Bundle
import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.LinearLayoutManager
import android.view.Menu import android.view.*
import android.view.MenuItem
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.download.DownloadService import eu.kanade.tachiyomi.data.download.DownloadService
import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.ui.base.activity.BaseRxActivity import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import eu.kanade.tachiyomi.util.plusAssign import kotlinx.android.synthetic.main.activity_download_manager.view.*
import kotlinx.android.synthetic.main.fragment_download_queue.*
import kotlinx.android.synthetic.main.toolbar.*
import nucleus.factory.RequiresPresenter
import rx.Observable import rx.Observable
import rx.Subscription import rx.Subscription
import rx.android.schedulers.AndroidSchedulers import rx.android.schedulers.AndroidSchedulers
import rx.subscriptions.CompositeSubscription
import java.util.* import java.util.*
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
/** /**
* Activity that shows the currently active downloads. * Controller that shows the currently active downloads.
* Uses R.layout.fragment_download_queue. * Uses R.layout.fragment_download_queue.
*/ */
@RequiresPresenter(DownloadPresenter::class) class DownloadController : NucleusController<DownloadPresenter>() {
class DownloadActivity : BaseRxActivity<DownloadPresenter>() {
/** /**
* Adapter containing the active downloads. * Adapter containing the active downloads.
*/ */
private lateinit var adapter: DownloadAdapter private var adapter: DownloadAdapter? = null
/**
* Subscription list to be cleared during [onDestroy].
*/
private val subscriptions by lazy { CompositeSubscription() }
/** /**
* Map of subscriptions for active downloads. * Map of subscriptions for active downloads.
@ -46,53 +36,66 @@ class DownloadActivity : BaseRxActivity<DownloadPresenter>() {
*/ */
private var isRunning: Boolean = false private var isRunning: Boolean = false
override fun onCreate(savedState: Bundle?) { init {
setAppTheme() setHasOptionsMenu(true)
super.onCreate(savedState) }
setContentView(R.layout.activity_download_manager)
setupToolbar(toolbar) override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
setToolbarTitle(R.string.label_download_queue) return inflater.inflate(R.layout.activity_download_manager, container, false)
}
override fun createPresenter(): DownloadPresenter {
return DownloadPresenter()
}
override fun getTitle(): String? {
return resources?.getString(R.string.label_download_queue)
}
override fun onViewCreated(view: View, savedViewState: Bundle?) {
super.onViewCreated(view, savedViewState)
// Check if download queue is empty and update information accordingly. // Check if download queue is empty and update information accordingly.
setInformationView() setInformationView()
// Initialize adapter. // Initialize adapter.
adapter = DownloadAdapter(this) adapter = DownloadAdapter()
recycler.adapter = adapter with(view) {
recycler.adapter = adapter
// Set the layout manager for the recycler and fixed size. // Set the layout manager for the recycler and fixed size.
recycler.layoutManager = LinearLayoutManager(this) recycler.layoutManager = LinearLayoutManager(context)
recycler.setHasFixedSize(true) recycler.setHasFixedSize(true)
}
// Suscribe to changes // Suscribe to changes
subscriptions += DownloadService.runningRelay DownloadService.runningRelay
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe { onQueueStatusChange(it) } .subscribeUntilDestroy { onQueueStatusChange(it) }
subscriptions += presenter.getDownloadStatusObservable() presenter.getDownloadStatusObservable()
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe { onStatusChange(it) } .subscribeUntilDestroy { onStatusChange(it) }
subscriptions += presenter.getDownloadProgressObservable() presenter.getDownloadProgressObservable()
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe { onUpdateDownloadedPages(it) } .subscribeUntilDestroy { onUpdateDownloadedPages(it) }
} }
override fun onDestroy() { override fun onDestroyView(view: View) {
super.onDestroyView(view)
for (subscription in progressSubscriptions.values) { for (subscription in progressSubscriptions.values) {
subscription.unsubscribe() subscription.unsubscribe()
} }
progressSubscriptions.clear() progressSubscriptions.clear()
subscriptions.clear() adapter = null
super.onDestroy()
} }
override fun onCreateOptionsMenu(menu: Menu): Boolean { override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
menuInflater.inflate(R.menu.download_queue, menu) inflater.inflate(R.menu.download_queue, menu)
return true
} }
override fun onPrepareOptionsMenu(menu: Menu): Boolean { override fun onPrepareOptionsMenu(menu: Menu) {
// Set start button visibility. // Set start button visibility.
menu.findItem(R.id.start_queue).isVisible = !isRunning && !presenter.downloadQueue.isEmpty() menu.findItem(R.id.start_queue).isVisible = !isRunning && !presenter.downloadQueue.isEmpty()
@ -101,18 +104,18 @@ class DownloadActivity : BaseRxActivity<DownloadPresenter>() {
// Set clear button visibility. // Set clear button visibility.
menu.findItem(R.id.clear_queue).isVisible = !presenter.downloadQueue.isEmpty() menu.findItem(R.id.clear_queue).isVisible = !presenter.downloadQueue.isEmpty()
return true
} }
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
val context = applicationContext ?: return false
when (item.itemId) { when (item.itemId) {
R.id.start_queue -> DownloadService.start(this) R.id.start_queue -> DownloadService.start(context)
R.id.pause_queue -> { R.id.pause_queue -> {
DownloadService.stop(this) DownloadService.stop(context)
presenter.pauseDownloads() presenter.pauseDownloads()
} }
R.id.clear_queue -> { R.id.clear_queue -> {
DownloadService.stop(this) DownloadService.stop(context)
presenter.clearQueue() presenter.clearQueue()
} }
else -> return super.onOptionsItemSelected(item) else -> return super.onOptionsItemSelected(item)
@ -187,7 +190,7 @@ class DownloadActivity : BaseRxActivity<DownloadPresenter>() {
*/ */
private fun onQueueStatusChange(running: Boolean) { private fun onQueueStatusChange(running: Boolean) {
isRunning = running isRunning = running
supportInvalidateOptionsMenu() activity?.invalidateOptionsMenu()
// Check if download queue is empty and update information accordingly. // Check if download queue is empty and update information accordingly.
setInformationView() setInformationView()
@ -199,9 +202,9 @@ class DownloadActivity : BaseRxActivity<DownloadPresenter>() {
* @param downloads the downloads from the queue. * @param downloads the downloads from the queue.
*/ */
fun onNextDownloads(downloads: List<Download>) { fun onNextDownloads(downloads: List<Download>) {
supportInvalidateOptionsMenu() activity?.invalidateOptionsMenu()
setInformationView() setInformationView()
adapter.setItems(downloads) adapter?.setItems(downloads)
} }
/** /**
@ -229,6 +232,7 @@ class DownloadActivity : BaseRxActivity<DownloadPresenter>() {
* @return the holder of the download or null if it's not bound. * @return the holder of the download or null if it's not bound.
*/ */
private fun getHolder(download: Download): DownloadHolder? { private fun getHolder(download: Download): DownloadHolder? {
val recycler = view?.recycler ?: return null
return recycler.findViewHolderForItemId(download.chapter.id!!) as? DownloadHolder return recycler.findViewHolderForItemId(download.chapter.id!!) as? DownloadHolder
} }
@ -236,11 +240,13 @@ class DownloadActivity : BaseRxActivity<DownloadPresenter>() {
* Set information view when queue is empty * Set information view when queue is empty
*/ */
private fun setInformationView() { private fun setInformationView() {
updateEmptyView(presenter.downloadQueue.isEmpty(), val emptyView = view?.empty_view ?: return
R.string.information_no_downloads, R.drawable.ic_file_download_black_128dp) if (presenter.downloadQueue.isEmpty()) {
emptyView.show(R.drawable.ic_file_download_black_128dp,
R.string.information_no_downloads)
} else {
emptyView.hide()
}
} }
fun updateEmptyView(show: Boolean, textResource: Int, drawable: Int) {
// if (show) empty_view.show(drawable, textResource) else empty_view.hide()
}
} }

View File

@ -12,9 +12,9 @@ import uy.kohesive.injekt.injectLazy
import java.util.* import java.util.*
/** /**
* Presenter of [DownloadActivity]. * Presenter of [DownloadController].
*/ */
class DownloadPresenter : BasePresenter<DownloadActivity>() { class DownloadPresenter : BasePresenter<DownloadController>() {
/** /**
* Download manager. * Download manager.
@ -33,7 +33,7 @@ class DownloadPresenter : BasePresenter<DownloadActivity>() {
downloadQueue.getUpdatedObservable() downloadQueue.getUpdatedObservable()
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.map { ArrayList(it) } .map { ArrayList(it) }
.subscribeLatestCache(DownloadActivity::onNextDownloads, { view, error -> .subscribeLatestCache(DownloadController::onNextDownloads, { view, error ->
Timber.e(error) Timber.e(error)
}) })
} }

View File

@ -1,7 +1,6 @@
package eu.kanade.tachiyomi.ui.main package eu.kanade.tachiyomi.ui.main
import android.animation.ObjectAnimator import android.animation.ObjectAnimator
import android.content.Intent
import android.graphics.Color import android.graphics.Color
import android.os.Bundle import android.os.Bundle
import android.support.v4.view.GravityCompat import android.support.v4.view.GravityCompat
@ -19,7 +18,7 @@ import eu.kanade.tachiyomi.ui.base.controller.NoToolbarElevationController
import eu.kanade.tachiyomi.ui.base.controller.SecondaryDrawerController import eu.kanade.tachiyomi.ui.base.controller.SecondaryDrawerController
import eu.kanade.tachiyomi.ui.base.controller.TabbedController import eu.kanade.tachiyomi.ui.base.controller.TabbedController
import eu.kanade.tachiyomi.ui.catalogue.CatalogueController import eu.kanade.tachiyomi.ui.catalogue.CatalogueController
import eu.kanade.tachiyomi.ui.download.DownloadActivity import eu.kanade.tachiyomi.ui.download.DownloadController
import eu.kanade.tachiyomi.ui.latest_updates.LatestUpdatesController import eu.kanade.tachiyomi.ui.latest_updates.LatestUpdatesController
import eu.kanade.tachiyomi.ui.library.LibraryController import eu.kanade.tachiyomi.ui.library.LibraryController
import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.ui.manga.MangaController
@ -85,7 +84,9 @@ class MainActivity : BaseActivity() {
R.id.nav_drawer_catalogues -> setRoot(CatalogueController(), id) R.id.nav_drawer_catalogues -> setRoot(CatalogueController(), id)
R.id.nav_drawer_latest_updates -> setRoot(LatestUpdatesController(), id) R.id.nav_drawer_latest_updates -> setRoot(LatestUpdatesController(), id)
R.id.nav_drawer_downloads -> { R.id.nav_drawer_downloads -> {
startActivity(Intent(this, DownloadActivity::class.java)) router.pushController(RouterTransaction.with(DownloadController())
.pushChangeHandler(FadeChangeHandler())
.popChangeHandler(FadeChangeHandler()))
} }
R.id.nav_drawer_settings -> R.id.nav_drawer_settings ->
router.pushController(RouterTransaction.with(SettingsMainController()) router.pushController(RouterTransaction.with(SettingsMainController())
@ -109,6 +110,7 @@ class MainActivity : BaseActivity() {
SHORTCUT_CATALOGUES -> setSelectedDrawerItem(R.id.nav_drawer_catalogues) SHORTCUT_CATALOGUES -> setSelectedDrawerItem(R.id.nav_drawer_catalogues)
SHORTCUT_MANGA -> router.setRoot( SHORTCUT_MANGA -> router.setRoot(
RouterTransaction.with(MangaController(intent.extras))) RouterTransaction.with(MangaController(intent.extras)))
SHORTCUT_DOWNLOADS -> setSelectedDrawerItem(R.id.nav_drawer_downloads)
else -> setSelectedDrawerItem(startScreenId) else -> setSelectedDrawerItem(startScreenId)
} }
} }
@ -225,6 +227,7 @@ class MainActivity : BaseActivity() {
private const val SHORTCUT_RECENTLY_UPDATED = "eu.kanade.tachiyomi.SHOW_RECENTLY_UPDATED" private const val SHORTCUT_RECENTLY_UPDATED = "eu.kanade.tachiyomi.SHOW_RECENTLY_UPDATED"
private const val SHORTCUT_RECENTLY_READ = "eu.kanade.tachiyomi.SHOW_RECENTLY_READ" private const val SHORTCUT_RECENTLY_READ = "eu.kanade.tachiyomi.SHOW_RECENTLY_READ"
private const val SHORTCUT_CATALOGUES = "eu.kanade.tachiyomi.SHOW_CATALOGUES" private const val SHORTCUT_CATALOGUES = "eu.kanade.tachiyomi.SHOW_CATALOGUES"
const val SHORTCUT_DOWNLOADS = "eu.kanade.tachiyomi.SHOW_DOWNLOADS"
const val SHORTCUT_MANGA = "eu.kanade.tachiyomi.SHOW_MANGA" const val SHORTCUT_MANGA = "eu.kanade.tachiyomi.SHOW_MANGA"
} }

View File

@ -1,42 +1,22 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout
android:layout_width="match_parent" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:fitsSystemWindows="true"> android:id="@+id/frame_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout <android.support.v7.widget.RecyclerView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:orientation="vertical"> android:id="@+id/recycler"
tools:listitem="@layout/item_download"/>
<android.support.design.widget.AppBarLayout <eu.kanade.tachiyomi.widget.EmptyView
android:id="@+id/appbar" android:id="@+id/empty_view"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone"/>
<include layout="@layout/toolbar"/> </FrameLayout>
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="@+id/frame_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/recycler"
tools:listitem="@layout/item_download"/>
<eu.kanade.tachiyomi.widget.EmptyView
android:id="@+id/empty_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone"/>
</FrameLayout>
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>