Use ActionBar in library

This commit is contained in:
Christopher Eby 2012-02-01 13:38:34 -06:00
parent 6d9734803f
commit 3f870ced44
13 changed files with 329 additions and 52 deletions

View File

@ -49,7 +49,8 @@ THE SOFTWARE.
android:launchMode="singleTop" />
<activity
android:name="LibraryActivity"
android:theme="@style/NoTitle"
android:theme="@style/Library"
android:uiOptions="splitActionBarWhenNarrow"
android:launchMode="singleTop" />
<activity
android:name="PlaylistActivity"

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2012 Christopher Eby <kreed@kreed.org>
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.
-->
<org.kreed.vanilla.ActionBarControls
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="?android:attr/selectableItemBackground"
android:clickable="true">
<ImageView
android:id="@+id/cover"
android:scaleType="fitCenter"
android:layout_marginLeft="5dip"
android:layout_width="36dip"
android:layout_height="36dip"
android:layout_gravity="center" />
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_marginLeft="5dip"
android:layout_gravity="center_horizontal"
android:orientation="vertical">
<TextView
android:id="@+id/title"
android:textSize="14sp"
android:singleLine="true"
android:gravity="center_vertical"
android:ellipsize="marquee"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/artist"
android:textSize="12sp"
android:singleLine="true"
android:gravity="center_vertical"
android:ellipsize="marquee"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</org.kreed.vanilla.ActionBarControls>

View File

@ -26,10 +26,6 @@ THE SOFTWARE.
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.viewpagerindicator.TabPageIndicator
android:id="@+id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="fill_parent"

View File

@ -26,4 +26,10 @@ THE SOFTWARE.
<style name="AlertDialogItem">
<item name="android:textColor">?android:textColorAlertDialogListItem</item>
</style>
<style name="Library" parent="Theme">
<item name="android:actionBarStyle">@style/LibraryActionBar</item>
</style>
<style name="LibraryActionBar" parent="android:Widget.Holo.ActionBar">
<item name="android:displayOptions"></item>
</style>
</resources>

View File

@ -23,7 +23,7 @@ THE SOFTWARE.
<resources>
<style name="Dialog" parent="android:Theme.Dialog" />
<style name="Theme" parent="android:Theme" />
<style name="NoTitle" parent="Theme">
<style name="Library" parent="Theme">
<item name="android:windowNoTitle">true</item>
</style>
<style name="NoBackground" parent="Theme">

View File

@ -0,0 +1,61 @@
/*
* Copyright (C) 2012 Christopher Eby <kreed@kreed.org>
*
* 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 org.kreed.vanilla;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ViewGroup;
import android.widget.LinearLayout;
/**
* LinearLayout that contains some hacks for sizing inside an ActionBar.
*/
public class ActionBarControls extends LinearLayout {
public ActionBarControls(Context context, AttributeSet attrs)
{
super(context, attrs);
}
@Override
public void onMeasure(int ws, int hs)
{
super.onMeasure(ws, hs);
float density = getResources().getDisplayMetrics().density;
int width = MeasureSpec.getSize(ws);
int widthMode = MeasureSpec.getMode(ws);
if (widthMode != MeasureSpec.EXACTLY)
width = (int)(200 * density);
setMeasuredDimension(width, (int)(40 * density));
ViewGroup.LayoutParams lp = getLayoutParams();
try {
lp.getClass().getField("expandable").set(lp, true);
} catch (Exception e) {
Log.d("VanillaMusic", "Failed to set controls expandable", e);
}
}
}

View File

@ -0,0 +1,121 @@
/*
* Copyright (C) 2012 Christopher Eby <kreed@kreed.org>
*
* 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 org.kreed.vanilla;
import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.Activity;
import android.app.FragmentTransaction;
import android.view.MenuItem;
import android.view.View;
/**
* Framework methods only in Honeycomb or above go here.
*/
public class CompatHoneycomb implements ActionBar.TabListener {
/**
* The LibraryActivity to callback to when a tab is selected.
*/
private final LibraryActivity mActivity;
private CompatHoneycomb(LibraryActivity activity)
{
mActivity = activity;
}
/**
* Add ActionBar tabs for LibraryActivity.
*
* @param activity The activity to add to.
* @return The custom view in the ActionBar (for current song info).
*/
public static View addActionBarTabs(LibraryActivity activity)
{
ActionBar ab = activity.getActionBar();
CompatHoneycomb listener = new CompatHoneycomb(activity);
ab.addTab(ab.newTab()
.setText(R.string.artists)
.setTabListener(listener));
ab.addTab(ab.newTab()
.setText(R.string.albums)
.setTabListener(listener));
ab.addTab(ab.newTab()
.setText(R.string.songs)
.setTabListener(listener));
ab.addTab(ab.newTab()
.setText(R.string.playlists)
.setTabListener(listener));
ab.addTab(ab.newTab()
.setText(R.string.genres)
.setTabListener(listener));
ab.addTab(ab.newTab()
.setText(R.string.files)
.setTabListener(listener));
ab.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
return ab.getCustomView();
}
/**
* Call {@link MenuItem#setActionView(View)} on the given MenuItem.
*/
public static void setActionView(MenuItem item, View view)
{
item.setActionView(view);
}
/**
* Call {@link MenuItem#setShowAsAction(int)} on the given MenuItem.
*/
public static void setShowAsAction(MenuItem item, int mode)
{
item.setShowAsAction(mode);
}
/**
* Select the ActionBar tab at the given position.
*
* @param activity The activity that owns the ActionBar.
* @param position The tab's position.
*/
public static void selectTab(Activity activity, int position)
{
ActionBar ab = activity.getActionBar();
ab.selectTab(ab.getTabAt(position));
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft)
{
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft)
{
mActivity.mViewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft)
{
}
}

View File

@ -163,6 +163,8 @@ public class FullPlaybackActivity extends PlaybackActivity
setControlsVisible(settings.getBoolean("visible_controls", true));
setDuration(0);
getWindow().addFlags(0x08000000); // show menu key on ICS
}
@Override

View File

@ -34,6 +34,7 @@ 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;
@ -46,16 +47,15 @@ import android.text.TextWatcher;
import android.util.Log;
import android.view.ContextMenu;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.HorizontalScrollView;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RadioGroup;
@ -88,12 +88,13 @@ public class LibraryActivity
{ SongTimeline.MODE_PLAY, SongTimeline.MODE_ENQUEUE, -1,
SongTimeline.MODE_PLAY_ID_FIRST, SongTimeline.MODE_ENQUEUE_ID_FIRST };
private ViewPager mViewPager;
public ViewPager mViewPager;
private View mSearchBox;
private boolean mSearchBoxVisible;
private TextView mTextFilter;
private View mClearButton;
private View mActionControls;
private View mControls;
private TextView mTitle;
private TextView mArtist;
@ -253,36 +254,6 @@ public class LibraryActivity
MediaView.init(this);
setContentView(R.layout.library_content);
SharedPreferences settings = PlaybackService.getSettings(this);
if (settings.getBoolean("controls_in_selector", false)) {
ViewGroup content = (ViewGroup)findViewById(R.id.content);
LayoutInflater.from(this).inflate(R.layout.library_controls, content, true);
mControls = findViewById(R.id.controls);
mTitle = (TextView)mControls.findViewById(R.id.title);
mArtist = (TextView)mControls.findViewById(R.id.artist);
mCover = (ImageView)mControls.findViewById(R.id.cover);
View previous = mControls.findViewById(R.id.previous);
mPlayPauseButton = (ImageButton)mControls.findViewById(R.id.play_pause);
View next = mControls.findViewById(R.id.next);
mCover.setOnClickListener(this);
previous.setOnClickListener(this);
mPlayPauseButton.setOnClickListener(this);
next.setOnClickListener(this);
mShuffleButton = (ImageButton)findViewById(R.id.shuffle);
mShuffleButton.setOnClickListener(this);
registerForContextMenu(mShuffleButton);
mEndButton = (ImageButton)findViewById(R.id.end_action);
mEndButton.setOnClickListener(this);
registerForContextMenu(mEndButton);
mEmptyQueue = findViewById(R.id.empty_queue);
mEmptyQueue.setOnClickListener(this);
}
mSearchBox = findViewById(R.id.search_box);
mTextFilter = (TextView)findViewById(R.id.filter_text);
@ -297,9 +268,53 @@ public class LibraryActivity
mViewPager = (ViewPager)findViewById(R.id.pager);
mViewPager.setAdapter(mPagerAdapter);
TabPageIndicator tabs = (TabPageIndicator)findViewById(R.id.tabs);
tabs.setViewPager(mViewPager);
tabs.setOnPageChangeListener(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
CompatHoneycomb.addActionBarTabs(this);
mViewPager.setOnPageChangeListener(this);
View controls = getLayoutInflater().inflate(R.layout.actionbar_controls, null);
mTitle = (TextView)controls.findViewById(R.id.title);
mArtist = (TextView)controls.findViewById(R.id.artist);
mCover = (ImageView)controls.findViewById(R.id.cover);
controls.setOnClickListener(this);
mActionControls = controls;
} else {
TabPageIndicator tabs = new TabPageIndicator(this);
tabs.setViewPager(mViewPager);
tabs.setOnPageChangeListener(this);
LinearLayout content = (LinearLayout)findViewById(R.id.content);
content.addView(tabs, 0, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
SharedPreferences settings = PlaybackService.getSettings(this);
if (settings.getBoolean("controls_in_selector", false)) {
getLayoutInflater().inflate(R.layout.library_controls, content, true);
mControls = findViewById(R.id.controls);
mTitle = (TextView)mControls.findViewById(R.id.title);
mArtist = (TextView)mControls.findViewById(R.id.artist);
mCover = (ImageView)mControls.findViewById(R.id.cover);
View previous = mControls.findViewById(R.id.previous);
mPlayPauseButton = (ImageButton)mControls.findViewById(R.id.play_pause);
View next = mControls.findViewById(R.id.next);
mCover.setOnClickListener(this);
previous.setOnClickListener(this);
mPlayPauseButton.setOnClickListener(this);
next.setOnClickListener(this);
mShuffleButton = (ImageButton)findViewById(R.id.shuffle);
mShuffleButton.setOnClickListener(this);
registerForContextMenu(mShuffleButton);
mEndButton = (ImageButton)findViewById(R.id.end_action);
mEndButton.setOnClickListener(this);
registerForContextMenu(mEndButton);
mEmptyQueue = findViewById(R.id.empty_queue);
mEmptyQueue.setOnClickListener(this);
}
}
getContentResolver().registerContentObserver(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI, true, mPlaylistObserver);
@ -445,8 +460,8 @@ public class LibraryActivity
int mode = action;
if (action == ACTION_PLAY_ALL || action == ACTION_ENQUEUE_ALL) {
LibraryAdapter adapter = mCurrentAdapter;
boolean notPlayAllAdapter = (adapter != mSongAdapter && adapter != mAlbumAdapter
&& adapter != mArtistAdapter) || id == MediaView.HEADER_ID;
boolean notPlayAllAdapter = adapter != mSongAdapter && adapter != mAlbumAdapter
&& adapter != mArtistAdapter || id == MediaView.HEADER_ID;
if (mode == ACTION_ENQUEUE_ALL && notPlayAllAdapter) {
mode = ACTION_ENQUEUE;
} else if (mode == ACTION_PLAY_ALL && notPlayAllAdapter) {
@ -607,7 +622,7 @@ public class LibraryActivity
MediaView mediaView = (MediaView)view;
LibraryAdapter adapter = (LibraryAdapter)list.getAdapter();
int action = mDefaultAction;
if (mediaView.isRightBitmapPressed() || (action == ACTION_EXPAND && mediaView.hasRightBitmap())) {
if (mediaView.isRightBitmapPressed() || action == ACTION_EXPAND && mediaView.hasRightBitmap()) {
if (adapter == mPlaylistAdapter)
editPlaylist(mediaView.getMediaId(), mediaView.getTitle());
else
@ -688,7 +703,7 @@ public class LibraryActivity
setSearchBoxVisible(false);
else
mTextFilter.setText("");
} else if (view == mCover) {
} else if (view == mCover || view == mActionControls) {
openPlaybackActivity();
} else if (view == mEmptyQueue) {
setState(PlaybackService.get(this).setFinishAction(SongTimeline.FINISH_RANDOM));
@ -971,8 +986,16 @@ public class LibraryActivity
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
menu.addSubMenu(0, MENU_SORT, 0, R.string.sort_by).setIcon(R.drawable.ic_menu_sort_alphabetically);
menu.add(0, MENU_SEARCH, 0, R.string.search).setIcon(R.drawable.ic_menu_search);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
MenuItem controls = menu.add(null);
CompatHoneycomb.setActionView(controls, mActionControls);
CompatHoneycomb.setShowAsAction(controls, MenuItem.SHOW_AS_ACTION_ALWAYS);
MenuItem search = menu.add(0, MENU_SEARCH, 0, R.string.search).setIcon(R.drawable.ic_menu_search);
CompatHoneycomb.setShowAsAction(search, MenuItem.SHOW_AS_ACTION_ALWAYS);
} else {
menu.add(0, MENU_SEARCH, 0, R.string.search).setIcon(R.drawable.ic_menu_search);
}
menu.add(0, MENU_SORT, 0, R.string.sort_by).setIcon(R.drawable.ic_menu_sort_alphabetically);
menu.add(0, MENU_PLAYBACK, 0, R.string.playback_view).setIcon(R.drawable.ic_menu_gallery);
return super.onCreateOptionsMenu(menu);
}
@ -1204,7 +1227,7 @@ public class LibraryActivity
}
@Override
protected void onSongChange(final Song song)
protected void onSongChange(Song song)
{
super.onSongChange(song);
@ -1212,8 +1235,15 @@ public class LibraryActivity
Bitmap cover = null;
if (song == null) {
mTitle.setText(R.string.none);
mArtist.setText(null);
if (mActionControls == null) {
mTitle.setText(R.string.none);
mArtist.setText(null);
} else {
mTitle.setText(null);
mArtist.setText(null);
mCover.setImageDrawable(null);
return;
}
} else {
Resources res = getResources();
String title = song.title == null ? res.getString(R.string.unknown) : song.title;
@ -1310,5 +1340,9 @@ public class LibraryActivity
if (position > 0)
requeryIfNeeded(position - 1);
updateLimiterViews();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
CompatHoneycomb.selectTab(this, position);
}
}
}

View File

@ -158,7 +158,6 @@ public class PlaybackActivity extends Activity
window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
else
window.clearFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
window.addFlags(0x08000000); // show menu key on ICS
}
@Override