Removed search button on main tab, it was redundant, added Exit button. Removed Help and Settings from remaining tabs. Start redesign of the Download tab
This commit is contained in:
parent
feca33c9ac
commit
97890e8929
|
@ -189,12 +189,13 @@
|
||||||
a:layout_alignParentLeft="true"
|
a:layout_alignParentLeft="true"
|
||||||
a:layout_toLeftOf="@+id/download_control_layout"
|
a:layout_toLeftOf="@+id/download_control_layout"
|
||||||
>
|
>
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
a:id="@+id/download_album_art_layout"
|
a:id="@+id/download_album_art_layout"
|
||||||
a:layout_width="fill_parent"
|
a:layout_width="fill_parent"
|
||||||
a:layout_height="fill_parent"
|
a:layout_height="fill_parent"
|
||||||
a:background="@drawable/album_art_background">
|
a:background="@drawable/pinstripe_tile" >
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
a:id="@+id/download_album_art_image"
|
a:id="@+id/download_album_art_image"
|
||||||
a:layout_width="wrap_content"
|
a:layout_width="wrap_content"
|
||||||
|
|
|
@ -9,14 +9,14 @@
|
||||||
a:layout_width="fill_parent"
|
a:layout_width="fill_parent"
|
||||||
a:layout_height="0dip"
|
a:layout_height="0dip"
|
||||||
a:layout_weight="1">
|
a:layout_weight="1">
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
a:id="@+id/download_album_art_layout"
|
a:id="@+id/download_album_art_layout"
|
||||||
a:orientation="vertical"
|
a:layout_width="fill_parent"
|
||||||
a:layout_width="fill_parent"
|
a:layout_height="fill_parent"
|
||||||
a:layout_height="fill_parent"
|
a:layout_weight="1"
|
||||||
a:layout_weight="1"
|
a:background="@drawable/pinstripe_tile"
|
||||||
a:background="@drawable/album_art_background">
|
a:orientation="vertical" >
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
a:id="@+id/download_repeat"
|
a:id="@+id/download_repeat"
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
a:scaleType="center"
|
a:scaleType="center"
|
||||||
a:showAsAction="ifRoom|withText"
|
a:showAsAction="ifRoom|withText"
|
||||||
a:src="@drawable/ic_menu_help" />
|
a:src="@drawable/ic_menu_help" />
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
a:id="@+id/action_button_4"
|
a:id="@+id/action_button_4"
|
||||||
a:layout_width="wrap_content"
|
a:layout_width="wrap_content"
|
||||||
|
@ -63,8 +63,8 @@
|
||||||
a:padding="5dp"
|
a:padding="5dp"
|
||||||
a:scaleType="center"
|
a:scaleType="center"
|
||||||
a:showAsAction="ifRoom|withText"
|
a:showAsAction="ifRoom|withText"
|
||||||
a:src="@drawable/ic_menu_settings" />
|
a:src="@drawable/ic_menu_exit" />
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
a:id="@+id/action_button_1"
|
a:id="@+id/action_button_1"
|
||||||
a:layout_width="wrap_content"
|
a:layout_width="wrap_content"
|
||||||
|
@ -75,8 +75,8 @@
|
||||||
a:padding="5dp"
|
a:padding="5dp"
|
||||||
a:scaleType="center"
|
a:scaleType="center"
|
||||||
a:showAsAction="ifRoom|withText"
|
a:showAsAction="ifRoom|withText"
|
||||||
a:src="@drawable/ic_menu_search" />
|
a:src="@drawable/ic_menu_shuffle" />
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
a:id="@+id/action_button_2"
|
a:id="@+id/action_button_2"
|
||||||
a:layout_width="wrap_content"
|
a:layout_width="wrap_content"
|
||||||
|
@ -87,6 +87,6 @@
|
||||||
a:padding="5dp"
|
a:padding="5dp"
|
||||||
a:scaleType="center"
|
a:scaleType="center"
|
||||||
a:showAsAction="ifRoom|withText"
|
a:showAsAction="ifRoom|withText"
|
||||||
a:src="@drawable/ic_menu_shuffle" />
|
a:src="@drawable/ic_menu_settings" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
|
@ -118,20 +118,8 @@ public class MainActivity extends SubsonicTabActivity {
|
||||||
// Title: Subsonic
|
// Title: Subsonic
|
||||||
setTitle(R.string.common_appname);
|
setTitle(R.string.common_appname);
|
||||||
|
|
||||||
// Button 1: search
|
// Button 1: shuffle
|
||||||
ImageButton actionSearchButton = (ImageButton)findViewById(R.id.action_button_1);
|
ImageButton actionShuffleButton = (ImageButton)findViewById(R.id.action_button_1);
|
||||||
actionSearchButton.setImageResource(R.drawable.ic_menu_search);
|
|
||||||
actionSearchButton.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
Intent intent = new Intent(MainActivity.this, SearchActivity.class);
|
|
||||||
intent.putExtra(Constants.INTENT_EXTRA_REQUEST_SEARCH, true);
|
|
||||||
Util.startActivityWithoutTransition(MainActivity.this, intent);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Button 2: shuffle
|
|
||||||
ImageButton actionShuffleButton = (ImageButton)findViewById(R.id.action_button_2);
|
|
||||||
actionShuffleButton.setImageResource(R.drawable.ic_menu_shuffle);
|
actionShuffleButton.setImageResource(R.drawable.ic_menu_shuffle);
|
||||||
actionShuffleButton.setOnClickListener(new View.OnClickListener() {
|
actionShuffleButton.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -141,7 +129,17 @@ public class MainActivity extends SubsonicTabActivity {
|
||||||
Util.startActivityWithoutTransition(MainActivity.this, intent);
|
Util.startActivityWithoutTransition(MainActivity.this, intent);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Button 2: settings
|
||||||
|
ImageButton actionSettingsButton = (ImageButton)findViewById(R.id.action_button_2);
|
||||||
|
actionSettingsButton.setImageResource(R.drawable.ic_menu_settings);
|
||||||
|
actionSettingsButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
startActivity(new Intent(MainActivity.this, SettingsActivity.class));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Button 3: help
|
// Button 3: help
|
||||||
ImageButton actionHelpButton = (ImageButton)findViewById(R.id.action_button_3);
|
ImageButton actionHelpButton = (ImageButton)findViewById(R.id.action_button_3);
|
||||||
actionHelpButton.setImageResource(R.drawable.ic_menu_help);
|
actionHelpButton.setImageResource(R.drawable.ic_menu_help);
|
||||||
|
@ -151,14 +149,14 @@ public class MainActivity extends SubsonicTabActivity {
|
||||||
startActivity(new Intent(MainActivity.this, HelpActivity.class));
|
startActivity(new Intent(MainActivity.this, HelpActivity.class));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Button 4: settings
|
// Button 4: exit
|
||||||
ImageButton actionSettingsButton = (ImageButton)findViewById(R.id.action_button_4);
|
ImageButton actionSearchButton = (ImageButton)findViewById(R.id.action_button_4);
|
||||||
actionSettingsButton.setImageResource(R.drawable.ic_menu_settings);
|
actionSearchButton.setImageResource(R.drawable.ic_menu_exit);
|
||||||
actionSettingsButton.setOnClickListener(new View.OnClickListener() {
|
actionSearchButton.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
startActivity(new Intent(MainActivity.this, SettingsActivity.class));
|
exit();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -138,8 +138,14 @@ public class SearchActivity extends SubsonicTabActivity {
|
||||||
// Button 1: gone
|
// Button 1: gone
|
||||||
findViewById(R.id.action_button_1).setVisibility(View.GONE);
|
findViewById(R.id.action_button_1).setVisibility(View.GONE);
|
||||||
|
|
||||||
// Button 2: search
|
// Button 2: gone
|
||||||
final ImageButton actionSearchButton = (ImageButton)findViewById(R.id.action_button_2);
|
findViewById(R.id.action_button_2).setVisibility(View.GONE);
|
||||||
|
|
||||||
|
// Button 3: gone
|
||||||
|
findViewById(R.id.action_button_3).setVisibility(View.GONE);
|
||||||
|
|
||||||
|
// Button 4: search
|
||||||
|
final ImageButton actionSearchButton = (ImageButton)findViewById(R.id.action_button_4);
|
||||||
actionSearchButton.setImageResource(R.drawable.ic_menu_search);
|
actionSearchButton.setImageResource(R.drawable.ic_menu_search);
|
||||||
actionSearchButton.setOnClickListener(new View.OnClickListener() {
|
actionSearchButton.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -147,26 +153,6 @@ public class SearchActivity extends SubsonicTabActivity {
|
||||||
onSearchRequested();
|
onSearchRequested();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Button 3: help
|
|
||||||
ImageButton actionHelpButton = (ImageButton)findViewById(R.id.action_button_3);
|
|
||||||
actionHelpButton.setImageResource(R.drawable.ic_menu_help);
|
|
||||||
actionHelpButton.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
startActivity(new Intent(SearchActivity.this, HelpActivity.class));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Button 4: settings
|
|
||||||
ImageButton actionSettingsButton = (ImageButton)findViewById(R.id.action_button_4);
|
|
||||||
actionSettingsButton.setImageResource(R.drawable.ic_menu_settings);
|
|
||||||
actionSettingsButton.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
startActivity(new Intent(SearchActivity.this, SettingsActivity.class));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
onNewIntent(getIntent());
|
onNewIntent(getIntent());
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,8 +170,14 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
|
||||||
getMusicDirectory(id, name);
|
getMusicDirectory(id, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Button 1: play all
|
// Button 1: gone
|
||||||
playAllButton = (ImageButton) findViewById(R.id.action_button_1);
|
findViewById(R.id.action_button_1).setVisibility(View.GONE);
|
||||||
|
|
||||||
|
// Button 2: gone
|
||||||
|
findViewById(R.id.action_button_2).setVisibility(View.GONE);
|
||||||
|
|
||||||
|
// Button 3: play all
|
||||||
|
playAllButton = (ImageButton) findViewById(R.id.action_button_3);
|
||||||
playAllButton.setImageResource(R.drawable.ic_menu_play_all);
|
playAllButton.setImageResource(R.drawable.ic_menu_play_all);
|
||||||
playAllButton.setVisibility(View.GONE);
|
playAllButton.setVisibility(View.GONE);
|
||||||
playAllButton.setOnClickListener(new View.OnClickListener() {
|
playAllButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@ -181,8 +187,8 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Button 2: refresh
|
// Button 4: refresh
|
||||||
ImageButton refreshButton = (ImageButton) findViewById(R.id.action_button_2);
|
ImageButton refreshButton = (ImageButton) findViewById(R.id.action_button_4);
|
||||||
refreshButton.setImageResource(R.drawable.ic_menu_refresh);
|
refreshButton.setImageResource(R.drawable.ic_menu_refresh);
|
||||||
refreshButton.setOnClickListener(new View.OnClickListener() {
|
refreshButton.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -190,26 +196,6 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Button 3: help
|
|
||||||
ImageButton actionHelpButton = (ImageButton)findViewById(R.id.action_button_3);
|
|
||||||
actionHelpButton.setImageResource(R.drawable.ic_menu_help);
|
|
||||||
actionHelpButton.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
startActivity(new Intent(SelectAlbumActivity.this, HelpActivity.class));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Button 4: settings
|
|
||||||
ImageButton actionSettingsButton = (ImageButton)findViewById(R.id.action_button_4);
|
|
||||||
actionSettingsButton.setImageResource(R.drawable.ic_menu_settings);
|
|
||||||
actionSettingsButton.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
startActivity(new Intent(SelectAlbumActivity.this, SettingsActivity.class));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void playAll() {
|
private void playAll() {
|
||||||
|
|
|
@ -76,8 +76,14 @@ public class SelectArtistActivity extends SubsonicTabActivity implements Adapter
|
||||||
|
|
||||||
setTitle(Util.isOffline(this) ? R.string.music_library_label_offline : R.string.music_library_label);
|
setTitle(Util.isOffline(this) ? R.string.music_library_label_offline : R.string.music_library_label);
|
||||||
|
|
||||||
// Button 1: shuffle
|
// Button 1: gone
|
||||||
ImageButton shuffleButton = (ImageButton) findViewById(R.id.action_button_1);
|
findViewById(R.id.action_button_1).setVisibility(View.GONE);
|
||||||
|
|
||||||
|
// Button 2: gone
|
||||||
|
findViewById(R.id.action_button_2).setVisibility(View.GONE);
|
||||||
|
|
||||||
|
// Button 3: shuffle
|
||||||
|
ImageButton shuffleButton = (ImageButton) findViewById(R.id.action_button_3);
|
||||||
shuffleButton.setImageResource(R.drawable.ic_menu_shuffle);
|
shuffleButton.setImageResource(R.drawable.ic_menu_shuffle);
|
||||||
shuffleButton.setOnClickListener(new View.OnClickListener() {
|
shuffleButton.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -88,8 +94,8 @@ public class SelectArtistActivity extends SubsonicTabActivity implements Adapter
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Button 2: refresh
|
// Button 4: refresh
|
||||||
ImageButton refreshButton = (ImageButton) findViewById(R.id.action_button_2);
|
ImageButton refreshButton = (ImageButton) findViewById(R.id.action_button_4);
|
||||||
refreshButton.setImageResource(R.drawable.ic_menu_refresh);
|
refreshButton.setImageResource(R.drawable.ic_menu_refresh);
|
||||||
refreshButton.setOnClickListener(new View.OnClickListener() {
|
refreshButton.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -97,26 +103,8 @@ public class SelectArtistActivity extends SubsonicTabActivity implements Adapter
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Button 3: help
|
|
||||||
ImageButton actionHelpButton = (ImageButton)findViewById(R.id.action_button_3);
|
|
||||||
actionHelpButton.setImageResource(R.drawable.ic_menu_help);
|
|
||||||
actionHelpButton.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
startActivity(new Intent(SelectArtistActivity.this, HelpActivity.class));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Button 4: settings
|
|
||||||
ImageButton actionSettingsButton = (ImageButton)findViewById(R.id.action_button_4);
|
|
||||||
actionSettingsButton.setImageResource(R.drawable.ic_menu_settings);
|
|
||||||
actionSettingsButton.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
startActivity(new Intent(SelectArtistActivity.this, SettingsActivity.class));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
musicFolders = null;
|
musicFolders = null;
|
||||||
load();
|
load();
|
||||||
|
|
|
@ -60,12 +60,17 @@ public class SelectPlaylistActivity extends SubsonicTabActivity implements Adapt
|
||||||
// Title: Playlists
|
// Title: Playlists
|
||||||
setTitle(R.string.playlist_label);
|
setTitle(R.string.playlist_label);
|
||||||
|
|
||||||
// Button 1: gone
|
// Button 1: gone
|
||||||
ImageButton searchButton = (ImageButton)findViewById(R.id.action_button_1);
|
findViewById(R.id.action_button_1).setVisibility(View.GONE);
|
||||||
searchButton.setVisibility(View.GONE);
|
|
||||||
|
|
||||||
// Button 2: refresh
|
// Button 2: gone
|
||||||
ImageButton refreshButton = (ImageButton) findViewById(R.id.action_button_2);
|
findViewById(R.id.action_button_2).setVisibility(View.GONE);
|
||||||
|
|
||||||
|
// Button 3: gone
|
||||||
|
findViewById(R.id.action_button_3).setVisibility(View.GONE);
|
||||||
|
|
||||||
|
// Button 4: refresh
|
||||||
|
ImageButton refreshButton = (ImageButton) findViewById(R.id.action_button_4);
|
||||||
refreshButton.setImageResource(R.drawable.ic_menu_refresh);
|
refreshButton.setImageResource(R.drawable.ic_menu_refresh);
|
||||||
refreshButton.setOnClickListener(new View.OnClickListener() {
|
refreshButton.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -73,26 +78,6 @@ public class SelectPlaylistActivity extends SubsonicTabActivity implements Adapt
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Button 3: help
|
|
||||||
ImageButton actionHelpButton = (ImageButton)findViewById(R.id.action_button_3);
|
|
||||||
actionHelpButton.setImageResource(R.drawable.ic_menu_help);
|
|
||||||
actionHelpButton.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
startActivity(new Intent(SelectPlaylistActivity.this, HelpActivity.class));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Button 4: settings
|
|
||||||
ImageButton actionSettingsButton = (ImageButton)findViewById(R.id.action_button_4);
|
|
||||||
actionSettingsButton.setImageResource(R.drawable.ic_menu_settings);
|
|
||||||
actionSettingsButton.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
startActivity(new Intent(SelectPlaylistActivity.this, SettingsActivity.class));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
load();
|
load();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,252 +1,253 @@
|
||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
|
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Copyright 2009 (C) Sindre Mehus
|
Copyright 2009 (C) Sindre Mehus
|
||||||
*/
|
*/
|
||||||
package net.sourceforge.subsonic.androidapp.util;
|
package net.sourceforge.subsonic.androidapp.util;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.LinearGradient;
|
import android.graphics.LinearGradient;
|
||||||
import android.graphics.Matrix;
|
import android.graphics.Matrix;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.Shader;
|
import android.graphics.Shader;
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.graphics.drawable.TransitionDrawable;
|
import android.graphics.drawable.TransitionDrawable;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import net.sourceforge.subsonic.androidapp.R;
|
import net.sourceforge.subsonic.androidapp.R;
|
||||||
import net.sourceforge.subsonic.androidapp.domain.MusicDirectory;
|
import net.sourceforge.subsonic.androidapp.domain.MusicDirectory;
|
||||||
import net.sourceforge.subsonic.androidapp.service.MusicService;
|
import net.sourceforge.subsonic.androidapp.service.MusicService;
|
||||||
import net.sourceforge.subsonic.androidapp.service.MusicServiceFactory;
|
import net.sourceforge.subsonic.androidapp.service.MusicServiceFactory;
|
||||||
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asynchronous loading of images, with caching.
|
* Asynchronous loading of images, with caching.
|
||||||
* <p/>
|
* <p/>
|
||||||
* There should normally be only one instance of this class.
|
* There should normally be only one instance of this class.
|
||||||
*
|
*
|
||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
*/
|
*/
|
||||||
public class ImageLoader implements Runnable {
|
public class ImageLoader implements Runnable {
|
||||||
|
|
||||||
private static final String TAG = ImageLoader.class.getSimpleName();
|
private static final String TAG = ImageLoader.class.getSimpleName();
|
||||||
private static final int CONCURRENCY = 5;
|
private static final int CONCURRENCY = 5;
|
||||||
|
|
||||||
private final LRUCache<String, Drawable> cache = new LRUCache<String, Drawable>(100);
|
private final LRUCache<String, Drawable> cache = new LRUCache<String, Drawable>(100);
|
||||||
private final BlockingQueue<Task> queue;
|
private final BlockingQueue<Task> queue;
|
||||||
private final int imageSizeDefault;
|
private final int imageSizeDefault;
|
||||||
private final int imageSizeLarge;
|
private final int imageSizeLarge;
|
||||||
private Drawable largeUnknownImage;
|
private Drawable largeUnknownImage;
|
||||||
|
|
||||||
public ImageLoader(Context context) {
|
public ImageLoader(Context context) {
|
||||||
queue = new LinkedBlockingQueue<Task>(500);
|
queue = new LinkedBlockingQueue<Task>(500);
|
||||||
|
|
||||||
// Determine the density-dependent image sizes.
|
// Determine the density-dependent image sizes.
|
||||||
imageSizeDefault = context.getResources().getDrawable(R.drawable.unknown_album).getIntrinsicHeight();
|
imageSizeDefault = context.getResources().getDrawable(R.drawable.unknown_album).getIntrinsicHeight();
|
||||||
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
|
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
|
||||||
imageSizeLarge = (int) Math.round(Math.min(metrics.widthPixels, metrics.heightPixels) * 0.6);
|
/*imageSizeLarge = (int) Math.round(Math.min(metrics.widthPixels, metrics.heightPixels) * 0.6);*/
|
||||||
|
imageSizeLarge = (int) Math.round(Math.min(metrics.widthPixels, metrics.heightPixels));
|
||||||
for (int i = 0; i < CONCURRENCY; i++) {
|
|
||||||
new Thread(this, "ImageLoader").start();
|
for (int i = 0; i < CONCURRENCY; i++) {
|
||||||
}
|
new Thread(this, "ImageLoader").start();
|
||||||
|
}
|
||||||
createLargeUnknownImage(context);
|
|
||||||
}
|
createLargeUnknownImage(context);
|
||||||
|
}
|
||||||
private void createLargeUnknownImage(Context context) {
|
|
||||||
BitmapDrawable drawable = (BitmapDrawable) context.getResources().getDrawable(R.drawable.unknown_album_large);
|
private void createLargeUnknownImage(Context context) {
|
||||||
Bitmap bitmap = Bitmap.createScaledBitmap(drawable.getBitmap(), imageSizeLarge, imageSizeLarge, true);
|
BitmapDrawable drawable = (BitmapDrawable) context.getResources().getDrawable(R.drawable.unknown_album_large);
|
||||||
bitmap = createReflection(bitmap);
|
Bitmap bitmap = Bitmap.createScaledBitmap(drawable.getBitmap(), imageSizeLarge, imageSizeLarge, true);
|
||||||
largeUnknownImage = Util.createDrawableFromBitmap(context, bitmap);
|
bitmap = createReflection(bitmap);
|
||||||
}
|
largeUnknownImage = Util.createDrawableFromBitmap(context, bitmap);
|
||||||
|
}
|
||||||
public void loadImage(View view, MusicDirectory.Entry entry, boolean large, boolean crossfade) {
|
|
||||||
if (entry == null || entry.getCoverArt() == null) {
|
public void loadImage(View view, MusicDirectory.Entry entry, boolean large, boolean crossfade) {
|
||||||
setUnknownImage(view, large);
|
if (entry == null || entry.getCoverArt() == null) {
|
||||||
return;
|
setUnknownImage(view, large);
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
int size = large ? imageSizeLarge : imageSizeDefault;
|
|
||||||
Drawable drawable = cache.get(getKey(entry.getCoverArt(), size));
|
int size = large ? imageSizeLarge : imageSizeDefault;
|
||||||
if (drawable != null) {
|
Drawable drawable = cache.get(getKey(entry.getCoverArt(), size));
|
||||||
setImage(view, drawable, large);
|
if (drawable != null) {
|
||||||
return;
|
setImage(view, drawable, large);
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
if (!large) {
|
|
||||||
setUnknownImage(view, large);
|
if (!large) {
|
||||||
}
|
setUnknownImage(view, large);
|
||||||
queue.offer(new Task(view, entry, size, large, large, crossfade));
|
}
|
||||||
}
|
queue.offer(new Task(view, entry, size, false, large, crossfade));
|
||||||
|
}
|
||||||
private String getKey(String coverArtId, int size) {
|
|
||||||
return coverArtId + size;
|
private String getKey(String coverArtId, int size) {
|
||||||
}
|
return coverArtId + size;
|
||||||
|
}
|
||||||
private void setImage(View view, Drawable drawable, boolean crossfade) {
|
|
||||||
if (view instanceof TextView) {
|
private void setImage(View view, Drawable drawable, boolean crossfade) {
|
||||||
// Cross-fading is not implemented for TextView since it's not in use. It would be easy to add it, though.
|
if (view instanceof TextView) {
|
||||||
TextView textView = (TextView) view;
|
// Cross-fading is not implemented for TextView since it's not in use. It would be easy to add it, though.
|
||||||
textView.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
|
TextView textView = (TextView) view;
|
||||||
} else if (view instanceof ImageView) {
|
textView.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
|
||||||
ImageView imageView = (ImageView) view;
|
} else if (view instanceof ImageView) {
|
||||||
if (crossfade) {
|
ImageView imageView = (ImageView) view;
|
||||||
|
if (crossfade) {
|
||||||
Drawable existingDrawable = imageView.getDrawable();
|
|
||||||
if (existingDrawable == null) {
|
Drawable existingDrawable = imageView.getDrawable();
|
||||||
Bitmap emptyImage = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
|
if (existingDrawable == null) {
|
||||||
existingDrawable = new BitmapDrawable(emptyImage);
|
Bitmap emptyImage = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
|
||||||
}
|
existingDrawable = new BitmapDrawable(emptyImage);
|
||||||
|
}
|
||||||
Drawable[] layers = new Drawable[]{existingDrawable, drawable};
|
|
||||||
|
Drawable[] layers = new Drawable[]{existingDrawable, drawable};
|
||||||
TransitionDrawable transitionDrawable = new TransitionDrawable(layers);
|
|
||||||
imageView.setImageDrawable(transitionDrawable);
|
TransitionDrawable transitionDrawable = new TransitionDrawable(layers);
|
||||||
transitionDrawable.startTransition(250);
|
imageView.setImageDrawable(transitionDrawable);
|
||||||
} else {
|
transitionDrawable.startTransition(250);
|
||||||
imageView.setImageDrawable(drawable);
|
} else {
|
||||||
}
|
imageView.setImageDrawable(drawable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private void setUnknownImage(View view, boolean large) {
|
|
||||||
if (large) {
|
private void setUnknownImage(View view, boolean large) {
|
||||||
setImage(view, largeUnknownImage, false);
|
if (large) {
|
||||||
} else {
|
setImage(view, largeUnknownImage, false);
|
||||||
if (view instanceof TextView) {
|
} else {
|
||||||
((TextView) view).setCompoundDrawablesWithIntrinsicBounds(R.drawable.unknown_album, 0, 0, 0);
|
if (view instanceof TextView) {
|
||||||
} else if (view instanceof ImageView) {
|
((TextView) view).setCompoundDrawablesWithIntrinsicBounds(R.drawable.unknown_album, 0, 0, 0);
|
||||||
((ImageView) view).setImageResource(R.drawable.unknown_album);
|
} else if (view instanceof ImageView) {
|
||||||
}
|
((ImageView) view).setImageResource(R.drawable.unknown_album);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public void clear() {
|
|
||||||
queue.clear();
|
public void clear() {
|
||||||
}
|
queue.clear();
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public void run() {
|
@Override
|
||||||
while (true) {
|
public void run() {
|
||||||
try {
|
while (true) {
|
||||||
Task task = queue.take();
|
try {
|
||||||
task.execute();
|
Task task = queue.take();
|
||||||
} catch (Throwable x) {
|
task.execute();
|
||||||
Log.e(TAG, "Unexpected exception in ImageLoader.", x);
|
} catch (Throwable x) {
|
||||||
}
|
Log.e(TAG, "Unexpected exception in ImageLoader.", x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private Bitmap createReflection(Bitmap originalImage) {
|
|
||||||
|
private Bitmap createReflection(Bitmap originalImage) {
|
||||||
int width = originalImage.getWidth();
|
|
||||||
int height = originalImage.getHeight();
|
int width = originalImage.getWidth();
|
||||||
|
int height = originalImage.getHeight();
|
||||||
// The gap we want between the reflection and the original image
|
|
||||||
final int reflectionGap = 4;
|
// The gap we want between the reflection and the original image
|
||||||
|
final int reflectionGap = 4;
|
||||||
// This will not scale but will flip on the Y axis
|
|
||||||
Matrix matrix = new Matrix();
|
// This will not scale but will flip on the Y axis
|
||||||
matrix.preScale(1, -1);
|
Matrix matrix = new Matrix();
|
||||||
|
matrix.preScale(1, -1);
|
||||||
// Create a Bitmap with the flip matix applied to it.
|
|
||||||
// We only want the bottom half of the image
|
// Create a Bitmap with the flip matix applied to it.
|
||||||
Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0, height / 2, width, height / 2, matrix, false);
|
// We only want the bottom half of the image
|
||||||
|
Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0, height / 2, width, height / 2, matrix, false);
|
||||||
// Create a new bitmap with same width but taller to fit reflection
|
|
||||||
Bitmap bitmapWithReflection = Bitmap.createBitmap(width, (height + height / 2), Bitmap.Config.ARGB_8888);
|
// Create a new bitmap with same width but taller to fit reflection
|
||||||
|
Bitmap bitmapWithReflection = Bitmap.createBitmap(width, (height + height / 2), Bitmap.Config.ARGB_8888);
|
||||||
// Create a new Canvas with the bitmap that's big enough for
|
|
||||||
// the image plus gap plus reflection
|
// Create a new Canvas with the bitmap that's big enough for
|
||||||
Canvas canvas = new Canvas(bitmapWithReflection);
|
// the image plus gap plus reflection
|
||||||
|
Canvas canvas = new Canvas(bitmapWithReflection);
|
||||||
// Draw in the original image
|
|
||||||
canvas.drawBitmap(originalImage, 0, 0, null);
|
// Draw in the original image
|
||||||
|
canvas.drawBitmap(originalImage, 0, 0, null);
|
||||||
// Draw in the gap
|
|
||||||
Paint defaultPaint = new Paint();
|
// Draw in the gap
|
||||||
canvas.drawRect(0, height, width, height + reflectionGap, defaultPaint);
|
Paint defaultPaint = new Paint();
|
||||||
|
canvas.drawRect(0, height, width, height + reflectionGap, defaultPaint);
|
||||||
// Draw in the reflection
|
|
||||||
canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);
|
// Draw in the reflection
|
||||||
|
canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);
|
||||||
// Create a shader that is a linear gradient that covers the reflection
|
|
||||||
Paint paint = new Paint();
|
// Create a shader that is a linear gradient that covers the reflection
|
||||||
LinearGradient shader = new LinearGradient(0, originalImage.getHeight(), 0,
|
Paint paint = new Paint();
|
||||||
bitmapWithReflection.getHeight() + reflectionGap, 0x70000000, 0xff000000,
|
LinearGradient shader = new LinearGradient(0, originalImage.getHeight(), 0,
|
||||||
Shader.TileMode.CLAMP);
|
bitmapWithReflection.getHeight() + reflectionGap, 0x70000000, 0xff000000,
|
||||||
|
Shader.TileMode.CLAMP);
|
||||||
// Set the paint to use this shader (linear gradient)
|
|
||||||
paint.setShader(shader);
|
// Set the paint to use this shader (linear gradient)
|
||||||
|
paint.setShader(shader);
|
||||||
// Draw a rectangle using the paint with our linear gradient
|
|
||||||
canvas.drawRect(0, height, width, bitmapWithReflection.getHeight() + reflectionGap, paint);
|
// Draw a rectangle using the paint with our linear gradient
|
||||||
|
canvas.drawRect(0, height, width, bitmapWithReflection.getHeight() + reflectionGap, paint);
|
||||||
return bitmapWithReflection;
|
|
||||||
}
|
return bitmapWithReflection;
|
||||||
|
}
|
||||||
private class Task {
|
|
||||||
private final View view;
|
private class Task {
|
||||||
private final MusicDirectory.Entry entry;
|
private final View view;
|
||||||
private final Handler handler;
|
private final MusicDirectory.Entry entry;
|
||||||
private final int size;
|
private final Handler handler;
|
||||||
private final boolean reflection;
|
private final int size;
|
||||||
private final boolean saveToFile;
|
private final boolean reflection;
|
||||||
private final boolean crossfade;
|
private final boolean saveToFile;
|
||||||
|
private final boolean crossfade;
|
||||||
public Task(View view, MusicDirectory.Entry entry, int size, boolean reflection, boolean saveToFile, boolean crossfade) {
|
|
||||||
this.view = view;
|
public Task(View view, MusicDirectory.Entry entry, int size, boolean reflection, boolean saveToFile, boolean crossfade) {
|
||||||
this.entry = entry;
|
this.view = view;
|
||||||
this.size = size;
|
this.entry = entry;
|
||||||
this.reflection = reflection;
|
this.size = size;
|
||||||
this.saveToFile = saveToFile;
|
this.reflection = reflection;
|
||||||
this.crossfade = crossfade;
|
this.saveToFile = saveToFile;
|
||||||
handler = new Handler();
|
this.crossfade = crossfade;
|
||||||
}
|
handler = new Handler();
|
||||||
|
}
|
||||||
public void execute() {
|
|
||||||
try {
|
public void execute() {
|
||||||
MusicService musicService = MusicServiceFactory.getMusicService(view.getContext());
|
try {
|
||||||
Bitmap bitmap = musicService.getCoverArt(view.getContext(), entry, size, saveToFile, null);
|
MusicService musicService = MusicServiceFactory.getMusicService(view.getContext());
|
||||||
|
Bitmap bitmap = musicService.getCoverArt(view.getContext(), entry, size, saveToFile, null);
|
||||||
if (reflection) {
|
|
||||||
bitmap = createReflection(bitmap);
|
if (reflection) {
|
||||||
}
|
bitmap = createReflection(bitmap);
|
||||||
|
}
|
||||||
final Drawable drawable = Util.createDrawableFromBitmap(view.getContext(), bitmap);
|
|
||||||
cache.put(getKey(entry.getCoverArt(), size), drawable);
|
final Drawable drawable = Util.createDrawableFromBitmap(view.getContext(), bitmap);
|
||||||
|
cache.put(getKey(entry.getCoverArt(), size), drawable);
|
||||||
handler.post(new Runnable() {
|
|
||||||
@Override
|
handler.post(new Runnable() {
|
||||||
public void run() {
|
@Override
|
||||||
setImage(view, drawable, crossfade);
|
public void run() {
|
||||||
}
|
setImage(view, drawable, crossfade);
|
||||||
});
|
}
|
||||||
} catch (Throwable x) {
|
});
|
||||||
Log.e(TAG, "Failed to download album art.", x);
|
} catch (Throwable x) {
|
||||||
}
|
Log.e(TAG, "Failed to download album art.", x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue