Skip to content

Commit 803e254

Browse files
Faeb35paroj
authored andcommitted
Now Playing glow and gesture
1 parent 86d3117 commit 803e254

8 files changed

Lines changed: 161 additions & 38 deletions

File tree

app/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,4 +102,5 @@ dependencies {
102102
implementation 'androidx.fragment:fragment:1.8.8'
103103
debugImplementation 'org.slf4j:slf4j-api:2.0.17' // For jupnp logging in debug builds
104104
debugImplementation 'uk.uuid.slf4j:slf4j-android:2.0.17-0'
105+
implementation 'androidx.palette:palette:1.0.0'
105106
}

app/src/main/java/github/paroj/dsub2000/fragments/NowPlayingFragment.java

Lines changed: 83 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,23 @@
2121
import java.util.concurrent.ScheduledExecutorService;
2222
import java.util.concurrent.TimeUnit;
2323

24+
import android.animation.ValueAnimator;
2425
import android.annotation.TargetApi;
2526
import androidx.appcompat.app.AlertDialog;
2627
import android.content.DialogInterface;
2728
import android.content.Intent;
2829
import android.content.SharedPreferences;
2930
import android.content.res.Configuration;
31+
import android.graphics.Bitmap;
32+
import android.graphics.Color;
33+
import android.graphics.Rect;
34+
import android.graphics.drawable.GradientDrawable;
35+
import android.graphics.drawable.TransitionDrawable;
3036
import android.os.Build;
3137
import android.os.Bundle;
3238
import android.os.Handler;
39+
40+
import androidx.core.graphics.ColorUtils;
3341
import androidx.core.view.MenuItemCompat;
3442
import androidx.mediarouter.app.MediaRouteButton;
3543
import androidx.recyclerview.widget.LinearLayoutManager;
@@ -50,14 +58,15 @@
5058
import android.view.WindowManager;
5159
import android.view.animation.AnimationUtils;
5260
import android.widget.EditText;
61+
import android.widget.FrameLayout;
5362
import android.widget.ImageButton;
54-
import android.widget.ImageView;
5563
import android.widget.SeekBar;
5664
import android.widget.TextView;
5765
import android.widget.ViewFlipper;
5866
import com.shehabic.droppy.DroppyClickCallbackInterface;
5967
import com.shehabic.droppy.DroppyMenuPopup;
6068
import com.shehabic.droppy.animations.DroppyFadeInAnimation;
69+
6170
import github.paroj.dsub2000.R;
6271
import github.paroj.dsub2000.activity.SubsonicFragmentActivity;
6372
import github.paroj.dsub2000.adapter.SectionAdapter;
@@ -78,6 +87,7 @@
7887
import github.paroj.dsub2000.adapter.DownloadFileAdapter;
7988
import github.paroj.dsub2000.view.FadeOutAnimation;
8089
import github.paroj.dsub2000.view.FastScroller;
90+
import github.paroj.dsub2000.view.RecyclingImageView;
8191
import github.paroj.dsub2000.view.UpdateView;
8292
import github.paroj.dsub2000.util.Util;
8393

@@ -95,12 +105,15 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
95105
private static final int ACTION_PREVIOUS = 1;
96106
private static final int ACTION_NEXT = 2;
97107
private static final int ACTION_REWIND = 3;
98-
private static final int ACTION_FORWARD = 4;
108+
private static final int ACTION_CLOSE = 4;
99109

110+
private FrameLayout downloadLayout;
111+
private int lastAlbumArtColor;
112+
private GradientDrawable glowDrawable;
100113
private ViewFlipper playlistFlipper;
101114
private TextView emptyTextView;
102115
private TextView songTitleTextView;
103-
private ImageView albumArtImageView;
116+
private RecyclingImageView albumArtImageView;
104117
private RecyclerView playlistView;
105118
private TextView positionTextView;
106119
private TextView durationTextView;
@@ -169,11 +182,63 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bu
169182
swipeDistance = (d.getWidth() + d.getHeight()) * PERCENTAGE_OF_SCREEN_FOR_SWIPE / 100;
170183
swipeVelocity = (d.getWidth() + d.getHeight()) * PERCENTAGE_OF_SCREEN_FOR_SWIPE / 100;
171184
gestureScanner = new GestureDetector(this);
185+
downloadLayout = (FrameLayout) rootView.findViewById(R.id.download_album_art_background);
186+
downloadLayout.setOnTouchListener(new View.OnTouchListener() {
187+
@Override
188+
public boolean onTouch(View v, MotionEvent me) {
189+
return gestureScanner.onTouchEvent(me);
190+
}
191+
});
192+
albumArtImageView = (RecyclingImageView)rootView.findViewById(R.id.download_album_art_image);
193+
if (albumArtImageView != null && downloadLayout != null) {
194+
glowDrawable = new GradientDrawable();
195+
downloadLayout.setBackground(glowDrawable);
196+
albumArtImageView.setOnImageChangedListener(drawable -> {
197+
if (drawable instanceof TransitionDrawable) {
198+
return;
199+
}
200+
Bitmap bitmap = ImageUtil.getBitmapFromDrawable(drawable);
201+
int albumArtColor = ImageUtil.getVibrantColorFromBitmap(bitmap, Color.TRANSPARENT);
202+
if (albumArtColor == Color.TRANSPARENT || lastAlbumArtColor == albumArtColor) {
203+
return;
204+
}
205+
206+
int gWidth = downloadLayout.getMeasuredWidth();
207+
int gHeight = downloadLayout.getMeasuredHeight();
208+
float gradientRadius = Math.max(gWidth, gHeight) * 0.52f;
209+
glowDrawable.setGradientType(GradientDrawable.RADIAL_GRADIENT);
210+
glowDrawable.setGradientRadius(gradientRadius);
211+
glowDrawable.setDither(true);
212+
213+
ValueAnimator animator = ValueAnimator.ofArgb(lastAlbumArtColor, albumArtColor);
214+
animator.setDuration(900);
215+
animator.addUpdateListener(animation -> {
216+
int color = (int) animation.getAnimatedValue();
217+
glowDrawable.setColors(new int[]{
218+
ColorUtils.setAlphaComponent(color, 100),
219+
ColorUtils.setAlphaComponent(color, 100),
220+
ColorUtils.setAlphaComponent(color, 100),
221+
ColorUtils.setAlphaComponent(color, 80),
222+
ColorUtils.setAlphaComponent(color, 0)
223+
});
224+
});
225+
animator.start();
226+
lastAlbumArtColor = albumArtColor;
227+
});
228+
albumArtImageView.setOnTouchListener(new View.OnTouchListener() {
229+
@Override
230+
public boolean onTouch(View v, MotionEvent me) {
231+
if (me.getAction() == MotionEvent.ACTION_DOWN) {
232+
lastY = (int) me.getRawY();
233+
}
234+
return gestureScanner.onTouchEvent(me);
235+
}
236+
});
237+
}
172238

173239
playlistFlipper = (ViewFlipper)rootView.findViewById(R.id.download_playlist_flipper);
174240
emptyTextView = (TextView)rootView.findViewById(R.id.download_empty);
175241
songTitleTextView = (TextView)rootView.findViewById(R.id.download_song_title);
176-
albumArtImageView = (ImageView)rootView.findViewById(R.id.download_album_art_image);
177242
positionTextView = (TextView)rootView.findViewById(R.id.download_position);
178243
durationTextView = (TextView)rootView.findViewById(R.id.download_duration);
179244
statusTextView = (TextView)rootView.findViewById(R.id.download_status);
@@ -237,15 +302,6 @@ public boolean onTouch(View v, MotionEvent me) {
237302
rateCombinedButton.setOnTouchListener(touchListener);
238303
playbackSpeedButton.setOnTouchListener(touchListener);
239304
emptyTextView.setOnTouchListener(touchListener);
240-
albumArtImageView.setOnTouchListener(new View.OnTouchListener() {
241-
@Override
242-
public boolean onTouch(View v, MotionEvent me) {
243-
if (me.getAction() == MotionEvent.ACTION_DOWN) {
244-
lastY = (int) me.getRawY();
245-
}
246-
return gestureScanner.onTouchEvent(me);
247-
}
248-
});
249305

250306
previousButton.setOnClickListener(new View.OnClickListener() {
251307
@Override
@@ -436,7 +492,7 @@ public void onClick(View view) {
436492
albumArtImageView.setOnClickListener(new View.OnClickListener() {
437493
@Override
438494
public void onClick(View view) {
439-
if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_TAP_COVER_FOR_PLAYLIST, true)) {
495+
if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_TAP_COVER_FOR_PLAYLIST, false)) {
440496
if (overlayHeight == -1 || lastY < (view.getBottom() - overlayHeight)) {
441497
toggleFullscreenAlbumArt();
442498
setControlsVisible(true);
@@ -1190,13 +1246,22 @@ else if (e2.getX() - e1.getX() > swipeDistance && Math.abs(velocityX) > swipeVel
11901246
}
11911247
// Top to Bottom swipe
11921248
else if (e2.getY() - e1.getY() > swipeDistance && Math.abs(velocityY) > swipeVelocity) {
1193-
action = ACTION_FORWARD;
1249+
action = ACTION_CLOSE;
11941250
}
11951251
// Bottom to Top swipe
11961252
else if (e1.getY() - e2.getY() > swipeDistance && Math.abs(velocityY) > swipeVelocity) {
11971253
action = ACTION_REWIND;
11981254
}
11991255

1256+
Rect rect = new Rect();
1257+
albumArtImageView.getGlobalVisibleRect(rect);
1258+
int x = (int) e1.getRawX();
1259+
int y = (int) e1.getRawY();
1260+
boolean startedOnImage = rect.contains(x, y);
1261+
if (!startedOnImage && action != ACTION_CLOSE) {
1262+
return false;
1263+
}
1264+
12001265
if(action > 0) {
12011266
final int performAction = action;
12021267
warnIfStorageUnavailable();
@@ -1210,8 +1275,9 @@ protected Void doInBackground() throws Throwable {
12101275
case ACTION_PREVIOUS:
12111276
downloadService.previous();
12121277
break;
1213-
case ACTION_FORWARD:
1214-
downloadService.fastForward();
1278+
case ACTION_CLOSE:
1279+
SubsonicFragmentActivity activity = (SubsonicFragmentActivity) getActivity();
1280+
activity.closeNowPlaying();
12151281
break;
12161282
case ACTION_REWIND:
12171283
downloadService.rewind();
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package github.paroj.dsub2000.util;
2+
3+
import android.graphics.Bitmap;
4+
import android.graphics.Canvas;
5+
import android.graphics.drawable.Drawable;
6+
7+
import androidx.palette.graphics.Palette;
8+
9+
public class ImageUtil {
10+
11+
public static Bitmap getBitmapFromDrawable(Drawable drawable) {
12+
int width = drawable.getIntrinsicWidth();
13+
int height = drawable.getIntrinsicHeight();
14+
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
15+
Canvas canvas = new Canvas(bitmap);
16+
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
17+
drawable.draw(canvas);
18+
return bitmap;
19+
}
20+
21+
public static int getVibrantColorFromBitmap(Bitmap bitmap, int defaultColor) {
22+
Palette palette = Palette.from(bitmap).generate();
23+
int dominantColor = palette.getDominantColor(defaultColor);
24+
return palette.getVibrantColor(dominantColor);
25+
}
26+
}

app/src/main/java/github/paroj/dsub2000/view/RecyclingImageView.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@
2828
public class RecyclingImageView extends ImageView {
2929
private boolean invalidated = false;
3030
private OnInvalidated onInvalidated;
31+
private OnImageChangedListener listener;
32+
public interface OnImageChangedListener {
33+
void onImageChanged(Drawable drawable);
34+
}
3135

3236
public RecyclingImageView(Context context) {
3337
super(context);
@@ -84,6 +88,9 @@ public void onDraw(Canvas canvas) {
8488
public void setImageDrawable(Drawable drawable) {
8589
super.setImageDrawable(drawable);
8690
setInvalidated(false);
91+
if (listener != null) {
92+
listener.onImageChanged(drawable);
93+
}
8794
}
8895

8996
private boolean isBitmapRecycled(Drawable drawable) {
@@ -99,6 +106,10 @@ private boolean isBitmapRecycled(Drawable drawable) {
99106
}
100107
}
101108

109+
public void setOnImageChangedListener(OnImageChangedListener listener) {
110+
this.listener = listener;
111+
}
112+
102113
public void setInvalidated(boolean invalidated) {
103114
this.invalidated = invalidated;
104115

app/src/main/res/layout-land/download.xml

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,33 @@
77

88
<ViewFlipper
99
android:id="@+id/download_playlist_flipper"
10-
android:layout_width="match_parent"
10+
android:layout_width="0dp"
1111
android:layout_height="match_parent"
1212
android:layout_weight="1">
1313

14-
<github.paroj.dsub2000.view.RecyclingImageView
15-
android:id="@+id/download_album_art_image"
16-
android:src="@drawable/unknown_album_large"
17-
android:layout_width="wrap_content"
18-
android:layout_height="match_parent"
19-
android:layout_weight="1"
20-
android:scaleType="fitCenter"/>
14+
<FrameLayout
15+
android:id="@+id/download_album_art_background"
16+
android:clickable="true"
17+
android:layout_width="match_parent"
18+
android:layout_height="match_parent">
19+
20+
<github.paroj.dsub2000.view.RecyclingImageView
21+
android:id="@+id/download_album_art_image"
22+
android:src="@drawable/unknown_album_large"
23+
android:layout_width="wrap_content"
24+
android:layout_height="wrap_content"
25+
android:layout_gravity="center"
26+
android:adjustViewBounds="true"
27+
android:scaleType="fitCenter"/>
28+
</FrameLayout>
2129

2230
<include layout="@layout/download_playlist"/>
2331

2432
</ViewFlipper>
2533

2634
<RelativeLayout
2735
android:id="@+id/download_control_layout"
28-
android:layout_width="match_parent"
36+
android:layout_width="0dp"
2937
android:layout_height="match_parent"
3038
android:layout_weight="1"
3139
android:background="@android:color/transparent">

app/src/main/res/layout-large-land/download.xml

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,27 @@
55
android:layout_width="match_parent"
66
android:layout_height="match_parent">
77

8-
<github.paroj.dsub2000.view.RecyclingImageView
9-
android:id="@+id/download_album_art_image"
10-
android:src="@drawable/unknown_album_large"
11-
android:layout_width="match_parent"
12-
android:layout_height="match_parent"
13-
android:layout_weight="1"
14-
android:scaleType="fitCenter"/>
8+
<FrameLayout
9+
android:id="@+id/download_album_art_background"
10+
android:clickable="true"
11+
android:layout_width="0dp"
12+
android:layout_height="match_parent"
13+
android:layout_weight="1">
14+
15+
<github.paroj.dsub2000.view.RecyclingImageView
16+
android:id="@+id/download_album_art_image"
17+
android:src="@drawable/unknown_album_large"
18+
android:layout_width="match_parent"
19+
android:layout_height="match_parent"
20+
android:adjustViewBounds="true"
21+
android:scaleType="fitCenter"/>
22+
</FrameLayout>
1523

1624
<RelativeLayout
1725
android:id="@+id/download_control_layout"
18-
android:layout_width="match_parent"
19-
android:layout_height="match_parent"
20-
android:layout_weight="1"
26+
android:layout_width="0dp"
27+
android:layout_height="match_parent"
28+
android:layout_weight="1"
2129
android:background="@android:color/transparent">
2230

2331
<ViewFlipper

app/src/main/res/layout-port/download.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,16 @@
2525
android:background="@android:color/transparent">
2626

2727
<FrameLayout
28+
android:id="@+id/download_album_art_background"
29+
android:clickable="true"
2830
android:layout_width="match_parent"
2931
android:layout_height="0dp"
3032
android:layout_weight="1">
3133

3234
<FrameLayout android:orientation="vertical"
3335
android:layout_width="match_parent"
34-
android:layout_height="wrap_content">
36+
android:layout_height="wrap_content"
37+
android:layout_gravity="center">
3538

3639
<github.paroj.dsub2000.view.RecyclingImageView
3740
android:id="@+id/download_album_art_image"

app/src/main/res/xml/settings_playback.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
android:title="@string/settings.tap_cover_for_playlist"
7979
android:summary="@string/settings.tap_cover_for_playlist_summary"
8080
android:key="tapCoverForPlaylist"
81-
android:defaultValue="true"/>
81+
android:defaultValue="false"/>
8282

8383
<CheckBoxPreference
8484
android:title="@string/settings.combine_thumbs_up_down"

0 commit comments

Comments
 (0)