Merge pull request #403 from Adonai/scroll-to-song
Implement scroll-to-song and option in menu
This commit is contained in:
commit
28017eebd5
@ -189,6 +189,8 @@
|
||||
<string name="use_idle_timeout_title">Задействовать таймер простоя</string>
|
||||
<string name="use_idle_timeout_summary">Воспроизведение остановится после определенного периода бездействия</string>
|
||||
<string name="idle_timeout_title">Время ожидания</string>
|
||||
<string name="enable_scroll_to_song_title">Прокрутка до песни</string>
|
||||
<string name="enable_scroll_to_song_summary">Прокручивать до текущей песни/альбома/исполнителя в списках библиотеки</string>
|
||||
<string name="coverloader_android_title">Загружать обложки из баз Android</string>
|
||||
<string name="coverloader_android_summary">Запрашивать обложки из встроенной базы медиа данных ОС Android</string>
|
||||
<string name="coverloader_vanilla_title">Загружать обложки из папки</string>
|
||||
|
@ -215,6 +215,9 @@ THE SOFTWARE.
|
||||
<string name="use_idle_timeout_summary">When active, playback will be stopped after the given period of inactivity</string>
|
||||
<string name="idle_timeout_title">Idle timeout</string>
|
||||
|
||||
<string name="enable_scroll_to_song_title">Scroll to song title</string>
|
||||
<string name="enable_scroll_to_song_summary">Scroll to currently playing song/album/artist in library lists</string>
|
||||
|
||||
<string name="coverloader_android_title">Load artwork from Android</string>
|
||||
<string name="coverloader_android_summary">Query Androids internal media database for album artwork</string>
|
||||
|
||||
|
@ -42,6 +42,11 @@ THE SOFTWARE.
|
||||
android:entries="@array/default_playlist_action_entries"
|
||||
android:entryValues="@array/default_playlist_action_entry_values"
|
||||
android:defaultValue="0" />
|
||||
<CheckBoxPreference
|
||||
android:key="enable_scroll_to_song"
|
||||
android:title="@string/enable_scroll_to_song_title"
|
||||
android:summary="@string/enable_scroll_to_song_summary"
|
||||
android:defaultValue="false" />
|
||||
<PreferenceScreen
|
||||
android:title="@string/filebrowser_start"
|
||||
android:summary="@string/customize_filebrowser_start">
|
||||
|
@ -28,39 +28,30 @@ import android.content.ContentResolver;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.PaintDrawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.provider.MediaStore;
|
||||
import android.support.iosched.tabs.VanillaTabLayout;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.SubMenu;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.HorizontalScrollView;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import android.widget.SearchView;
|
||||
|
||||
import java.io.File;
|
||||
@ -872,8 +863,10 @@ public class LibraryActivity
|
||||
super.onSongChange(song);
|
||||
|
||||
mBottomBarControls.setSong(song);
|
||||
if (song != null)
|
||||
if (song != null) {
|
||||
mHandler.sendMessage(mHandler.obtainMessage(MSG_UPDATE_COVER, song));
|
||||
mPagerAdapter.onSongChange(song);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -26,7 +26,7 @@ package ch.blinkenlights.android.vanilla;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.database.ContentObserver;
|
||||
import android.os.Build;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
@ -35,6 +35,7 @@ import android.os.Parcelable;
|
||||
import android.provider.MediaStore;
|
||||
import android.support.v4.view.PagerAdapter;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.util.TypedValue;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.ContextMenu.ContextMenuInfo;
|
||||
import android.view.LayoutInflater;
|
||||
@ -48,6 +49,8 @@ import android.widget.TextView;
|
||||
import android.widget.LinearLayout;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static android.graphics.drawable.GradientDrawable.Orientation.RIGHT_LEFT;
|
||||
|
||||
/**
|
||||
* PagerAdapter that manages the library media ListViews.
|
||||
*/
|
||||
@ -851,6 +854,39 @@ public class LibraryPagerAdapter
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform usability-related actions on pager and contained lists, e.g. highlight current song
|
||||
* or scroll to it if opted-in
|
||||
* @param song song that is currently playing, can be null
|
||||
*/
|
||||
public void onSongChange(Song song) {
|
||||
int type = mTabOrder[mCurrentPage];
|
||||
long id = MediaUtils.getCurrentIdForType(song, type);
|
||||
if (id == -1) // unknown type
|
||||
return;
|
||||
|
||||
ListView view = mLists[type];
|
||||
if (view == null) // not initialized yet, nothing to do
|
||||
return;
|
||||
|
||||
// scroll to song on song change if opted-in
|
||||
SharedPreferences sharedPrefs = PlaybackService.getSettings(mActivity);
|
||||
boolean shouldScroll = sharedPrefs.getBoolean(PrefKeys.ENABLE_SCROLL_TO_SONG, PrefDefaults.ENABLE_SCROLL_TO_SONG);
|
||||
if(shouldScroll) {
|
||||
int middlePos = (view.getFirstVisiblePosition() + view.getLastVisiblePosition()) / 2;
|
||||
for (int pos = 0; pos < view.getCount(); pos++) {
|
||||
if (view.getItemIdAtPosition(pos) == id) {
|
||||
if (Math.abs(middlePos - pos) < 30) {
|
||||
view.smoothScrollToPosition(pos);
|
||||
} else {
|
||||
view.setSelection(pos);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* LRU implementation: saves the adapter position
|
||||
*/
|
||||
|
@ -341,7 +341,7 @@ public class MediaUtils {
|
||||
String[] projection = { "_id" };
|
||||
Uri uri = MediaStore.Audio.Genres.getContentUriForAudioId("external", (int)id);
|
||||
Cursor cursor = queryResolver(resolver, uri, projection, null, null, null);
|
||||
|
||||
|
||||
if (cursor != null) {
|
||||
if (cursor.moveToNext())
|
||||
return cursor.getLong(0);
|
||||
@ -381,7 +381,7 @@ public class MediaUtils {
|
||||
if (albumShuffle) {
|
||||
List<Song> tempList = new ArrayList<Song>(list);
|
||||
Collections.sort(tempList);
|
||||
|
||||
|
||||
// Build map of albumId to start index in sorted list
|
||||
Map<Long, Integer> albumStartIndices = new HashMap<Long, Integer>();
|
||||
int index = 0;
|
||||
@ -391,11 +391,11 @@ public class MediaUtils {
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
|
||||
//Extract album list and shuffle
|
||||
List<Long> shuffledAlbums = new ArrayList<Long>(albumStartIndices.keySet());
|
||||
Collections.shuffle(shuffledAlbums, random);
|
||||
|
||||
|
||||
//Build Song list from album list
|
||||
list.clear();
|
||||
for (Long albumId : shuffledAlbums) {
|
||||
@ -588,16 +588,16 @@ public class MediaUtils {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pfx = (new File(pfx)).getParent();
|
||||
if(pfx == null)
|
||||
break; /* hit root */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a final slash if the path points to an existing directory
|
||||
*/
|
||||
@ -682,4 +682,28 @@ public class MediaUtils {
|
||||
return matrixCursor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve ID of specified media type for requested song. This works only for
|
||||
* media-oriented types: {@link #TYPE_ARTIST}, {@link #TYPE_ALBUM}, {@link #TYPE_SONG}
|
||||
* @param song requested song
|
||||
* @param mType media type e.g. {@link #TYPE_ARTIST}
|
||||
* @return ID of media type, {@link #TYPE_INVALID} if unsupported
|
||||
*/
|
||||
public static long getCurrentIdForType(Song song, int mType)
|
||||
{
|
||||
if(song == null)
|
||||
return TYPE_INVALID;
|
||||
|
||||
switch(mType) {
|
||||
case TYPE_ARTIST:
|
||||
return song.artistId;
|
||||
case TYPE_ALBUM:
|
||||
return song.albumId;
|
||||
case TYPE_SONG:
|
||||
return song.id;
|
||||
default:
|
||||
return TYPE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -68,4 +68,5 @@ public class PrefDefaults {
|
||||
public static final int VOLUME_DURING_DUCKING = 50;
|
||||
public static final int AUTOPLAYLIST_PLAYCOUNTS = 0;
|
||||
public static final boolean IGNORE_AUDIOFOCUS_LOSS = false;
|
||||
public static final boolean ENABLE_SCROLL_TO_SONG = false;
|
||||
}
|
||||
|
@ -24,7 +24,7 @@
|
||||
package ch.blinkenlights.android.vanilla;
|
||||
|
||||
/**
|
||||
* SharedPreference keys. Must be kept in sync with PrefDefaults.java.
|
||||
* SharedPreference keys. Must be kept in sync with {@link PrefDefaults}.
|
||||
*/
|
||||
public class PrefKeys {
|
||||
public static final String COVER_LONGPRESS_ACTION = "cover_longpress_action";
|
||||
@ -69,4 +69,5 @@ public class PrefKeys {
|
||||
public static final String VOLUME_DURING_DUCKING = "volume_during_ducking";
|
||||
public static final String AUTOPLAYLIST_PLAYCOUNTS = "playcounts_autoplaylist";
|
||||
public static final String IGNORE_AUDIOFOCUS_LOSS = "ignore_audiofocus_loss";
|
||||
public static final String ENABLE_SCROLL_TO_SONG = "enable_scroll_to_song";
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user