Compare commits

...
Sign in to create a new pull request.

4 commits

Author SHA1 Message Date
h4h13
b52d5936e8 WIP 2020-04-19 02:18:34 +05:30
Eugeniu Olog
23c882bdb7 removed previous bottomnavigation translation 2020-04-17 21:18:50 +02:00
Eugeniu Olog
5d34055fd0 added scroll helper to main activity 2020-04-17 21:01:35 +02:00
Eugeniu Olog
967c6fb5ac fixed statusbar implementation:
`r.getIdentifier("status_bar_height", "dimen", "android")` was returning
always about 24 dp, with notch not being considered. A best approach is to
use WindowInset API
2020-04-17 18:34:05 +02:00
27 changed files with 386 additions and 498 deletions

View file

@ -176,6 +176,8 @@ dependencies {
implementation 'com.github.AdrienPoupa:jaudiotagger:2.2.3' implementation 'com.github.AdrienPoupa:jaudiotagger:2.2.3'
implementation 'com.github.ologe:scroll-helper:2.0.0-beta01'
implementation 'com.anjlab.android.iab.v3:library:1.1.0' implementation 'com.anjlab.android.iab.v3:library:1.1.0'
implementation 'com.r0adkll:slidableactivity:2.1.0' implementation 'com.r0adkll:slidableactivity:2.1.0'
implementation 'com.heinrichreimersoftware:material-intro:1.6' implementation 'com.heinrichreimersoftware:material-intro:1.6'

View file

@ -0,0 +1,67 @@
package code.name.monkey.retromusic
import android.view.View
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import code.name.monkey.retromusic.fragments.player.normal.PlayerFragment
import dev.olog.scrollhelper.ScrollHelper
class RetroScrollHelper(
private val activity: FragmentActivity
) : ScrollHelper(activity,
true,
false // TODO when true, scrolls both bottomsheet and bottom navigation
) {
private val skipFragment = listOf(
PlayerFragment::class.java.name
)
// TODO every fragment has to have it's unique tag in order to work correctly
// here you can decide what fragment will be processed by the library
// probably you want to skip player fragments, ecc ..
override fun shouldSkipFragment(fragment: Fragment): Boolean {
return fragment::class.java.name in skipFragment
}
override fun findBottomNavigation(): View? {
return activity.findViewById(R.id.bottomNavigationView)
}
override fun findBottomSheet(): View? {
return activity.findViewById(R.id.slidingPanel)
}
override fun findFab(fragment: Fragment): View? {
return null
}
override fun findRecyclerView(fragment: Fragment): RecyclerView? {
return fragment.requireView().findViewById(R.id.recyclerView)
}
override fun findToolbar(fragment: Fragment): View? {
return fragment.requireActivity().findViewById(R.id.toolbarContainer)
}
override fun findTabLayout(fragment: Fragment): View? {
return null
}
override fun findViewPager(fragment: Fragment): ViewPager2? {
return null
}
// TODO override this if you want to apply custom padding
override fun updateRecyclerViewPadding(
fragment: Fragment,
recyclerView: RecyclerView,
topPadding: Int,
bottomPadding: Int
) {
super.updateRecyclerViewPadding(fragment, recyclerView, topPadding, bottomPadding)
}
}

View file

@ -55,6 +55,7 @@ import java.util.List;
import code.name.monkey.appthemehelper.util.ATHUtil; import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper; import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
import code.name.monkey.retromusic.R; import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.RetroScrollHelper;
import code.name.monkey.retromusic.activities.base.AbsSlidingMusicPanelActivity; import code.name.monkey.retromusic.activities.base.AbsSlidingMusicPanelActivity;
import code.name.monkey.retromusic.dialogs.CreatePlaylistDialog; import code.name.monkey.retromusic.dialogs.CreatePlaylistDialog;
import code.name.monkey.retromusic.fragments.base.AbsLibraryPagerRecyclerViewCustomGridSizeFragment; import code.name.monkey.retromusic.fragments.base.AbsLibraryPagerRecyclerViewCustomGridSizeFragment;
@ -83,6 +84,7 @@ import code.name.monkey.retromusic.util.NavigationUtil;
import code.name.monkey.retromusic.util.PreferenceUtil; import code.name.monkey.retromusic.util.PreferenceUtil;
import code.name.monkey.retromusic.util.RetroColorUtil; import code.name.monkey.retromusic.util.RetroColorUtil;
import code.name.monkey.retromusic.util.RetroUtil; import code.name.monkey.retromusic.util.RetroUtil;
import dev.olog.scrollhelper.ScrollHelper;
/** /**
* Created by hemanths on 2020-02-19. * Created by hemanths on 2020-02-19.
@ -119,6 +121,9 @@ public class MainActivity extends AbsSlidingMusicPanelActivity
private Toolbar mToolbar; private Toolbar mToolbar;
private MaterialCardView mToolbarContainer; private MaterialCardView mToolbarContainer;
@SuppressWarnings("FieldCanBeLocal")
private ScrollHelper scrollHelper;
@Override @Override
protected void onCreate(@Nullable final Bundle savedInstanceState) { protected void onCreate(@Nullable final Bundle savedInstanceState) {
setDrawUnderStatusBar(); setDrawUnderStatusBar();
@ -151,6 +156,8 @@ public class MainActivity extends AbsSlidingMusicPanelActivity
checkShowChangelog(); checkShowChangelog();
AppRater.appLaunched(this); AppRater.appLaunched(this);
setupToolbar(); setupToolbar();
scrollHelper = new RetroScrollHelper(this);
} }
@Override @Override

View file

@ -111,10 +111,14 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(),
} }
} }
override fun onPause() {
super.onPause()
bottomSheetBehavior.removeBottomSheetCallback(bottomSheetCallbackList)
}
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
bottomSheetBehavior.removeBottomSheetCallback(bottomSheetCallbackList) navigationBarColorAnimator?.cancel() // just in case
if (navigationBarColorAnimator != null) navigationBarColorAnimator?.cancel() // just in case
} }
protected fun wrapSlidingMusicPanel(@LayoutRes resId: Int): View { protected fun wrapSlidingMusicPanel(@LayoutRes resId: Int): View {
@ -142,7 +146,6 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(),
// necessary to make the views below clickable // necessary to make the views below clickable
miniPlayerFragment?.view?.visibility = if (alpha == 0f) View.GONE else View.VISIBLE miniPlayerFragment?.view?.visibility = if (alpha == 0f) View.GONE else View.VISIBLE
bottomNavigationView.translationY = progress * 500
//bottomNavigationView.alpha = alpha //bottomNavigationView.alpha = alpha
} }
@ -217,8 +220,8 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(),
} }
} }
fun setBottomBarVisibility(gone: Int) { fun setBottomBarVisibility(visibility: Int) {
bottomNavigationView.visibility = gone bottomNavigationView.visibility = visibility
hideBottomBar(false) hideBottomBar(false)
} }

View file

@ -34,20 +34,36 @@ class HomeAdapter(
} }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val layout = LayoutInflater.from(activity) println("onCreateViewHolder: $viewType")
.inflate(R.layout.section_recycler_view, parent, false)
return when (viewType) { return when (viewType) {
RECENT_ARTISTS, TOP_ARTISTS -> ArtistViewHolder(layout) RECENT_ARTISTS, TOP_ARTISTS -> ArtistViewHolder(
PLAYLISTS -> PlaylistViewHolder(layout) LayoutInflater.from(activity).inflate(
else -> { R.layout.section_recycler_view,
AlbumViewHolder( parent,
LayoutInflater.from(activity).inflate( false
R.layout.metal_section_recycler_view,
parent,
false
)
) )
} )
PLAYLISTS -> PlaylistViewHolder(
LayoutInflater.from(activity).inflate(
R.layout.section_recycler_view,
parent,
false
)
)
/*TOP_ALBUMS, RECENT_ALBUMS -> AlbumViewHolder(
LayoutInflater.from(activity).inflate(
R.layout.metal_section_recycler_view,
parent,
false
)
)*/
else -> AlbumViewHolder(
LayoutInflater.from(activity).inflate(
R.layout.metal_section_recycler_view,
parent,
false
)
)
} }
} }
@ -63,13 +79,17 @@ class HomeAdapter(
} }
RECENT_ARTISTS -> { RECENT_ARTISTS -> {
val viewHolder = holder as ArtistViewHolder val viewHolder = holder as ArtistViewHolder
viewHolder.bindView(list[position].arrayList.toArtists(), R.string.recent_artists) viewHolder.bindView(
list[position].arrayList.toArtists(),
R.string.recent_artists
)
} }
TOP_ARTISTS -> { TOP_ARTISTS -> {
val viewHolder = holder as ArtistViewHolder val viewHolder = holder as ArtistViewHolder
viewHolder.bindView(list[position].arrayList.toArtists(), R.string.top_artists) viewHolder.bindView(list[position].arrayList.toArtists(), R.string.top_artists)
} }
PLAYLISTS -> { PLAYLISTS -> {
val viewHolder = holder as PlaylistViewHolder val viewHolder = holder as PlaylistViewHolder
viewHolder.bindView(list[position].arrayList.toPlaylist(), R.string.favorites) viewHolder.bindView(list[position].arrayList.toPlaylist(), R.string.favorites)
} }
@ -91,14 +111,18 @@ class HomeAdapter(
@Retention(AnnotationRetention.SOURCE) @Retention(AnnotationRetention.SOURCE)
annotation class HomeSection annotation class HomeSection
const val RECENT_ALBUMS = 3 const val RECENT_ALBUMS = 4
const val TOP_ALBUMS = 1 const val TOP_ALBUMS = 2
const val RECENT_ARTISTS = 2 const val RECENT_ARTISTS = 3
const val TOP_ARTISTS = 0 const val TOP_ARTISTS = 1
const val PLAYLISTS = 4 const val PLAYLISTS = 5
} }
private inner class AlbumViewHolder(view: View) : AbsHomeViewItem(view) { inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
}
inner class AlbumViewHolder(view: View) : AbsHomeViewItem(view) {
fun bindView(list: ArrayList<Album>, titleRes: Int) { fun bindView(list: ArrayList<Album>, titleRes: Int) {
if (list.isNotEmpty()) { if (list.isNotEmpty()) {
recyclerView.apply { recyclerView.apply {
@ -130,7 +154,7 @@ class HomeAdapter(
} }
} }
private inner class PlaylistViewHolder(view: View) : AbsHomeViewItem(view) { inner class PlaylistViewHolder(view: View) : AbsHomeViewItem(view) {
fun bindView(arrayList: ArrayList<Playlist>, titleRes: Int) { fun bindView(arrayList: ArrayList<Playlist>, titleRes: Int) {
if (arrayList.isNotEmpty()) { if (arrayList.isNotEmpty()) {
val songs = PlaylistSongsLoader.getPlaylistSongList(activity, arrayList[0]) val songs = PlaylistSongsLoader.getPlaylistSongList(activity, arrayList[0])

View file

@ -0,0 +1,34 @@
package code.name.monkey.retromusic.adapter
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import code.name.monkey.retromusic.R
class SmartPlaylistAdapter : RecyclerView.Adapter<SmartPlaylistAdapter.ViewHolder>() {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): ViewHolder {
return ViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.abs_playlists,
parent,
false
)
);
}
override fun getItemCount(): Int {
return 1
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
}
}

View file

@ -0,0 +1,10 @@
package code.name.monkey.retromusic.extensions
import android.content.Context
import androidx.annotation.DimenRes
@Suppress("NOTHING_TO_INLINE")
inline fun Context.dip(value: Int): Int = (value * resources.displayMetrics.density).toInt()
@Suppress("NOTHING_TO_INLINE")
inline fun Context.dimen(@DimenRes resource: Int): Int = resources.getDimensionPixelSize(resource)

View file

@ -8,17 +8,13 @@ import androidx.annotation.NonNull
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.util.DensityUtil
import code.name.monkey.retromusic.util.ThemedFastScroller.create import code.name.monkey.retromusic.util.ThemedFastScroller.create
import code.name.monkey.retromusic.views.ScrollingViewOnApplyWindowInsetsListener
import com.google.android.material.appbar.AppBarLayout
import kotlinx.android.synthetic.main.fragment_main_activity_recycler_view.* import kotlinx.android.synthetic.main.fragment_main_activity_recycler_view.*
import me.zhanghai.android.fastscroll.FastScroller import me.zhanghai.android.fastscroll.FastScroller
import me.zhanghai.android.fastscroll.FastScrollerBuilder import me.zhanghai.android.fastscroll.FastScrollerBuilder
abstract class AbsLibraryPagerRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : RecyclerView.LayoutManager> : abstract class AbsLibraryPagerRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : RecyclerView.LayoutManager> :
AbsLibraryPagerFragment(), AppBarLayout.OnOffsetChangedListener { AbsLibraryPagerFragment() {
protected var adapter: A? = null protected var adapter: A? = null
protected var layoutManager: LM? = null protected var layoutManager: LM? = null
@ -31,7 +27,6 @@ abstract class AbsLibraryPagerRecyclerViewFragment<A : RecyclerView.Adapter<*>,
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
mainActivity.addOnAppBarOffsetChangedListener(this)
initLayoutManager() initLayoutManager()
initAdapter() initAdapter()
setUpRecyclerView() setUpRecyclerView()
@ -41,13 +36,6 @@ abstract class AbsLibraryPagerRecyclerViewFragment<A : RecyclerView.Adapter<*>,
recyclerView.layoutManager = layoutManager recyclerView.layoutManager = layoutManager
recyclerView.adapter = adapter recyclerView.adapter = adapter
val fastScroller = create(recyclerView) val fastScroller = create(recyclerView)
recyclerView.setOnApplyWindowInsetsListener(
ScrollingViewOnApplyWindowInsetsListener(
recyclerView,
fastScroller
)
)
checkForPadding()
} }
protected open fun createFastScroller(recyclerView: RecyclerView): FastScroller { protected open fun createFastScroller(recyclerView: RecyclerView): FastScroller {
@ -60,7 +48,6 @@ abstract class AbsLibraryPagerRecyclerViewFragment<A : RecyclerView.Adapter<*>,
override fun onChanged() { override fun onChanged() {
super.onChanged() super.onChanged()
checkIsEmpty() checkIsEmpty()
checkForPadding()
} }
}) })
} }
@ -78,18 +65,6 @@ abstract class AbsLibraryPagerRecyclerViewFragment<A : RecyclerView.Adapter<*>,
empty.visibility = if (adapter!!.itemCount == 0) View.VISIBLE else View.GONE empty.visibility = if (adapter!!.itemCount == 0) View.VISIBLE else View.GONE
} }
private fun checkForPadding() {
val itemCount: Int = adapter?.itemCount ?: 0
val params = container.layoutParams as ViewGroup.MarginLayoutParams
if (itemCount > 0 && MusicPlayerRemote.playingQueue.isNotEmpty()) {
val height = DensityUtil.dip2px(requireContext(), 104f)
params.bottomMargin = height
} else {
val height = DensityUtil.dip2px(requireContext(), 52f)
params.bottomMargin = height
}
}
private fun initLayoutManager() { private fun initLayoutManager() {
layoutManager = createLayoutManager() layoutManager = createLayoutManager()
} }
@ -99,25 +74,6 @@ abstract class AbsLibraryPagerRecyclerViewFragment<A : RecyclerView.Adapter<*>,
@NonNull @NonNull
protected abstract fun createAdapter(): A protected abstract fun createAdapter(): A
override fun onOffsetChanged(p0: AppBarLayout?, i: Int) {
container.setPadding(
container.paddingLeft,
container.paddingTop,
container.paddingRight,
mainActivity.totalAppBarScrollingRange + i
)
}
override fun onQueueChanged() {
super.onQueueChanged()
checkForPadding()
}
override fun onServiceConnected() {
super.onServiceConnected()
checkForPadding()
}
protected fun invalidateLayoutManager() { protected fun invalidateLayoutManager() {
initLayoutManager() initLayoutManager()
recyclerView.layoutManager = layoutManager recyclerView.layoutManager = layoutManager
@ -129,11 +85,6 @@ abstract class AbsLibraryPagerRecyclerViewFragment<A : RecyclerView.Adapter<*>,
recyclerView.adapter = adapter recyclerView.adapter = adapter
} }
override fun onDestroyView() {
super.onDestroyView()
mainActivity.removeOnAppBarOffsetChangedListener(this)
}
fun recyclerView(): RecyclerView { fun recyclerView(): RecyclerView {
return recyclerView return recyclerView
} }

View file

@ -12,6 +12,7 @@ import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.mvp.presenter.AlbumsPresenter import code.name.monkey.retromusic.mvp.presenter.AlbumsPresenter
import code.name.monkey.retromusic.mvp.presenter.AlbumsView import code.name.monkey.retromusic.mvp.presenter.AlbumsView
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import dev.olog.scrollhelper.layoutmanagers.OverScrollGridLayoutManager
import javax.inject.Inject import javax.inject.Inject
class AlbumsFragment : class AlbumsFragment :
@ -51,7 +52,7 @@ class AlbumsFragment :
get() = R.string.no_albums get() = R.string.no_albums
override fun createLayoutManager(): GridLayoutManager { override fun createLayoutManager(): GridLayoutManager {
return GridLayoutManager(requireActivity(), getGridSize()) return OverScrollGridLayoutManager(requireActivity(), getGridSize())
} }
override fun createAdapter(): AlbumAdapter { override fun createAdapter(): AlbumAdapter {

View file

@ -12,6 +12,7 @@ import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.mvp.presenter.ArtistsPresenter import code.name.monkey.retromusic.mvp.presenter.ArtistsPresenter
import code.name.monkey.retromusic.mvp.presenter.ArtistsView import code.name.monkey.retromusic.mvp.presenter.ArtistsView
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import dev.olog.scrollhelper.layoutmanagers.OverScrollGridLayoutManager
import javax.inject.Inject import javax.inject.Inject
class ArtistsFragment : class ArtistsFragment :
@ -63,7 +64,7 @@ class ArtistsFragment :
} }
override fun createLayoutManager(): GridLayoutManager { override fun createLayoutManager(): GridLayoutManager {
return GridLayoutManager(requireActivity(), getGridSize()) return OverScrollGridLayoutManager(requireActivity(), getGridSize())
} }
override fun createAdapter(): ArtistAdapter { override fun createAdapter(): ArtistAdapter {

View file

@ -14,38 +14,24 @@
package code.name.monkey.retromusic.fragments.mainactivity package code.name.monkey.retromusic.fragments.mainactivity
import android.app.ActivityOptions
import android.os.Bundle import android.os.Bundle
import android.util.DisplayMetrics import android.util.DisplayMetrics
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.MergeAdapter
import code.name.monkey.retromusic.App import code.name.monkey.retromusic.App
import code.name.monkey.retromusic.Constants
import code.name.monkey.retromusic.Constants.USER_BANNER
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.HomeAdapter import code.name.monkey.retromusic.adapter.HomeAdapter
import code.name.monkey.retromusic.adapter.SmartPlaylistAdapter
import code.name.monkey.retromusic.extensions.show import code.name.monkey.retromusic.extensions.show
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.interfaces.MainActivityFragmentCallbacks import code.name.monkey.retromusic.interfaces.MainActivityFragmentCallbacks
import code.name.monkey.retromusic.loaders.SongLoader
import code.name.monkey.retromusic.model.Home import code.name.monkey.retromusic.model.Home
import code.name.monkey.retromusic.model.smartplaylist.HistoryPlaylist
import code.name.monkey.retromusic.model.smartplaylist.LastAddedPlaylist
import code.name.monkey.retromusic.model.smartplaylist.MyTopTracksPlaylist
import code.name.monkey.retromusic.mvp.presenter.HomePresenter import code.name.monkey.retromusic.mvp.presenter.HomePresenter
import code.name.monkey.retromusic.mvp.presenter.HomeView import code.name.monkey.retromusic.mvp.presenter.HomeView
import code.name.monkey.retromusic.util.NavigationUtil import dev.olog.scrollhelper.layoutmanagers.OverScrollLinearLayoutManager
import code.name.monkey.retromusic.util.PreferenceUtil
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import kotlinx.android.synthetic.main.abs_playlists.*
import kotlinx.android.synthetic.main.fragment_banner_home.*
import kotlinx.android.synthetic.main.home_content.* import kotlinx.android.synthetic.main.home_content.*
import java.io.File
import java.util.*
import javax.inject.Inject import javax.inject.Inject
class BannerHomeFragment : AbsMainActivityFragment(), MainActivityFragmentCallbacks, HomeView { class BannerHomeFragment : AbsMainActivityFragment(), MainActivityFragmentCallbacks, HomeView {
@ -64,27 +50,12 @@ class BannerHomeFragment : AbsMainActivityFragment(), MainActivityFragmentCallba
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
return inflater.inflate( return inflater.inflate(
if (PreferenceUtil.getInstance(requireContext()).isHomeBanner) R.layout.fragment_banner_home else R.layout.fragment_home, R.layout.fragment_home,
viewGroup, viewGroup,
false false
) )
} }
private fun loadImageFromStorage() {
Glide.with(requireContext())
.load(
File(
PreferenceUtil.getInstance(requireContext()).profileImage,
Constants.USER_PROFILE
)
)
.asBitmap()
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.placeholder(R.drawable.ic_person_flat)
.error(R.drawable.ic_person_flat)
.into(userImage)
}
private val displayMetrics: DisplayMetrics private val displayMetrics: DisplayMetrics
get() { get() {
@ -98,51 +69,13 @@ class BannerHomeFragment : AbsMainActivityFragment(), MainActivityFragmentCallba
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
setStatusBarColorAuto(view) setStatusBarColorAuto(view)
bannerImage?.setOnClickListener {
val options = ActivityOptions.makeSceneTransitionAnimation(
mainActivity,
userImage,
getString(R.string.transition_user_image)
)
NavigationUtil.goToUserInfo(requireActivity(), options)
}
lastAdded.setOnClickListener {
NavigationUtil.goToPlaylistNew(requireActivity(), LastAddedPlaylist(requireActivity()))
}
topPlayed.setOnClickListener {
NavigationUtil.goToPlaylistNew(
requireActivity(),
MyTopTracksPlaylist(requireActivity())
)
}
actionShuffle.setOnClickListener {
MusicPlayerRemote.openAndShuffleQueue(SongLoader.getAllSongs(requireActivity()), true)
}
history.setOnClickListener {
NavigationUtil.goToPlaylistNew(requireActivity(), HistoryPlaylist(requireActivity()))
}
userImage?.setOnClickListener {
val options = ActivityOptions.makeSceneTransitionAnimation(
mainActivity,
userImage,
getString(R.string.transition_user_image)
)
NavigationUtil.goToUserInfo(requireActivity(), options)
}
titleWelcome?.text =
String.format("%s", PreferenceUtil.getInstance(requireContext()).userName)
App.musicComponent.inject(this) App.musicComponent.inject(this)
homeAdapter = HomeAdapter(mainActivity, displayMetrics) homeAdapter = HomeAdapter(mainActivity, displayMetrics)
val smartPlaylistAdapter: SmartPlaylistAdapter = SmartPlaylistAdapter()
recyclerView.apply { recyclerView.apply {
layoutManager = LinearLayoutManager(mainActivity) layoutManager = OverScrollLinearLayoutManager(mainActivity)
adapter = homeAdapter adapter = MergeAdapter(smartPlaylistAdapter, homeAdapter)
} }
homePresenter.attachView(this) homePresenter.attachView(this)
homePresenter.loadSections() homePresenter.loadSections()
@ -152,11 +85,6 @@ class BannerHomeFragment : AbsMainActivityFragment(), MainActivityFragmentCallba
return false return false
} }
override fun onResume() {
super.onResume()
getTimeOfTheDay()
}
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
homePresenter.detachView() homePresenter.detachView()
@ -166,49 +94,6 @@ class BannerHomeFragment : AbsMainActivityFragment(), MainActivityFragmentCallba
emptyContainer.show() emptyContainer.show()
} }
private fun getTimeOfTheDay() {
val c = Calendar.getInstance()
val timeOfDay = c.get(Calendar.HOUR_OF_DAY)
var images = arrayOf<String>()
when (timeOfDay) {
in 0..5 -> images = resources.getStringArray(R.array.night)
in 6..11 -> images = resources.getStringArray(R.array.morning)
in 12..15 -> images = resources.getStringArray(R.array.after_noon)
in 16..19 -> images = resources.getStringArray(R.array.evening)
in 20..23 -> images = resources.getStringArray(R.array.night)
}
val day = images[Random().nextInt(images.size)]
loadTimeImage(day)
}
private fun loadTimeImage(day: String) {
bannerImage?.let {
val request = Glide.with(requireContext())
if (PreferenceUtil.getInstance(requireContext()).bannerImage.isEmpty()) {
request.load(day)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.placeholder(R.drawable.material_design_default)
.error(R.drawable.material_design_default)
.into(it)
} else {
request.load(
File(
PreferenceUtil.getInstance(requireContext()).bannerImage,
USER_BANNER
)
)
.asBitmap()
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.placeholder(R.drawable.material_design_default)
.error(R.drawable.material_design_default)
.into(it)
}
}
loadImageFromStorage()
}
companion object { companion object {
const val TAG: String = "BannerHomeFragment" const val TAG: String = "BannerHomeFragment"

View file

@ -24,7 +24,6 @@ import android.view.LayoutInflater;
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.ViewGroup.MarginLayoutParams;
import android.webkit.MimeTypeMap; import android.webkit.MimeTypeMap;
import android.widget.PopupMenu; import android.widget.PopupMenu;
import android.widget.TextView; import android.widget.TextView;
@ -34,7 +33,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.loader.app.LoaderManager; import androidx.loader.app.LoaderManager;
import androidx.loader.content.Loader; import androidx.loader.content.Loader;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.afollestad.materialcab.MaterialCab; import com.afollestad.materialcab.MaterialCab;
@ -50,7 +48,6 @@ import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Objects;
import code.name.monkey.appthemehelper.ThemeStore; import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.util.ATHUtil; import code.name.monkey.appthemehelper.util.ATHUtil;
@ -67,19 +64,16 @@ import code.name.monkey.retromusic.misc.DialogAsyncTask;
import code.name.monkey.retromusic.misc.UpdateToastMediaScannerCompletionListener; import code.name.monkey.retromusic.misc.UpdateToastMediaScannerCompletionListener;
import code.name.monkey.retromusic.misc.WrappedAsyncTaskLoader; import code.name.monkey.retromusic.misc.WrappedAsyncTaskLoader;
import code.name.monkey.retromusic.model.Song; import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.util.DensityUtil;
import code.name.monkey.retromusic.util.FileUtil; import code.name.monkey.retromusic.util.FileUtil;
import code.name.monkey.retromusic.util.PreferenceUtil; import code.name.monkey.retromusic.util.PreferenceUtil;
import code.name.monkey.retromusic.util.RetroColorUtil; import code.name.monkey.retromusic.util.RetroColorUtil;
import code.name.monkey.retromusic.util.ThemedFastScroller; import code.name.monkey.retromusic.util.ThemedFastScroller;
import code.name.monkey.retromusic.views.BreadCrumbLayout;
import code.name.monkey.retromusic.views.ScrollingViewOnApplyWindowInsetsListener; import code.name.monkey.retromusic.views.ScrollingViewOnApplyWindowInsetsListener;
import dev.olog.scrollhelper.layoutmanagers.OverScrollLinearLayoutManager;
import me.zhanghai.android.fastscroll.FastScroller; import me.zhanghai.android.fastscroll.FastScroller;
public class FoldersFragment extends AbsMainActivityFragment implements public class FoldersFragment extends AbsMainActivityFragment implements
MainActivityFragmentCallbacks, MainActivityFragmentCallbacks, CabHolder, SongFileAdapter.Callbacks, LoaderManager.LoaderCallbacks<List<File>> {
CabHolder, BreadCrumbLayout.SelectionCallback, SongFileAdapter.Callbacks,
LoaderManager.LoaderCallbacks<List<File>> {
public static final String TAG = FoldersFragment.class.getSimpleName(); public static final String TAG = FoldersFragment.class.getSimpleName();
public static final FileFilter AUDIO_FILE_FILTER = file -> !file.isHidden() && (file.isDirectory() || public static final FileFilter AUDIO_FILE_FILTER = file -> !file.isHidden() && (file.isDirectory() ||
@ -87,11 +81,11 @@ public class FoldersFragment extends AbsMainActivityFragment implements
FileUtil.fileIsMimeType(file, "application/opus", MimeTypeMap.getSingleton()) || FileUtil.fileIsMimeType(file, "application/opus", MimeTypeMap.getSingleton()) ||
FileUtil.fileIsMimeType(file, "application/ogg", MimeTypeMap.getSingleton())); FileUtil.fileIsMimeType(file, "application/ogg", MimeTypeMap.getSingleton()));
private static final String PATH = "path"; private static final String PATH = "path";
private static final String CRUMBS = "crumbs";
private static final int LOADER_ID = LoaderIds.Companion.getFOLDERS_FRAGMENT(); private static final int LOADER_ID = LoaderIds.Companion.getFOLDERS_FRAGMENT();
private SongFileAdapter adapter; private SongFileAdapter adapter;
private BreadCrumbLayout breadCrumbs;
private MaterialCab cab; private MaterialCab cab;
private File file;
private View coordinatorLayout, empty; private View coordinatorLayout, empty;
private TextView emojiText; private TextView emojiText;
private Comparator<File> fileComparator = (lhs, rhs) -> { private Comparator<File> fileComparator = (lhs, rhs) -> {
@ -110,7 +104,7 @@ public class FoldersFragment extends AbsMainActivityFragment implements
} }
public static File getDefaultStartDirectory() { public static File getDefaultStartDirectory() {
File musicDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC); File musicDir = Environment.getExternalStorageDirectory();
File startFolder; File startFolder;
if (musicDir.exists() && musicDir.isDirectory()) { if (musicDir.exists() && musicDir.isDirectory()) {
startFolder = musicDir; startFolder = musicDir;
@ -159,8 +153,6 @@ public class FoldersFragment extends AbsMainActivityFragment implements
@Override @Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
setStatusBarColorAuto(view); setStatusBarColorAuto(view);
setUpAppbarColor();
setUpBreadCrumbs();
setUpRecyclerView(); setUpRecyclerView();
setUpAdapter(); setUpAdapter();
} }
@ -171,39 +163,19 @@ public class FoldersFragment extends AbsMainActivityFragment implements
if (savedInstanceState == null) { if (savedInstanceState == null) {
//noinspection ConstantConditions //noinspection ConstantConditions
setCrumb(new BreadCrumbLayout.Crumb( setCrumb(FileUtil.safeGetCanonicalFile((File) getArguments().getSerializable(PATH)));
FileUtil.safeGetCanonicalFile((File) getArguments().getSerializable(PATH))), true);
} else { } else {
breadCrumbs.restoreFromStateWrapper(savedInstanceState.getParcelable(CRUMBS));
getLoaderManager().initLoader(LOADER_ID, null, this); getLoaderManager().initLoader(LOADER_ID, null, this);
} }
} }
@Override
public void onPause() {
super.onPause();
saveScrollPosition();
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
if (breadCrumbs != null) {
outState.putParcelable(CRUMBS, breadCrumbs.getStateWrapper());
}
}
@Override @Override
public boolean handleBackPress() { public boolean handleBackPress() {
if (cab != null && cab.isActive()) { if (cab != null && cab.isActive()) {
cab.finish(); cab.finish();
return true; return true;
} }
if (breadCrumbs != null && breadCrumbs.popHistory()) {
setCrumb(breadCrumbs.lastHistory(), false);
return true;
}
return false; return false;
} }
@ -213,10 +185,6 @@ public class FoldersFragment extends AbsMainActivityFragment implements
return new AsyncFileLoader(this); return new AsyncFileLoader(this);
} }
@Override
public void onCrumbSelection(BreadCrumbLayout.Crumb crumb, int index) {
setCrumb(crumb, true);
}
@Override @Override
public void onFileMenuClicked(final File file, View view) { public void onFileMenuClicked(final File file, View view) {
@ -286,7 +254,7 @@ public class FoldersFragment extends AbsMainActivityFragment implements
public void onFileSelected(File file) { public void onFileSelected(File file) {
file = tryGetCanonicalFile(file); // important as we compare the path value later file = tryGetCanonicalFile(file); // important as we compare the path value later
if (file.isDirectory()) { if (file.isDirectory()) {
setCrumb(new BreadCrumbLayout.Crumb(file), true); setCrumb(file);
} else { } else {
FileFilter fileFilter = pathname -> !pathname.isDirectory() && AUDIO_FILE_FILTER FileFilter fileFilter = pathname -> !pathname.isDirectory() && AUDIO_FILE_FILTER
.accept(pathname); .accept(pathname);
@ -340,34 +308,21 @@ public class FoldersFragment extends AbsMainActivityFragment implements
public boolean onOptionsItemSelected(@NonNull MenuItem item) { public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.action_go_to_start_directory: case R.id.action_go_to_start_directory:
setCrumb(new BreadCrumbLayout.Crumb( setCrumb(tryGetCanonicalFile(PreferenceUtil.getInstance(requireContext()).getStartDirectory()));
tryGetCanonicalFile(PreferenceUtil.getInstance(requireContext()).getStartDirectory())), true);
return true; return true;
case R.id.action_scan: case R.id.action_scan:
BreadCrumbLayout.Crumb crumb = getActiveCrumb();
if (crumb != null) { /* if (crumb != null) {
//noinspection Convert2MethodRef //noinspection Convert2MethodRef
new ListPathsAsyncTask(getActivity(), paths -> scanPaths(paths)) new ListPathsAsyncTask(getActivity(), paths -> scanPaths(paths))
.execute(new ListPathsAsyncTask.LoadingInfo(crumb.getFile(), .execute(new ListPathsAsyncTask.LoadingInfo(crumb.getFile(),
AUDIO_FILE_FILTER)); AUDIO_FILE_FILTER));
} }*/
return true; return true;
} }
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
@Override
public void onQueueChanged() {
super.onQueueChanged();
checkForPadding();
}
@Override
public void onServiceConnected() {
super.onServiceConnected();
checkForPadding();
}
@NonNull @NonNull
@Override @Override
public MaterialCab openCab(int menuRes, MaterialCab.Callback callback) { public MaterialCab openCab(int menuRes, MaterialCab.Callback callback) {
@ -383,12 +338,6 @@ public class FoldersFragment extends AbsMainActivityFragment implements
return cab; return cab;
} }
private void checkForPadding() {
final int count = adapter.getItemCount();
final MarginLayoutParams params = (MarginLayoutParams) coordinatorLayout.getLayoutParams();
params.bottomMargin = count > 0 && !MusicPlayerRemote.getPlayingQueue().isEmpty() ? DensityUtil
.dip2px(requireContext(), 104f) : DensityUtil.dip2px(requireContext(), 54f);
}
private void checkIsEmpty() { private void checkIsEmpty() {
emojiText.setText(getEmojiByUnicode(0x1F631)); emojiText.setText(getEmojiByUnicode(0x1F631));
@ -397,11 +346,6 @@ public class FoldersFragment extends AbsMainActivityFragment implements
} }
} }
@Nullable
private BreadCrumbLayout.Crumb getActiveCrumb() {
return breadCrumbs != null && breadCrumbs.size() > 0 ? breadCrumbs
.getCrumb(breadCrumbs.getActiveIndex()) : null;
}
private String getEmojiByUnicode(int unicode) { private String getEmojiByUnicode(int unicode) {
return new String(Character.toChars(unicode)); return new String(Character.toChars(unicode));
@ -414,18 +358,11 @@ public class FoldersFragment extends AbsMainActivityFragment implements
private void initViews(View view) { private void initViews(View view) {
coordinatorLayout = view.findViewById(R.id.coordinatorLayout); coordinatorLayout = view.findViewById(R.id.coordinatorLayout);
recyclerView = view.findViewById(R.id.recyclerView); recyclerView = view.findViewById(R.id.recyclerView);
breadCrumbs = view.findViewById(R.id.breadCrumbs);
empty = view.findViewById(android.R.id.empty); empty = view.findViewById(android.R.id.empty);
emojiText = view.findViewById(R.id.emptyEmoji); emojiText = view.findViewById(R.id.emptyEmoji);
} }
private void saveScrollPosition() {
BreadCrumbLayout.Crumb crumb = getActiveCrumb();
if (crumb != null) {
crumb.setScrollPosition(
((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition());
}
}
private void scanPaths(@Nullable String[] toBeScanned) { private void scanPaths(@Nullable String[] toBeScanned) {
if (getActivity() == null) { if (getActivity() == null) {
@ -439,15 +376,12 @@ public class FoldersFragment extends AbsMainActivityFragment implements
} }
} }
private void setCrumb(BreadCrumbLayout.Crumb crumb, boolean addToHistory) { public File getFile() {
if (crumb == null) { return file;
return; }
}
saveScrollPosition(); private void setCrumb(File file) {
breadCrumbs.setActiveOrAdd(crumb, false); this.file = file;
if (addToHistory) {
breadCrumbs.addHistory(crumb);
}
getLoaderManager().restartLoader(LOADER_ID, null, this); getLoaderManager().restartLoader(LOADER_ID, null, this);
} }
@ -459,26 +393,15 @@ public class FoldersFragment extends AbsMainActivityFragment implements
public void onChanged() { public void onChanged() {
super.onChanged(); super.onChanged();
checkIsEmpty(); checkIsEmpty();
checkForPadding();
} }
}); });
recyclerView.setAdapter(adapter); recyclerView.setAdapter(adapter);
checkIsEmpty(); checkIsEmpty();
} }
private void setUpAppbarColor() {
breadCrumbs.setActivatedContentColor(
ATHUtil.INSTANCE.resolveColor(requireContext(), android.R.attr.textColorPrimary));
breadCrumbs.setDeactivatedContentColor(
ATHUtil.INSTANCE.resolveColor(requireContext(), android.R.attr.textColorSecondary));
}
private void setUpBreadCrumbs() {
breadCrumbs.setCallback(this);
}
private void setUpRecyclerView() { private void setUpRecyclerView() {
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); recyclerView.setLayoutManager(new OverScrollLinearLayoutManager(getActivity()));
FastScroller fastScroller = ThemedFastScroller.INSTANCE.create(recyclerView); FastScroller fastScroller = ThemedFastScroller.INSTANCE.create(recyclerView);
recyclerView.setOnApplyWindowInsetsListener( recyclerView.setOnApplyWindowInsetsListener(
new ScrollingViewOnApplyWindowInsetsListener(recyclerView, fastScroller)); new ScrollingViewOnApplyWindowInsetsListener(recyclerView, fastScroller));
@ -492,11 +415,7 @@ public class FoldersFragment extends AbsMainActivityFragment implements
private void updateAdapter(@NonNull List<File> files) { private void updateAdapter(@NonNull List<File> files) {
adapter.swapDataSet(files); adapter.swapDataSet(files);
BreadCrumbLayout.Crumb crumb = getActiveCrumb();
if (crumb != null && recyclerView != null) {
((LinearLayoutManager) recyclerView.getLayoutManager())
.scrollToPositionWithOffset(crumb.getScrollPosition(), 0);
}
} }
public static class ListPathsAsyncTask extends public static class ListPathsAsyncTask extends
@ -595,7 +514,7 @@ public class FoldersFragment extends AbsMainActivityFragment implements
private WeakReference<FoldersFragment> fragmentWeakReference; private WeakReference<FoldersFragment> fragmentWeakReference;
AsyncFileLoader(FoldersFragment foldersFragment) { AsyncFileLoader(FoldersFragment foldersFragment) {
super(Objects.requireNonNull(foldersFragment.getActivity())); super(foldersFragment.requireActivity());
fragmentWeakReference = new WeakReference<>(foldersFragment); fragmentWeakReference = new WeakReference<>(foldersFragment);
} }
@ -604,10 +523,7 @@ public class FoldersFragment extends AbsMainActivityFragment implements
FoldersFragment foldersFragment = fragmentWeakReference.get(); FoldersFragment foldersFragment = fragmentWeakReference.get();
File directory = null; File directory = null;
if (foldersFragment != null) { if (foldersFragment != null) {
BreadCrumbLayout.Crumb crumb = foldersFragment.getActiveCrumb(); directory = foldersFragment.getFile();
if (crumb != null) {
directory = crumb.getFile();
}
} }
if (directory != null) { if (directory != null) {
List<File> files = FileUtil.listFiles(directory, AUDIO_FILE_FILTER); List<File> files = FileUtil.listFiles(directory, AUDIO_FILE_FILTER);

View file

@ -25,6 +25,7 @@ import code.name.monkey.retromusic.interfaces.MainActivityFragmentCallbacks
import code.name.monkey.retromusic.model.Genre import code.name.monkey.retromusic.model.Genre
import code.name.monkey.retromusic.mvp.presenter.GenresPresenter import code.name.monkey.retromusic.mvp.presenter.GenresPresenter
import code.name.monkey.retromusic.mvp.presenter.GenresView import code.name.monkey.retromusic.mvp.presenter.GenresView
import dev.olog.scrollhelper.layoutmanagers.OverScrollLinearLayoutManager
import javax.inject.Inject import javax.inject.Inject
class GenresFragment : AbsLibraryPagerRecyclerViewFragment<GenreAdapter, LinearLayoutManager>(), class GenresFragment : AbsLibraryPagerRecyclerViewFragment<GenreAdapter, LinearLayoutManager>(),
@ -42,7 +43,7 @@ class GenresFragment : AbsLibraryPagerRecyclerViewFragment<GenreAdapter, LinearL
} }
override fun createLayoutManager(): LinearLayoutManager { override fun createLayoutManager(): LinearLayoutManager {
return LinearLayoutManager(activity) return OverScrollLinearLayoutManager(activity)
} }
override fun createAdapter(): GenreAdapter { override fun createAdapter(): GenreAdapter {

View file

@ -28,6 +28,7 @@ import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropM
import com.h6ah4i.android.widget.advrecyclerview.swipeable.RecyclerViewSwipeManager import com.h6ah4i.android.widget.advrecyclerview.swipeable.RecyclerViewSwipeManager
import com.h6ah4i.android.widget.advrecyclerview.touchguard.RecyclerViewTouchActionGuardManager import com.h6ah4i.android.widget.advrecyclerview.touchguard.RecyclerViewTouchActionGuardManager
import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils
import dev.olog.scrollhelper.layoutmanagers.OverScrollLinearLayoutManager
import kotlinx.android.synthetic.main.activity_playing_queue.* import kotlinx.android.synthetic.main.activity_playing_queue.*
/** /**
@ -73,7 +74,7 @@ class PlayingQueueFragment :
} }
override fun createLayoutManager(): LinearLayoutManager { override fun createLayoutManager(): LinearLayoutManager {
return LinearLayoutManager(requireContext()) return OverScrollLinearLayoutManager(requireContext())
} }
override fun createAdapter(): PlayingQueueAdapter { override fun createAdapter(): PlayingQueueAdapter {

View file

@ -13,6 +13,7 @@ import code.name.monkey.retromusic.interfaces.MainActivityFragmentCallbacks
import code.name.monkey.retromusic.model.Playlist import code.name.monkey.retromusic.model.Playlist
import code.name.monkey.retromusic.mvp.presenter.PlaylistView import code.name.monkey.retromusic.mvp.presenter.PlaylistView
import code.name.monkey.retromusic.mvp.presenter.PlaylistsPresenter import code.name.monkey.retromusic.mvp.presenter.PlaylistsPresenter
import dev.olog.scrollhelper.layoutmanagers.OverScrollGridLayoutManager
import javax.inject.Inject import javax.inject.Inject
class PlaylistsFragment : class PlaylistsFragment :
@ -40,7 +41,7 @@ class PlaylistsFragment :
} }
override fun createLayoutManager(): GridLayoutManager { override fun createLayoutManager(): GridLayoutManager {
return GridLayoutManager(requireContext(), 1) return OverScrollGridLayoutManager(requireContext(), 1)
} }
override fun createAdapter(): PlaylistAdapter { override fun createAdapter(): PlaylistAdapter {

View file

@ -14,6 +14,7 @@ import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.mvp.presenter.SongPresenter import code.name.monkey.retromusic.mvp.presenter.SongPresenter
import code.name.monkey.retromusic.mvp.presenter.SongView import code.name.monkey.retromusic.mvp.presenter.SongView
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import dev.olog.scrollhelper.layoutmanagers.OverScrollGridLayoutManager
import java.util.* import java.util.*
import javax.inject.Inject import javax.inject.Inject
@ -39,7 +40,7 @@ class SongsFragment :
} }
override fun createLayoutManager(): GridLayoutManager { override fun createLayoutManager(): GridLayoutManager {
return GridLayoutManager(requireActivity(), getGridSize()).apply { return OverScrollGridLayoutManager(requireActivity(), getGridSize()).apply {
spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() { spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int { override fun getSpanSize(position: Int): Int {
return if (position == 0) { return if (position == 0) {

View file

@ -185,7 +185,7 @@ public final class PreferenceUtil {
private static final String AUTO_DOWNLOAD_IMAGES_POLICY = "auto_download_images_policy"; private static final String AUTO_DOWNLOAD_IMAGES_POLICY = "auto_download_images_policy";
private static final String START_DIRECTORY = "start_directory"; private static final String START_DIRECTORY = "start_directory_";
private static final String SYNCHRONIZED_LYRICS_SHOW = "synchronized_lyrics_show"; private static final String SYNCHRONIZED_LYRICS_SHOW = "synchronized_lyrics_show";

View file

@ -18,11 +18,13 @@ import code.name.monkey.appthemehelper.ThemeStore.Companion.accentColor
import code.name.monkey.appthemehelper.util.ColorUtil.isColorLight import code.name.monkey.appthemehelper.util.ColorUtil.isColorLight
import code.name.monkey.appthemehelper.util.MaterialValueHelper.getPrimaryTextColor import code.name.monkey.appthemehelper.util.MaterialValueHelper.getPrimaryTextColor
import code.name.monkey.appthemehelper.util.TintHelper import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.extensions.dimen
import code.name.monkey.retromusic.extensions.dip
import code.name.monkey.retromusic.views.PopupBackground import code.name.monkey.retromusic.views.PopupBackground
import me.zhanghai.android.fastscroll.FastScroller import me.zhanghai.android.fastscroll.FastScroller
import me.zhanghai.android.fastscroll.FastScrollerBuilder import me.zhanghai.android.fastscroll.FastScrollerBuilder
import me.zhanghai.android.fastscroll.PopupStyles import me.zhanghai.android.fastscroll.PopupStyles
import me.zhanghai.android.fastscroll.R
object ThemedFastScroller { object ThemedFastScroller {
fun create(view: ViewGroup): FastScroller { fun create(view: ViewGroup): FastScroller {
@ -37,6 +39,13 @@ object ThemedFastScroller {
popupText.setTextColor(textColor) popupText.setTextColor(textColor)
} }
fastScrollerBuilder.setPadding(
0,
view.context.dimen(R.dimen.toolbar_height) + view.context.dip(8),
0,
view.context.dimen(R.dimen.mini_player_height)
)
fastScrollerBuilder.setThumbDrawable( fastScrollerBuilder.setThumbDrawable(
TintHelper.createTintedDrawable( TintHelper.createTintedDrawable(
context, context,

View file

@ -1,59 +0,0 @@
/*
* Copyright (c) 2019 Hemanth Savarala.
*
* Licensed under the GNU General Public License v3
*
* This is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*/
package code.name.monkey.retromusic.views;
import android.content.Context;
import android.content.res.Resources;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.NonNull;
public class StatusBarView extends View {
public StatusBarView(@NonNull Context context) {
super(context);
init(context);
}
public StatusBarView(@NonNull Context context, @NonNull AttributeSet attrs) {
super(context, attrs);
init(context);
}
public StatusBarView(@NonNull Context context, @NonNull AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
public static int getStatusBarHeight(@NonNull Resources r) {
int result = 0;
int resourceId = r.getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = r.getDimensionPixelSize(resourceId);
}
return result;
}
private void init(Context context) {
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), getStatusBarHeight(getResources()));
}
}

View file

@ -0,0 +1,30 @@
package code.name.monkey.retromusic.views
import android.content.Context
import android.util.AttributeSet
import android.view.View
class StatusBarView(
context: Context,
attrs: AttributeSet
) : View(context, attrs) {
override fun onAttachedToWindow() {
super.onAttachedToWindow()
if (isInEditMode){
return
}
setOnApplyWindowInsetsListener { _, insets ->
val height = insets?.systemWindowInsetTop ?: 0
setHeight(height)
insets
}
}
private fun setHeight(px: Int) {
val params = layoutParams ?: return
params.height = px
layoutParams = params
}
}

View file

@ -1,79 +1,72 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout 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" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?colorSurface" android:background="?colorSurface">
android:orientation="vertical">
<!-- TODO in order to work, children has to be defined in reverse drawing order-->
<!-- TODO so: first fragment_container, than toolbar, than statusbar -->
<FrameLayout <FrameLayout
android:layout_width="match_parent" android:id="@+id/fragment_container"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/status_bar" />
<com.google.android.material.card.MaterialCardView
android:id="@+id/toolbarContainer"
android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:elevation="0dp" app:cardCornerRadius="8dp"
tools:ignore="UnusedAttribute"> app:cardUseCompatPadding="true"
app:layout_constraintEnd_toEndOf="parent"
<include layout="@layout/status_bar" /> app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/status_bar"
</FrameLayout> app:layout_scrollFlags="scroll|enterAlways">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:elevation="0dp"
app:elevation="0dp"
app:liftOnScroll="true">
<com.google.android.material.card.MaterialCardView
android:id="@+id/toolbarContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="8dp"
app:cardUseCompatPadding="true"
app:layout_scrollFlags="scroll|enterAlways">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="@dimen/toolbar_height"
android:background="?attr/colorSurface"
app:popupTheme="?attr/toolbarPopupTheme"
app:titleTextColor="?attr/colorControlNormal"
app:titleTextAppearance="@style/TextViewHeadline6"
tools:ignore="UnusedAttribute">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/appTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/app_name"
android:textColor="?attr/colorControlNormal"
android:textAppearance="@style/TextViewHeadline6" />
</androidx.appcompat.widget.Toolbar>
<ViewStub
android:id="@+id/cab_stub"
android:layout_width="match_parent"
android:layout_height="@dimen/toolbar_height" />
</FrameLayout>
</com.google.android.material.card.MaterialCardView>
</com.google.android.material.appbar.AppBarLayout>
<FrameLayout <FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content">
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout> <androidx.appcompat.widget.Toolbar
</LinearLayout> android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="@dimen/toolbar_height"
android:background="?attr/colorSurface"
app:popupTheme="?attr/toolbarPopupTheme"
app:titleTextAppearance="@style/TextViewHeadline6"
app:titleTextColor="?attr/colorControlNormal"
tools:ignore="UnusedAttribute">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/appTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/app_name"
android:textAppearance="@style/TextViewHeadline6"
android:textColor="?attr/colorControlNormal" />
</androidx.appcompat.widget.Toolbar>
<ViewStub
android:id="@+id/cab_stub"
android:layout_width="match_parent"
android:layout_height="@dimen/toolbar_height" />
</FrameLayout>
</com.google.android.material.card.MaterialCardView>
<include
layout="@layout/status_bar"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:layout_height="24dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -17,6 +17,7 @@
android:id="@+id/container" android:id="@+id/container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/toolbar_height"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"> app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout

View file

@ -11,63 +11,72 @@
~ without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ~ without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
~ See the GNU General Public License for more details. ~ See the GNU General Public License for more details.
--> -->
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
<FrameLayout 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" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent">
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<androidx.constraintlayout.widget.ConstraintLayout <!-- <code.name.monkey.retromusic.views.RetroShapeableImageView
android:id="@+id/userImage"
android:layout_width="42dp"
android:layout_height="42dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="8dp"
android:scaleType="centerCrop"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:retroCornerSize="21dp"
tools:srcCompat="@tools:sample/avatars" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:ellipsize="end"
android:text="@string/welcome"
app:layout_constraintStart_toEndOf="@+id/userImage"
app:layout_constraintTop_toTopOf="@+id/userImage"
tools:text="@tools:sample/lorem" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/titleWelcome"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:padding="0dp"
android:textAppearance="@style/TextViewHeadline5"
android:textColor="?android:attr/textColorPrimary"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/userImage"
app:layout_constraintStart_toEndOf="@+id/userImage"
app:layout_constraintTop_toBottomOf="@+id/text"
tools:text="@tools:sample/lorem" />
-->
<!--<include
layout="@layout/home_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/titleWelcome" />-->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="match_parent"
android:nestedScrollingEnabled="false"
android:overScrollMode="never"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:spanCount="3"
tools:itemCount="3"
tools:listitem="@layout/item_album_card" />
<code.name.monkey.retromusic.views.RetroShapeableImageView </FrameLayout>
android:id="@+id/userImage"
android:layout_width="42dp"
android:layout_height="42dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="8dp"
android:scaleType="centerCrop"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:retroCornerSize="21dp"
tools:srcCompat="@tools:sample/avatars" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:ellipsize="end"
android:text="@string/welcome"
app:layout_constraintStart_toEndOf="@+id/userImage"
app:layout_constraintTop_toTopOf="@+id/userImage"
tools:text="@tools:sample/lorem" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/titleWelcome"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:padding="0dp"
android:textAppearance="@style/TextViewHeadline5"
android:textColor="?android:attr/textColorPrimary"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/userImage"
app:layout_constraintStart_toEndOf="@+id/userImage"
app:layout_constraintTop_toBottomOf="@+id/text"
tools:text="@tools:sample/lorem" />
<include
layout="@layout/home_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/titleWelcome" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>

View file

@ -6,15 +6,16 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<!-- TODO note that recycler view has to cover the entire screen -->
<!-- TODO so has to be drawn under bottom navigation, toolbar, ecc, but has to be below statusbar-->
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView" android:id="@+id/recyclerView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:clipToPadding="false" android:clipToPadding="false"
android:layoutAnimation="@anim/layout_animation_fall_down" android:layoutAnimation="@anim/layout_animation_fall_down"
android:overScrollMode="never" android:overScrollMode="never"
android:scrollbars="none" android:scrollbars="none"
app:layout_dodgeInsetEdges="bottom"
tools:listitem="@layout/item_list" /> tools:listitem="@layout/item_list" />
<LinearLayout <LinearLayout

View file

@ -22,7 +22,7 @@
android:focusableInTouchMode="true" android:focusableInTouchMode="true"
android:orientation="vertical"> android:orientation="vertical">
<include layout="@layout/abs_playlists" /> <!-- <include layout="@layout/abs_playlists" />-->
<FrameLayout <FrameLayout
android:layout_width="match_parent" android:layout_width="match_parent"

View file

@ -37,7 +37,7 @@
android:id="@+id/miniPlayerFragment" android:id="@+id/miniPlayerFragment"
android:name="code.name.monkey.retromusic.fragments.MiniPlayerFragment" android:name="code.name.monkey.retromusic.fragments.MiniPlayerFragment"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="48dp" android:layout_height="@dimen/mini_player_height"
tools:layout="@layout/fragment_mini_player" /> tools:layout="@layout/fragment_mini_player" />
</FrameLayout> </FrameLayout>

View file

@ -5,5 +5,4 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:background="@android:color/transparent" android:background="@android:color/transparent"
android:elevation="@dimen/toolbar_elevation"
tools:ignore="UnusedAttribute" /> tools:ignore="UnusedAttribute" />