Fix crahsing on home screen shortcuts

This commit is contained in:
h4h13 2019-03-05 07:52:14 +05:30
parent 835ec949ba
commit 240874f312
13 changed files with 416 additions and 524 deletions

View file

@ -12,23 +12,14 @@
* See the GNU General Public License for more details.
*/
package code.name.monkey.retromusic.model;
package code.name.monkey.retromusic.model
import android.content.Context;
import android.content.Context
import io.reactivex.Observable
import java.util.*
import java.util.ArrayList;
abstract class AbsCustomPlaylist(id: Int, name: String) : Playlist(id, name) {
import androidx.annotation.NonNull;
import io.reactivex.Observable;
import kotlinx.android.parcel.Parcelize;
@Parcelize
public abstract class AbsCustomPlaylist extends Playlist {
public AbsCustomPlaylist(int id, @NonNull String name) {
super(id, name);
}
@NonNull
public abstract Observable<ArrayList<Song>> getSongs(@NonNull Context context);
abstract fun getSongs(context: Context): Observable<ArrayList<Song>>
}

View file

@ -0,0 +1,90 @@
/*
* 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.model;
import android.os.Parcel;
import android.os.Parcelable;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class Playlist implements Parcelable {
public final int id;
public final String name;
public Playlist(final int id, final String name) {
this.id = id;
this.name = name;
}
public Playlist() {
this.id = -1;
this.name = "";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Playlist playlist = (Playlist) o;
if (id != playlist.id) return false;
return name != null ? name.equals(playlist.name) : playlist.name == null;
}
@Override
public int hashCode() {
int result = id;
result = 31 * result + (name != null ? name.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "Playlist{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.id);
dest.writeString(this.name);
}
protected Playlist(Parcel in) {
this.id = in.readInt();
this.name = in.readString();
}
public static final Creator<Playlist> CREATOR = new Creator<Playlist>() {
public Playlist createFromParcel(Parcel source) {
return new Playlist(source);
}
public Playlist[] newArray(int size) {
return new Playlist[size];
}
};
}

View file

@ -1,21 +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.model
import android.os.Parcelable
import kotlinx.android.parcel.Parcelize
@Parcelize
open class Playlist(val id: Int = -1, val name: String = "") : Parcelable

View file

@ -15,22 +15,70 @@
package code.name.monkey.retromusic.model.smartplaylist;
import android.content.Context;
import android.os.Parcel;
import android.support.annotation.DrawableRes;
import android.support.annotation.Nullable;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import code.name.monkey.retromusic.model.AbsCustomPlaylist;
import kotlinx.android.parcel.Parcelize;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.model.AbsCustomPlaylist;
@Parcelize
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public abstract class AbsSmartPlaylist extends AbsCustomPlaylist {
@DrawableRes
public final int iconRes;
public AbsSmartPlaylist(final @NonNull String name, final int iconRes) {
public AbsSmartPlaylist(final String name, final int iconRes) {
super(-Math.abs(31 * name.hashCode() + (iconRes * name.hashCode() * 31 * 31)), name);
this.iconRes = iconRes;
}
public abstract void clear(@NonNull Context context);
public AbsSmartPlaylist() {
super();
this.iconRes = R.drawable.ic_queue_music_white_24dp;
}
public abstract void clear(Context context);
public boolean isClearable() {
return true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + iconRes;
return result;
}
@Override
public boolean equals(@Nullable final Object obj) {
if (super.equals(obj)) {
if (getClass() != obj.getClass()) {
return false;
}
final AbsSmartPlaylist other = (AbsSmartPlaylist) obj;
return iconRes == other.iconRes;
}
return false;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(this.iconRes);
}
protected AbsSmartPlaylist(Parcel in) {
super(in);
this.iconRes = in.readInt();
}
}

View file

@ -0,0 +1,67 @@
/*
* 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.model.smartplaylist;
import android.content.Context;
import android.os.Parcel;
import android.support.annotation.NonNull;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.loader.TopAndRecentlyPlayedTracksLoader;
import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.provider.HistoryStore;
import java.util.ArrayList;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class HistoryPlaylist extends AbsSmartPlaylist {
public HistoryPlaylist(@NonNull Context context) {
super(context.getString(R.string.history), R.drawable.ic_access_time_white_24dp);
}
@NonNull
@Override
public ArrayList<Song> getSongs(@NonNull Context context) {
return TopAndRecentlyPlayedTracksLoader.getRecentlyPlayedTracks(context);
}
@Override
public void clear(@NonNull Context context) {
HistoryStore.getInstance(context).clear();
}
@Override
public int describeContents() {
return 0;
}
protected HistoryPlaylist(Parcel in) {
super(in);
}
public static final Creator<HistoryPlaylist> CREATOR = new Creator<HistoryPlaylist>() {
public HistoryPlaylist createFromParcel(Parcel source) {
return new HistoryPlaylist(source);
}
public HistoryPlaylist[] newArray(int size) {
return new HistoryPlaylist[size];
}
};
}

View file

@ -1,36 +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.model.smartplaylist
import android.content.Context
import java.util.ArrayList
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.loaders.TopAndRecentlyPlayedTracksLoader
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.providers.HistoryStore
import io.reactivex.Observable
import kotlinx.android.parcel.Parcelize
class HistoryPlaylist(context: Context) : AbsSmartPlaylist(context.getString(R.string.history), R.drawable.ic_access_time_white_24dp) {
override fun getSongs(context: Context): Observable<ArrayList<Song>> {
return TopAndRecentlyPlayedTracksLoader.getRecentlyPlayedTracks(context)
}
override fun clear(context: Context) {
HistoryStore.getInstance(context).clear()
}
}

View file

@ -0,0 +1,69 @@
/*
* 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.model.smartplaylist;
import android.content.Context;
import android.os.Parcel;
import android.support.annotation.NonNull;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.loader.LastAddedLoader;
import com.kabouzeid.gramophone.model.Song;
import java.util.ArrayList;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class LastAddedPlaylist extends AbsSmartPlaylist {
public LastAddedPlaylist(@NonNull Context context) {
super(context.getString(R.string.last_added), R.drawable.ic_library_add_white_24dp);
}
@NonNull
@Override
public ArrayList<Song> getSongs(@NonNull Context context) {
return LastAddedLoader.getLastAddedSongs(context);
}
@Override
public void clear(@NonNull Context context) {
}
@Override
public boolean isClearable() {
return false;
}
@Override
public int describeContents() {
return 0;
}
protected LastAddedPlaylist(Parcel in) {
super(in);
}
public static final Creator<LastAddedPlaylist> CREATOR = new Creator<LastAddedPlaylist>() {
public LastAddedPlaylist createFromParcel(Parcel source) {
return new LastAddedPlaylist(source);
}
public LastAddedPlaylist[] newArray(int size) {
return new LastAddedPlaylist[size];
}
};
}

View file

@ -1,32 +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.model.smartplaylist
import android.content.Context
import java.util.ArrayList
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.loaders.LastAddedSongsLoader
import code.name.monkey.retromusic.model.Song
import io.reactivex.Observable
class LastAddedPlaylist(context: Context) : AbsSmartPlaylist(context.getString(R.string.last_added), R.drawable.ic_library_add_white_24dp) {
override fun getSongs(context: Context): Observable<ArrayList<Song>> {
return LastAddedSongsLoader.getLastAddedSongs(context)
}
override fun clear(context: Context) {}
}

View file

@ -0,0 +1,67 @@
/*
* 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.model.smartplaylist;
import android.content.Context;
import android.os.Parcel;
import android.support.annotation.NonNull;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.loader.TopAndRecentlyPlayedTracksLoader;
import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.provider.SongPlayCountStore;
import java.util.ArrayList;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class MyTopTracksPlaylist extends AbsSmartPlaylist {
public MyTopTracksPlaylist(@NonNull Context context) {
super(context.getString(R.string.my_top_tracks), R.drawable.ic_trending_up_white_24dp);
}
@NonNull
@Override
public ArrayList<Song> getSongs(@NonNull Context context) {
return TopAndRecentlyPlayedTracksLoader.getTopTracks(context);
}
@Override
public void clear(@NonNull Context context) {
SongPlayCountStore.getInstance(context).clear();
}
@Override
public int describeContents() {
return 0;
}
protected MyTopTracksPlaylist(Parcel in) {
super(in);
}
public static final Creator<MyTopTracksPlaylist> CREATOR = new Creator<MyTopTracksPlaylist>() {
public MyTopTracksPlaylist createFromParcel(Parcel source) {
return new MyTopTracksPlaylist(source);
}
public MyTopTracksPlaylist[] newArray(int size) {
return new MyTopTracksPlaylist[size];
}
};
}

View file

@ -1,36 +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.model.smartplaylist
import android.content.Context
import java.util.ArrayList
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.loaders.TopAndRecentlyPlayedTracksLoader
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.providers.SongPlayCountStore
import io.reactivex.Observable
class MyTopTracksPlaylist(context: Context) : AbsSmartPlaylist(context.getString(R.string.my_top_tracks), R.drawable.ic_trending_up_white_24dp) {
override fun getSongs(context: Context): Observable<ArrayList<Song>> {
return TopAndRecentlyPlayedTracksLoader.getTopTracks(context)
}
override fun clear(context: Context) {
SongPlayCountStore.getInstance(context).clear()
}
}

View file

@ -0,0 +1,62 @@
/*
* 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.model.smartplaylist;
import android.content.Context;
import android.os.Parcel;
import android.support.annotation.NonNull;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.loader.SongLoader;
import com.kabouzeid.gramophone.model.Song;
import java.util.ArrayList;
public class ShuffleAllPlaylist extends AbsSmartPlaylist {
public ShuffleAllPlaylist(@NonNull Context context) {
super(context.getString(R.string.action_shuffle_all), R.drawable.ic_shuffle_white_24dp);
}
@NonNull
@Override
public ArrayList<Song> getSongs(@NonNull Context context) {
return SongLoader.getAllSongs(context);
}
@Override
public void clear(@NonNull Context context) {
// Shuffle all is not a real "Smart Playlist"
}
@Override
public int describeContents() {
return 0;
}
protected ShuffleAllPlaylist(Parcel in) {
super(in);
}
public static final Creator<ShuffleAllPlaylist> CREATOR = new Creator<ShuffleAllPlaylist>() {
public ShuffleAllPlaylist createFromParcel(Parcel source) {
return new ShuffleAllPlaylist(source);
}
public ShuffleAllPlaylist[] newArray(int size) {
return new ShuffleAllPlaylist[size];
}
};
}

View file

@ -1,35 +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.model.smartplaylist
import android.content.Context
import java.util.ArrayList
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.loaders.SongLoader
import code.name.monkey.retromusic.model.Song
import io.reactivex.Observable
class ShuffleAllPlaylist(context: Context) : AbsSmartPlaylist(context.getString(R.string.action_shuffle_all), R.drawable.ic_shuffle_white_24dp) {
override fun getSongs(context: Context): Observable<ArrayList<Song>> {
return SongLoader.getAllSongs(context)
}
override fun clear(context: Context) {
// Shuffle all is not a real "Smart Playlist"
}
}

View file

@ -1,342 +0,0 @@
package code.name.monkey.appthemehelper.util
import android.annotation.TargetApi
import android.graphics.PorterDuff
import android.graphics.drawable.Drawable
import android.os.Build
import androidx.annotation.ColorInt
import androidx.viewpager.widget.ViewPager
import androidx.core.widget.EdgeEffectCompat
import androidx.core.widget.NestedScrollView
import androidx.recyclerview.widget.RecyclerView
import android.widget.AbsListView
import android.widget.EdgeEffect
import android.widget.ScrollView
import code.name.monkey.appthemehelper.BuildConfig
import java.lang.reflect.Field
class EdgeGlowUtil protected constructor() {
companion object {
// Invalidation methods
private var EDGE_GLOW_FIELD_EDGE: Field? = null
private var EDGE_GLOW_FIELD_GLOW: Field? = null
private var EDGE_EFFECT_COMPAT_FIELD_EDGE_EFFECT: Field? = null
private fun invalidateEdgeEffectFields() {
if (EDGE_GLOW_FIELD_EDGE != null && EDGE_GLOW_FIELD_GLOW != null &&
EDGE_EFFECT_COMPAT_FIELD_EDGE_EFFECT != null) {
EDGE_GLOW_FIELD_EDGE!!.isAccessible = true
EDGE_GLOW_FIELD_GLOW!!.isAccessible = true
EDGE_EFFECT_COMPAT_FIELD_EDGE_EFFECT!!.isAccessible = true
return
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
var edge: Field? = null
var glow: Field? = null
var cls: Class<*>? = null
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
try {
cls = Class.forName("android.widget.EdgeGlow")
} catch (e: ClassNotFoundException) {
if (BuildConfig.DEBUG) e.printStackTrace()
}
} else {
cls = EdgeEffect::class.java
}
if (cls != null) {
for (f in cls.declaredFields) {
when (f.name) {
"mEdge" -> {
f.isAccessible = true
edge = f
}
"mGlow" -> {
f.isAccessible = true
glow = f
}
}
}
}
EDGE_GLOW_FIELD_EDGE = edge
EDGE_GLOW_FIELD_GLOW = glow
} else {
EDGE_GLOW_FIELD_EDGE = null
EDGE_GLOW_FIELD_GLOW = null
}
var efc: Field? = null
try {
efc = EdgeEffectCompat::class.java.getDeclaredField("mEdgeEffect")
} catch (e: NoSuchFieldException) {
if (BuildConfig.DEBUG) e.printStackTrace()
}
EDGE_EFFECT_COMPAT_FIELD_EDGE_EFFECT = efc
}
private var SCROLL_VIEW_FIELD_EDGE_GLOW_TOP: Field? = null
private var SCROLL_VIEW_FIELD_EDGE_GLOW_BOTTOM: Field? = null
private fun invalidateScrollViewFields() {
if (SCROLL_VIEW_FIELD_EDGE_GLOW_TOP != null && SCROLL_VIEW_FIELD_EDGE_GLOW_BOTTOM != null) {
SCROLL_VIEW_FIELD_EDGE_GLOW_TOP!!.isAccessible = true
SCROLL_VIEW_FIELD_EDGE_GLOW_BOTTOM!!.isAccessible = true
return
}
val cls = ScrollView::class.java
for (f in cls.declaredFields) {
when (f.name) {
"mEdgeGlowTop" -> {
f.isAccessible = true
SCROLL_VIEW_FIELD_EDGE_GLOW_TOP = f
}
"mEdgeGlowBottom" -> {
f.isAccessible = true
SCROLL_VIEW_FIELD_EDGE_GLOW_BOTTOM = f
}
}
}
}
private var NESTED_SCROLL_VIEW_FIELD_EDGE_GLOW_TOP: Field? = null
private var NESTED_SCROLL_VIEW_FIELD_EDGE_GLOW_BOTTOM: Field? = null
private fun invalidateNestedScrollViewFields() {
if (NESTED_SCROLL_VIEW_FIELD_EDGE_GLOW_TOP != null && NESTED_SCROLL_VIEW_FIELD_EDGE_GLOW_BOTTOM != null) {
NESTED_SCROLL_VIEW_FIELD_EDGE_GLOW_TOP!!.isAccessible = true
NESTED_SCROLL_VIEW_FIELD_EDGE_GLOW_BOTTOM!!.isAccessible = true
return
}
val cls = ATHUtil.inClassPath("android.support.v4.widget.NestedScrollView")
for (f in cls.declaredFields) {
when (f.name) {
"mEdgeGlowTop" -> {
f.isAccessible = true
NESTED_SCROLL_VIEW_FIELD_EDGE_GLOW_TOP = f
}
"mEdgeGlowBottom" -> {
f.isAccessible = true
NESTED_SCROLL_VIEW_FIELD_EDGE_GLOW_BOTTOM = f
}
}
}
}
private var LIST_VIEW_FIELD_EDGE_GLOW_TOP: Field? = null
private var LIST_VIEW_FIELD_EDGE_GLOW_BOTTOM: Field? = null
private fun invalidateListViewFields() {
if (LIST_VIEW_FIELD_EDGE_GLOW_TOP != null && LIST_VIEW_FIELD_EDGE_GLOW_BOTTOM != null) {
LIST_VIEW_FIELD_EDGE_GLOW_TOP!!.isAccessible = true
LIST_VIEW_FIELD_EDGE_GLOW_BOTTOM!!.isAccessible = true
return
}
val cls = AbsListView::class.java
for (f in cls.declaredFields) {
when (f.name) {
"mEdgeGlowTop" -> {
f.isAccessible = true
LIST_VIEW_FIELD_EDGE_GLOW_TOP = f
}
"mEdgeGlowBottom" -> {
f.isAccessible = true
LIST_VIEW_FIELD_EDGE_GLOW_BOTTOM = f
}
}
}
}
private var RECYCLER_VIEW_FIELD_EDGE_GLOW_TOP: Field? = null
private var RECYCLER_VIEW_FIELD_EDGE_GLOW_LEFT: Field? = null
private var RECYCLER_VIEW_FIELD_EDGE_GLOW_RIGHT: Field? = null
private var RECYCLER_VIEW_FIELD_EDGE_GLOW_BOTTOM: Field? = null
private fun invalidateRecyclerViewFields() {
if (RECYCLER_VIEW_FIELD_EDGE_GLOW_TOP != null && RECYCLER_VIEW_FIELD_EDGE_GLOW_LEFT != null &&
RECYCLER_VIEW_FIELD_EDGE_GLOW_RIGHT != null && RECYCLER_VIEW_FIELD_EDGE_GLOW_BOTTOM != null) {
RECYCLER_VIEW_FIELD_EDGE_GLOW_TOP!!.isAccessible = true
RECYCLER_VIEW_FIELD_EDGE_GLOW_LEFT!!.isAccessible = true
RECYCLER_VIEW_FIELD_EDGE_GLOW_RIGHT!!.isAccessible = true
RECYCLER_VIEW_FIELD_EDGE_GLOW_BOTTOM!!.isAccessible = true
return
}
val cls = ATHUtil.inClassPath("android.support.v7.widget.RecyclerView")
for (f in cls.declaredFields) {
when (f.name) {
"mTopGlow" -> {
f.isAccessible = true
RECYCLER_VIEW_FIELD_EDGE_GLOW_TOP = f
}
"mBottomGlow" -> {
f.isAccessible = true
RECYCLER_VIEW_FIELD_EDGE_GLOW_BOTTOM = f
}
"mLeftGlow" -> {
f.isAccessible = true
RECYCLER_VIEW_FIELD_EDGE_GLOW_LEFT = f
}
"mRightGlow" -> {
f.isAccessible = true
RECYCLER_VIEW_FIELD_EDGE_GLOW_RIGHT = f
}
}
}
}
private var VIEW_PAGER_FIELD_EDGE_GLOW_LEFT: Field? = null
private var VIEW_PAGER_FIELD_EDGE_GLOW_RIGHT: Field? = null
private fun invalidateViewPagerFields() {
if (VIEW_PAGER_FIELD_EDGE_GLOW_LEFT != null && VIEW_PAGER_FIELD_EDGE_GLOW_RIGHT != null) {
VIEW_PAGER_FIELD_EDGE_GLOW_LEFT!!.isAccessible = true
VIEW_PAGER_FIELD_EDGE_GLOW_RIGHT!!.isAccessible = true
return
}
val cls = ATHUtil.inClassPath("android.support.v4.view.ViewPager")
for (f in cls.declaredFields) {
when (f.name) {
"mLeftEdge" -> {
f.isAccessible = true
VIEW_PAGER_FIELD_EDGE_GLOW_LEFT = f
}
"mRightEdge" -> {
f.isAccessible = true
VIEW_PAGER_FIELD_EDGE_GLOW_RIGHT = f
}
}
}
}
// Setter methods
fun setEdgeGlowColor(scrollView: ScrollView, @ColorInt color: Int) {
invalidateScrollViewFields()
try {
var ee: Any
ee = SCROLL_VIEW_FIELD_EDGE_GLOW_TOP!!.get(scrollView)
setEffectColor(ee, color)
ee = SCROLL_VIEW_FIELD_EDGE_GLOW_BOTTOM!!.get(scrollView)
setEffectColor(ee, color)
} catch (ex: Exception) {
if (BuildConfig.DEBUG) ex.printStackTrace()
}
}
fun setEdgeGlowColor(scrollView: NestedScrollView, @ColorInt color: Int) {
invalidateNestedScrollViewFields()
try {
var ee: Any
ee = NESTED_SCROLL_VIEW_FIELD_EDGE_GLOW_TOP!!.get(scrollView)
setEffectColor(ee, color)
ee = NESTED_SCROLL_VIEW_FIELD_EDGE_GLOW_BOTTOM!!.get(scrollView)
setEffectColor(ee, color)
} catch (ex: Exception) {
if (BuildConfig.DEBUG) ex.printStackTrace()
}
}
fun setEdgeGlowColor(listView: AbsListView, @ColorInt color: Int) {
invalidateListViewFields()
try {
var ee: Any
ee = LIST_VIEW_FIELD_EDGE_GLOW_TOP!!.get(listView)
setEffectColor(ee, color)
ee = LIST_VIEW_FIELD_EDGE_GLOW_BOTTOM!!.get(listView)
setEffectColor(ee, color)
} catch (ex: Exception) {
if (BuildConfig.DEBUG) ex.printStackTrace()
}
}
fun setEdgeGlowColor(scrollView: RecyclerView, @ColorInt color: Int, scrollListener: RecyclerView.OnScrollListener?) {
var scrollListener = scrollListener
invalidateRecyclerViewFields()
invalidateRecyclerViewFields()
if (scrollListener == null) {
scrollListener = object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
EdgeGlowUtil.setEdgeGlowColor(recyclerView, color, this)
}
}
scrollView.addOnScrollListener(scrollListener)
}
try {
var ee: Any
ee = RECYCLER_VIEW_FIELD_EDGE_GLOW_TOP!!.get(scrollView)
setEffectColor(ee, color)
ee = RECYCLER_VIEW_FIELD_EDGE_GLOW_BOTTOM!!.get(scrollView)
setEffectColor(ee, color)
ee = RECYCLER_VIEW_FIELD_EDGE_GLOW_LEFT!!.get(scrollView)
setEffectColor(ee, color)
ee = RECYCLER_VIEW_FIELD_EDGE_GLOW_RIGHT!!.get(scrollView)
setEffectColor(ee, color)
} catch (ex: Exception) {
if (BuildConfig.DEBUG) ex.printStackTrace()
}
}
fun setEdgeGlowColor(pager: ViewPager, @ColorInt color: Int) {
invalidateViewPagerFields()
try {
var ee: Any
ee = VIEW_PAGER_FIELD_EDGE_GLOW_LEFT!!.get(pager)
setEffectColor(ee, color)
ee = VIEW_PAGER_FIELD_EDGE_GLOW_RIGHT!!.get(pager)
setEffectColor(ee, color)
} catch (ex: Exception) {
if (BuildConfig.DEBUG) ex.printStackTrace()
}
}
// Utilities
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private fun setEffectColor(edgeEffect: Any?, @ColorInt color: Int) {
var edgeEffect = edgeEffect
invalidateEdgeEffectFields()
if (edgeEffect is EdgeEffectCompat) {
// EdgeEffectCompat
try {
EDGE_EFFECT_COMPAT_FIELD_EDGE_EFFECT!!.isAccessible = true
edgeEffect = EDGE_EFFECT_COMPAT_FIELD_EDGE_EFFECT!!.get(edgeEffect)
} catch (e: IllegalAccessException) {
e.printStackTrace()
return
}
}
if (edgeEffect == null)
return
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
// EdgeGlow
try {
EDGE_GLOW_FIELD_EDGE!!.isAccessible = true
val mEdge = EDGE_GLOW_FIELD_EDGE!!.get(edgeEffect) as Drawable
EDGE_GLOW_FIELD_GLOW!!.isAccessible = true
val mGlow = EDGE_GLOW_FIELD_GLOW!!.get(edgeEffect) as Drawable
mEdge.setColorFilter(color, PorterDuff.Mode.SRC_IN)
mGlow.setColorFilter(color, PorterDuff.Mode.SRC_IN)
mEdge.callback = null // free up any references
mGlow.callback = null // free up any references
} catch (ex: Exception) {
ex.printStackTrace()
}
} else {
// EdgeEffect
(edgeEffect as EdgeEffect).color = color
}
}
}
}