Add multiselection
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
* Copyright (c) 2015 David Schulte
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package de.arcus.framework.utils;
|
||||
|
||||
import android.support.annotation.ColorRes;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.support.v7.view.ActionMode;
|
||||
import android.view.View;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Selection list
|
||||
*/
|
||||
public class SelectionList<T> {
|
||||
/**
|
||||
* The selected items
|
||||
*/
|
||||
private List<T> mItems = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* The activity
|
||||
* We need the activity to show the action mode when some items are selected
|
||||
*/
|
||||
private ActionBarActivity mActivity;
|
||||
|
||||
/**
|
||||
* The action mode
|
||||
*/
|
||||
private ActionMode mActionMode;
|
||||
|
||||
/**
|
||||
* The callback for the action mode
|
||||
*/
|
||||
private ActionMode.Callback mActionModeCallback;
|
||||
|
||||
/**
|
||||
* The colors
|
||||
*/
|
||||
private @ColorRes int mResColorNormal;
|
||||
private @ColorRes int mResColorSelected;
|
||||
|
||||
/**
|
||||
* Sets the colors of the view.
|
||||
* Use @SuppressWarnings("ResourceAsColor") to prevent Lint errors
|
||||
* @param colorNormal Normal state
|
||||
* @param colorSelected Selected state
|
||||
*/
|
||||
public void setColor(@ColorRes int colorNormal, @ColorRes int colorSelected) {
|
||||
mResColorNormal = colorNormal;
|
||||
mResColorSelected = colorSelected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the action mode for this selection list
|
||||
* @param activity The activity
|
||||
*/
|
||||
public void setupActionMode(ActionBarActivity activity, ActionMode.Callback callback) {
|
||||
mActivity = activity;
|
||||
mActionModeCallback = callback;
|
||||
|
||||
// Updates the action mode
|
||||
updateActionModeMenu();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the selection state of the item
|
||||
* @param item The item
|
||||
* @param state The selection state
|
||||
*/
|
||||
public void setSelected(T item, boolean state) {
|
||||
// Adds the item to the selection list
|
||||
if (state && !mItems.contains(item))
|
||||
mItems.add(item);
|
||||
|
||||
// Removes the item from the selection list
|
||||
if (!state && mItems.contains(item))
|
||||
mItems.remove(item);
|
||||
|
||||
// Updates the action mode
|
||||
updateActionModeMenu();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the selection state of the item and change the item background
|
||||
* @param item The item
|
||||
* @param state The selection state
|
||||
* @param view The view
|
||||
*/
|
||||
public void setSelected(T item, boolean state, View view) {
|
||||
// Set the selection state
|
||||
setSelected(item, state);
|
||||
|
||||
// Change the background
|
||||
if (state)
|
||||
view.setBackgroundColor(view.getResources().getColor(mResColorSelected));
|
||||
else
|
||||
view.setBackgroundColor(view.getResources().getColor(mResColorNormal));
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the item
|
||||
* @param item The selected item
|
||||
* @return Returns whether the item is now selected
|
||||
*/
|
||||
public boolean toggle(T item) {
|
||||
boolean state = isSelected(item);
|
||||
|
||||
setSelected(item, !state);
|
||||
|
||||
return !state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the item
|
||||
* @param item The selected item
|
||||
* @param view The view
|
||||
* @return Returns whether the item is now selected
|
||||
*/
|
||||
public boolean toggle(T item, View view) {
|
||||
boolean state = isSelected(item);
|
||||
|
||||
setSelected(item, !state, view);
|
||||
|
||||
return !state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all selected items
|
||||
* @return Returns a list with all selected items
|
||||
*/
|
||||
public List<T> getSelectedItems() {
|
||||
return mItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the selection
|
||||
*/
|
||||
public void clear() {
|
||||
mItems.clear();
|
||||
|
||||
// Updates the action mode
|
||||
updateActionModeMenu();
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this after the view was created.
|
||||
* This will change the background color.
|
||||
* @param item The selected item
|
||||
* @param view The view
|
||||
*/
|
||||
public void initView(T item, View view) {
|
||||
// Change the background
|
||||
if (isSelected(item))
|
||||
view.setBackgroundColor(view.getResources().getColor(mResColorSelected));
|
||||
else
|
||||
view.setBackgroundColor(view.getResources().getColor(mResColorNormal));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the action mode menu
|
||||
*/
|
||||
private void updateActionModeMenu() {
|
||||
// Null check
|
||||
if (mActionModeCallback != null && mActivity != null && !mActivity.isFinishing()) {
|
||||
|
||||
// Some items are selected, shows the action mode
|
||||
if (mItems.size() > 0 && mActionMode == null) {
|
||||
mActionMode = mActivity.startSupportActionMode(mActionModeCallback);
|
||||
}
|
||||
|
||||
// Close the action mode
|
||||
if (mItems.size() == 0 && mActionMode != null) {
|
||||
// Set mActionMode to null before call finish to prevent recursion
|
||||
ActionMode actionMode = mActionMode;
|
||||
mActionMode = null;
|
||||
|
||||
// Close the action mode
|
||||
actionMode.finish();
|
||||
}
|
||||
|
||||
// Set the text
|
||||
if (mActionMode != null) {
|
||||
mActionMode.setTitle("TEST: " + mItems.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the item is selected
|
||||
* @param item The selected item
|
||||
* @return Returns true if the item is selected
|
||||
*/
|
||||
public boolean isSelected(T item) {
|
||||
return mItems.contains(item);
|
||||
}
|
||||
|
||||
}
|
|
@ -30,6 +30,7 @@
|
|||
android:allowBackup="true"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme" >
|
||||
<activity
|
||||
android:name=".activitys.MusicTrackListActivity"
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright (c) 2015 David Schulte
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package de.arcus.playmusicexporter2.actionmode;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v7.view.ActionMode;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import de.arcus.playmusicexporter2.R;
|
||||
import de.arcus.playmusicexporter2.items.SelectedTrack;
|
||||
|
||||
/**
|
||||
* Action mode for selected tracks
|
||||
*/
|
||||
public class ActionModeTitle implements ActionMode.Callback {
|
||||
/**
|
||||
* The context
|
||||
*/
|
||||
private Context mContext;
|
||||
|
||||
public ActionModeTitle(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
// Called when the action mode is created; startActionMode() was called
|
||||
@Override
|
||||
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
||||
// Inflate a menu resource providing context menu items
|
||||
MenuInflater inflater = mode.getMenuInflater();
|
||||
inflater.inflate(R.menu.action_mode_selection, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Called each time the action mode is shown. Always called after onCreateActionMode, but
|
||||
// may be called multiple times if the mode is invalidated.
|
||||
@Override
|
||||
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
|
||||
return false; // Return false if nothing is done
|
||||
}
|
||||
|
||||
// Called when the user selects a contextual menu item
|
||||
@Override
|
||||
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_export:
|
||||
|
||||
// Export all selected tracks
|
||||
for(SelectedTrack selectedTrack : SelectedTrack.getSelectionList().getSelectedItems()) {
|
||||
selectedTrack.export(mContext);
|
||||
}
|
||||
|
||||
mode.finish();
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Called when the user exits the action mode
|
||||
@Override
|
||||
public void onDestroyActionMode(ActionMode mode) {
|
||||
// Clears the selection
|
||||
SelectedTrack.getSelectionList().clear();
|
||||
}
|
||||
|
||||
}
|
|
@ -31,6 +31,8 @@ import android.view.MenuItem;
|
|||
import de.arcus.framework.crashhandler.CrashHandler;
|
||||
import de.arcus.playmusicexporter2.R;
|
||||
import de.arcus.playmusicexporter2.fragments.MusicTrackDetailFragment;
|
||||
import de.arcus.playmusiclib.PlayMusicManager;
|
||||
import de.arcus.playmusiclib.items.MusicTrackList;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -69,12 +71,25 @@ public class MusicTrackDetailActivity extends ActionBarActivity {
|
|||
// using a fragment transaction.
|
||||
Bundle arguments = new Bundle();
|
||||
|
||||
arguments.putLong(MusicTrackDetailFragment.ARG_MUSIC_TRACK_LIST_ID,
|
||||
getIntent().getLongExtra(MusicTrackDetailFragment.ARG_MUSIC_TRACK_LIST_ID, 0));
|
||||
// Loads the track list
|
||||
long id = getIntent().getLongExtra(MusicTrackDetailFragment.ARG_MUSIC_TRACK_LIST_ID, 0);
|
||||
String type = getIntent().getStringExtra(MusicTrackDetailFragment.ARG_MUSIC_TRACK_LIST_TYPE);
|
||||
|
||||
arguments.putString(MusicTrackDetailFragment.ARG_MUSIC_TRACK_LIST_TYPE,
|
||||
getIntent().getStringExtra(MusicTrackDetailFragment.ARG_MUSIC_TRACK_LIST_TYPE));
|
||||
|
||||
PlayMusicManager playMusicManager = PlayMusicManager.getInstance();
|
||||
if (playMusicManager != null) {
|
||||
MusicTrackList musicTrackList = MusicTrackList.deserialize(playMusicManager, id, type);
|
||||
|
||||
// Sets the title
|
||||
setTitle(musicTrackList.getTitle());
|
||||
}
|
||||
|
||||
// Puts the track list information to the fragment
|
||||
arguments.putLong(MusicTrackDetailFragment.ARG_MUSIC_TRACK_LIST_ID, id);
|
||||
arguments.putString(MusicTrackDetailFragment.ARG_MUSIC_TRACK_LIST_TYPE, type);
|
||||
|
||||
|
||||
// Loads the fragment
|
||||
MusicTrackDetailFragment fragment = new MusicTrackDetailFragment();
|
||||
fragment.setArguments(arguments);
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
|
|
|
@ -34,6 +34,7 @@ import android.widget.TextView;
|
|||
import java.util.List;
|
||||
|
||||
import de.arcus.playmusicexporter2.R;
|
||||
import de.arcus.playmusicexporter2.items.SelectedTrack;
|
||||
import de.arcus.playmusicexporter2.utils.ImageViewLoader;
|
||||
import de.arcus.playmusiclib.items.MusicTrack;
|
||||
|
||||
|
@ -131,10 +132,10 @@ public class MusicTrackAdapter extends ArrayAdapter<MusicTrack> {
|
|||
// Shows the artwork
|
||||
if (mShowArtworks) {
|
||||
ImageView imageView = (ImageView) view.findViewById(R.id.image_music_track_artwork);
|
||||
imageView.setImageResource(R.drawable.cd_case);
|
||||
|
||||
String artworkPath = musicTrack.getArtworkPath();
|
||||
if (artworkPath != null)
|
||||
ImageViewLoader.loadImage(imageView, artworkPath);
|
||||
|
||||
ImageViewLoader.loadImage(imageView, artworkPath, R.drawable.cd_case);
|
||||
}
|
||||
|
||||
// Sets the title
|
||||
|
@ -150,6 +151,9 @@ public class MusicTrackAdapter extends ArrayAdapter<MusicTrack> {
|
|||
// Track is available?
|
||||
view.setEnabled(musicTrack.isOfflineAvailable());
|
||||
|
||||
// Selected state
|
||||
SelectedTrack.getSelectionList().initView(new SelectedTrack(musicTrack.getId()), view);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
|
|
|
@ -90,17 +90,11 @@ public class MusicTrackListAdapter extends ArrayAdapter<MusicTrackList> {
|
|||
// Final for the callback
|
||||
imageView = (ImageView)view.findViewById(R.id.image_music_track_artwork);
|
||||
|
||||
// Default icon
|
||||
imageView.setImageResource(R.drawable.cd_case);
|
||||
|
||||
// Gets the artwork
|
||||
String artworkPath = musicTrackList.getArtworkPath();
|
||||
|
||||
if (artworkPath != null) {
|
||||
ImageViewLoader.loadImage(imageView, artworkPath);
|
||||
}
|
||||
|
||||
|
||||
// Loads the artwork
|
||||
ImageViewLoader.loadImage(imageView, artworkPath, R.drawable.cd_case);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
|
|
@ -22,10 +22,10 @@
|
|||
|
||||
package de.arcus.playmusicexporter2.fragments;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
@ -35,8 +35,9 @@ import android.widget.ListView;
|
|||
import android.widget.TextView;
|
||||
|
||||
import de.arcus.playmusicexporter2.R;
|
||||
import de.arcus.playmusicexporter2.actionmode.ActionModeTitle;
|
||||
import de.arcus.playmusicexporter2.adapter.MusicTrackAdapter;
|
||||
import de.arcus.playmusicexporter2.services.ExportService;
|
||||
import de.arcus.playmusicexporter2.items.SelectedTrack;
|
||||
import de.arcus.playmusicexporter2.utils.ImageViewLoader;
|
||||
import de.arcus.playmusicexporter2.utils.MusicPathBuilder;
|
||||
import de.arcus.playmusiclib.PlayMusicManager;
|
||||
|
@ -87,6 +88,9 @@ public class MusicTrackDetailFragment extends Fragment {
|
|||
mMusicTrackList = MusicTrackList.deserialize(playMusicManager, id, type);
|
||||
}
|
||||
}
|
||||
|
||||
// Setup the selection list for this activity
|
||||
SelectedTrack.getSelectionList().setupActionMode((ActionBarActivity)getActivity(), new ActionModeTitle(getActivity()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -109,10 +113,11 @@ public class MusicTrackDetailFragment extends Fragment {
|
|||
|
||||
// Sets the artwork image
|
||||
imageView = (ImageView)headerView.findViewById(R.id.image_music_track_artwork);
|
||||
imageView.setImageResource(R.drawable.cd_case);
|
||||
|
||||
String artworkPath = mMusicTrackList.getArtworkPath();
|
||||
if (artworkPath != null)
|
||||
ImageViewLoader.loadImage(imageView, artworkPath);
|
||||
|
||||
// Loads the artwork
|
||||
ImageViewLoader.loadImage(imageView, artworkPath, R.drawable.cd_case);
|
||||
|
||||
// Sets the title
|
||||
textView = (TextView)headerView.findViewById(R.id.text_music_track_list_title);
|
||||
|
@ -132,6 +137,7 @@ public class MusicTrackDetailFragment extends Fragment {
|
|||
listView.setItemsCanFocus(false);
|
||||
|
||||
|
||||
// Click on one list item
|
||||
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
|
@ -145,23 +151,15 @@ public class MusicTrackDetailFragment extends Fragment {
|
|||
|
||||
// Track is available
|
||||
if (musicTrack.isOfflineAvailable()) {
|
||||
|
||||
// Build the path
|
||||
String path = MusicPathBuilder.Build(musicTrack, "{album-artist}/{album}/{disc=CD $}/{no=$$.} {title}.mp3");
|
||||
|
||||
// Path to the public music folder
|
||||
path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC) + "/" + path;
|
||||
|
||||
|
||||
Intent intent = new Intent(MusicTrackDetailFragment.this.getActivity(), ExportService.class);
|
||||
|
||||
// Puts the export parameter
|
||||
intent.putExtra(ExportService.ARG_EXPORT_TRACK_ID, musicTrack.getId());
|
||||
intent.putExtra(ExportService.ARG_EXPORT_PATH, path);
|
||||
|
||||
// Starts the service
|
||||
MusicTrackDetailFragment.this.getActivity().startService(intent);
|
||||
//playMusicManager.exportMusicTrack(musicTrack, path);
|
||||
|
||||
// Toggles the music track
|
||||
SelectedTrack.getSelectionList().toggle(new SelectedTrack(musicTrack.getId(), path), view);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright (c) 2015 David Schulte
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package de.arcus.playmusicexporter2.items;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import de.arcus.playmusicexporter2.R;
|
||||
import de.arcus.playmusicexporter2.services.ExportService;
|
||||
import de.arcus.framework.utils.SelectionList;
|
||||
|
||||
/**
|
||||
* The selected track
|
||||
*/
|
||||
public class SelectedTrack {
|
||||
/**
|
||||
* The instance of the selection
|
||||
*/
|
||||
private static SelectionList<SelectedTrack> selectionList;
|
||||
|
||||
/**
|
||||
* Gets the latest instance of the track selection.
|
||||
* Creates a new one if it doesn't exist.
|
||||
* @return The instance
|
||||
*/
|
||||
@SuppressWarnings("ResourceAsColor")
|
||||
public static SelectionList<SelectedTrack> getSelectionList() {
|
||||
// Create a new instance
|
||||
if (selectionList == null) {
|
||||
selectionList = new SelectionList<>();
|
||||
|
||||
// Sets the color resources
|
||||
selectionList.setColor(R.color.button_navigation_drawer_normal, R.color.button_navigation_drawer_selected);
|
||||
}
|
||||
|
||||
return selectionList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Type of the track
|
||||
*/
|
||||
private long mId;
|
||||
|
||||
/**
|
||||
* The path of the track
|
||||
*/
|
||||
private String mPath;
|
||||
|
||||
public SelectedTrack(long id) {
|
||||
mId = id;
|
||||
}
|
||||
|
||||
public SelectedTrack(long id, String path) {
|
||||
mId = id;
|
||||
mPath = path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the track to the export list
|
||||
*/
|
||||
public void export(Context context) {
|
||||
Intent intent = new Intent(context, ExportService.class);
|
||||
|
||||
// Puts the export parameter
|
||||
intent.putExtra(ExportService.ARG_EXPORT_TRACK_ID, mId);
|
||||
intent.putExtra(ExportService.ARG_EXPORT_PATH, mPath);
|
||||
|
||||
// Starts the service
|
||||
context.startService(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
// Compares two selected tracks
|
||||
if (o instanceof SelectedTrack) {
|
||||
SelectedTrack other = (SelectedTrack)o;
|
||||
|
||||
return mId == other.mId;
|
||||
}
|
||||
|
||||
return super.equals(o);
|
||||
}
|
||||
}
|
|
@ -24,6 +24,7 @@ package de.arcus.playmusicexporter2.utils;
|
|||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
@ -64,6 +65,11 @@ public class ImageViewLoader {
|
|||
*/
|
||||
private String mNewImagePath;
|
||||
|
||||
/**
|
||||
* The default image of the image view
|
||||
*/
|
||||
private int mDefaultImage;
|
||||
|
||||
/**
|
||||
* @return Gets the path of the image we want to load
|
||||
*/
|
||||
|
@ -71,13 +77,14 @@ public class ImageViewLoader {
|
|||
return mImagePath;
|
||||
}
|
||||
|
||||
public static void loadImage(ImageView imageView, String path) {
|
||||
public static void loadImage(ImageView imageView, String path, int defaultImage) {
|
||||
// Checks for an old artwork loader on this image view
|
||||
ImageViewLoader imageViewLoader = (ImageViewLoader)imageView.getTag();
|
||||
|
||||
if (imageViewLoader == null) {
|
||||
imageViewLoader = new ImageViewLoader(imageView, path);
|
||||
if (path == null) path = "";
|
||||
|
||||
if (imageViewLoader == null) {
|
||||
imageViewLoader = new ImageViewLoader(imageView, path, defaultImage);
|
||||
|
||||
// Save the loader in the tag
|
||||
// If someone wants to load another artwork to this view
|
||||
|
@ -95,68 +102,85 @@ public class ImageViewLoader {
|
|||
* @param imageView The image view we want to set
|
||||
* @param path The path to load
|
||||
*/
|
||||
private ImageViewLoader(ImageView imageView, String path) {
|
||||
private ImageViewLoader(ImageView imageView, String path, int defaultImage) {
|
||||
mImageView = new WeakReference<>(imageView);
|
||||
mImagePath = path;
|
||||
mDefaultImage = defaultImage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the image asynchronously
|
||||
*/
|
||||
private void loadImage() {
|
||||
mIsLoading = true;
|
||||
// Show the default icon while loading
|
||||
final ImageView imageViewDefault = mImageView.get();
|
||||
if (imageViewDefault != null) {
|
||||
// Sets the bitmap in the UI thread
|
||||
Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Default icon
|
||||
imageViewDefault.setImageResource(mDefaultImage);
|
||||
}
|
||||
};
|
||||
imageViewDefault.post(runnable);
|
||||
}
|
||||
|
||||
// Be careful! Don't scroll to fast! This will spam the superuser to do list!
|
||||
SuperUserTools.fileReadToByteArrayAsync(mImagePath, new SuperUserCommandCallback() {
|
||||
@Override
|
||||
public void onFinished(SuperUserCommand command) {
|
||||
if (!TextUtils.isEmpty(mImagePath)) {
|
||||
mIsLoading = true;
|
||||
|
||||
final ImageView imageView = mImageView.get();
|
||||
// Be careful! Don't scroll to fast! This will spam the superuser to do list!
|
||||
SuperUserTools.fileReadToByteArrayAsync(mImagePath, new SuperUserCommandCallback() {
|
||||
@Override
|
||||
public void onFinished(SuperUserCommand command) {
|
||||
|
||||
if (imageView != null) {
|
||||
final ImageView imageView = mImageView.get();
|
||||
|
||||
// Success
|
||||
if (command.commandWasSuccessful()) {
|
||||
// Binary data
|
||||
byte[] bitmapData = command.getStandardOutputBinary();
|
||||
if (imageView != null) {
|
||||
|
||||
// Loads the bitmap
|
||||
try {
|
||||
// We already want to load a new image, so we don't need to set this
|
||||
if (mNewImagePath == null) {
|
||||
// Loads the bitmap
|
||||
final Bitmap bitmap = BitmapFactory.decodeByteArray(bitmapData, 0, bitmapData.length);
|
||||
// Success
|
||||
if (command.commandWasSuccessful()) {
|
||||
// Binary data
|
||||
byte[] bitmapData = command.getStandardOutputBinary();
|
||||
|
||||
// The the bitmap in the UI thread
|
||||
Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
imageView.setImageBitmap(bitmap);
|
||||
}
|
||||
};
|
||||
imageView.post(runnable);
|
||||
// Loads the bitmap
|
||||
try {
|
||||
// We already want to load a new image, so we don't need to set this
|
||||
if (mNewImagePath == null) {
|
||||
// Loads the bitmap
|
||||
final Bitmap bitmap = BitmapFactory.decodeByteArray(bitmapData, 0, bitmapData.length);
|
||||
|
||||
// Sets the bitmap in the UI thread
|
||||
Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
imageView.setImageBitmap(bitmap);
|
||||
}
|
||||
};
|
||||
imageView.post(runnable);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} else {
|
||||
// File not found
|
||||
imageView.setImageResource(R.drawable.cd_case);
|
||||
}
|
||||
} else {
|
||||
// File not found
|
||||
imageView.setImageResource(R.drawable.cd_case);
|
||||
}
|
||||
|
||||
mIsLoading = false;
|
||||
|
||||
// Loads the next image
|
||||
if (mNewImagePath != null) {
|
||||
mImagePath = mNewImagePath;
|
||||
mNewImagePath = null;
|
||||
|
||||
loadImage();
|
||||
}
|
||||
}
|
||||
|
||||
mIsLoading = false;
|
||||
|
||||
// Loads the next image
|
||||
if (mNewImagePath != null) {
|
||||
mImagePath = mNewImagePath;
|
||||
mNewImagePath = null;
|
||||
|
||||
loadImage();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -165,7 +189,9 @@ public class ImageViewLoader {
|
|||
*/
|
||||
private void updateImage(String path) {
|
||||
// The same artwork; nothing to do
|
||||
if (path.equals(mImagePath)) return;
|
||||
if (path.equals(mImagePath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mIsLoading) {
|
||||
mNewImagePath = path;
|
||||
|
|
BIN
playmusicexporter/src/main/res/drawable-hdpi/ic_action_play.png
Normal file
After Width: | Height: | Size: 440 B |
BIN
playmusicexporter/src/main/res/drawable-hdpi/ic_action_save.png
Normal file
After Width: | Height: | Size: 394 B |
BIN
playmusicexporter/src/main/res/drawable-hdpi/ic_action_share.png
Normal file
After Width: | Height: | Size: 513 B |
BIN
playmusicexporter/src/main/res/drawable-mdpi/ic_action_play.png
Normal file
After Width: | Height: | Size: 339 B |
BIN
playmusicexporter/src/main/res/drawable-mdpi/ic_action_save.png
Normal file
After Width: | Height: | Size: 362 B |
BIN
playmusicexporter/src/main/res/drawable-mdpi/ic_action_share.png
Normal file
After Width: | Height: | Size: 383 B |
BIN
playmusicexporter/src/main/res/drawable-xhdpi/ic_action_play.png
Normal file
After Width: | Height: | Size: 522 B |
BIN
playmusicexporter/src/main/res/drawable-xhdpi/ic_action_save.png
Normal file
After Width: | Height: | Size: 441 B |
After Width: | Height: | Size: 666 B |
After Width: | Height: | Size: 669 B |
After Width: | Height: | Size: 495 B |
After Width: | Height: | Size: 969 B |
|
@ -45,7 +45,7 @@
|
|||
android:text="1"
|
||||
android:id="@+id/text_music_track_number"
|
||||
android:gravity="center"
|
||||
android:textSize="16dp"
|
||||
android:textSize="16sp"
|
||||
android:textColor="@color/text_music_number" />
|
||||
|
||||
<TextView
|
||||
|
|
|
@ -75,5 +75,6 @@
|
|||
android:layout_alignRight="@+id/text_music_track_list_title"
|
||||
android:layout_alignEnd="@+id/text_music_track_list_title"
|
||||
android:maxLines="2" />
|
||||
|
||||
</RelativeLayout>
|
||||
</RelativeLayout>
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) 2015 David Schulte
|
||||
~
|
||||
~ Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
~ of this software and associated documentation files (the "Software"), to deal
|
||||
~ in the Software without restriction, including without limitation the rights
|
||||
~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
~ copies of the Software, and to permit persons to whom the Software is
|
||||
~ furnished to do so, subject to the following conditions:
|
||||
~
|
||||
~ The above copyright notice and this permission notice shall be included in
|
||||
~ all copies or substantial portions of the Software.
|
||||
~
|
||||
~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
~ THE SOFTWARE.
|
||||
-->
|
||||
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto/">
|
||||
<item android:id="@+id/action_export"
|
||||
android:title="@string/action_export"
|
||||
android:icon="@drawable/ic_action_save"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item android:id="@+id/action_share"
|
||||
android:title="@string/action_share"
|
||||
android:icon="@drawable/ic_action_share"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item android:id="@+id/action_play"
|
||||
android:title="@string/action_play"
|
||||
android:icon="@drawable/ic_action_play"
|
||||
app:showAsAction="ifRoom" />
|
||||
</menu>
|
|
@ -51,4 +51,8 @@
|
|||
<string name="notification_export_finished_summery">%1$d Titel wurden erfolgreich exportiert!</string>
|
||||
<string name="notification_export_finished_title">Export abgeschlossen!</string>
|
||||
<string name="search">Suchen</string>
|
||||
<string name="button_export_group">Alle Titel exportieren</string>
|
||||
<string name="action_export">Exportieren</string>
|
||||
<string name="action_play">Wiedergeben</string>
|
||||
<string name="action_share">Teilen</string>
|
||||
</resources>
|
|
@ -26,6 +26,10 @@
|
|||
<string name="app_name">Play Music Exporter</string>
|
||||
<string name="title_track_detail">Track Detail</string>
|
||||
|
||||
<string name="action_export">Export</string>
|
||||
<string name="action_play">Play</string>
|
||||
<string name="action_share">Share</string>
|
||||
|
||||
<string name="navigation_drawer_open">Open drawer</string>
|
||||
<string name="navigation_drawer_close">Close drawer</string>
|
||||
|
||||
|
@ -45,6 +49,7 @@
|
|||
<string name="notification_export_finished_single_summery">Track was exported successfully!</string>
|
||||
|
||||
<string name="search">Search</string>
|
||||
<string name="button_export_group">Export all tracks</string>
|
||||
|
||||
<string name="settings_category_export">Export settings</string>
|
||||
<string name="settings_category_extra">Extras</string>
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
<item name="colorAccent">@color/application_main</item>
|
||||
<item name="colorPrimaryDark">@color/application_main_dark</item>
|
||||
<item name="actionBarStyle">@style/AppTheme.ActionBar</item>
|
||||
<item name="actionModeBackground">@color/application_main</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.ActionBar" parent="Widget.AppCompat.Light.ActionBar.Solid.Inverse">
|
||||
|
|