squashed merge of hacky-bottom branch

This commit is contained in:
Adrian Ulrich 2016-01-07 09:16:24 +01:00
parent 34076dc9a2
commit dc45137eee
30 changed files with 453 additions and 225 deletions

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:color="@android:color/primary_text_dark" />
<item android:color="@android:color/primary_text_dark" android:alpha="0.65" />
<item android:state_selected="true" android:color="@android:color/background_light" />
<item android:color="@android:color/background_light" android:alpha="0.65" />
</selector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 B

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 396 B

After

Width:  |  Height:  |  Size: 396 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 B

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 247 B

After

Width:  |  Height:  |  Size: 247 B

View File

@ -0,0 +1,25 @@
<!--
Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2c-1.1,0 -2,0.9 -2,2S10.9,8 12,8zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2c1.1,0 2,-0.9 2,-2S13.1,10 12,10zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2c1.1,0 2,-0.9 2,-2S13.1,16 12,16z"
android:fillColor="@android:color/white"/>
</vector>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- holo style menu button drawable -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/ic_menu_search_material" />
</selector>

View File

@ -0,0 +1,3 @@
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#30ffffff" >
</ripple>

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

View File

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

Before

Width:  |  Height:  |  Size: 465 B

After

Width:  |  Height:  |  Size: 465 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 728 B

After

Width:  |  Height:  |  Size: 728 B

View File

Before

Width:  |  Height:  |  Size: 915 B

After

Width:  |  Height:  |  Size: 915 B

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- holo style menu button drawable -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/ic_menu_moreoverflow_normal_holo_dark" />
</selector>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- holo style menu button drawable -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/ic_menu_search_holo" />
</selector>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- holo style selector for pre-ripple devices -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@android:color/holo_blue_dark" />
</selector>

View File

@ -1,62 +0,0 @@
<?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.
-->
<ch.blinkenlights.android.vanilla.ActionBarControls
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="?android:attr/selectableItemBackground"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
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"
android:contentDescription="@string/cover_art" />
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_marginLeft="5dip"
android:layout_gravity="center"
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:textColor="@android:color/primary_text_dark"
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:textColor="@android:color/secondary_text_dark"
android:layout_height="wrap_content" />
</LinearLayout>
</ch.blinkenlights.android.vanilla.ActionBarControls>

View File

@ -0,0 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2016 Adrian Ulrich <adrian@blinkenlights.ch>
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.
-->
<ch.blinkenlights.android.vanilla.BottomBarControls
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@color/tabs_background"
android:elevation="8dp"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<LinearLayout
android:layout_height="@dimen/row_normal_height"
android:layout_width="fill_parent"
android:background="@drawable/unbound_ripple_light"
android:gravity="center_vertical"
android:id="@+id/content_controls">
<ImageView
android:id="@+id/cover"
android:scaleType="centerCrop"
android:layout_width="@dimen/cover_size"
android:layout_height="@dimen/cover_size"
android:layout_marginLeft="@dimen/cover_padding"
android:layout_gravity="center_vertical"
android:contentDescription="@string/cover_art" />
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="0px"
android:layout_weight="1"
android:layout_marginLeft="@dimen/text_padding"
android:layout_gravity="center"
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:textColor="@android:color/background_light"
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:textColor="@android:color/secondary_text_dark"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
<SearchView
android:visibility="gone"
android:layout_height="@dimen/row_normal_height"
android:layout_width="fill_parent"
android:iconifiedByDefault="false"
android:imeOptions="actionSearch|flagNoFullscreen"
android:id="@+id/search_view" />
</ch.blinkenlights.android.vanilla.BottomBarControls>

View File

@ -31,6 +31,7 @@ THE SOFTWARE.
android:id="@+id/sliding_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="4dp"
android:background="@color/tabs_background" />
<android.support.v4.view.ViewPager
@ -49,6 +50,7 @@ THE SOFTWARE.
android:layout_width="wrap_content"
android:layout_height="fill_parent" />
</HorizontalScrollView>
<include layout="@layout/bottombar_controls" android:id="@+id/bottombar_controls" />
<include layout="@layout/permission_request" />
</LinearLayout>

View File

@ -23,7 +23,7 @@
<!-- library tabs -->
<color name="tabs_background">@color/vanillaPrimary</color>
<color name="tabs_active_indicator">@android:color/primary_text_dark</color>
<color name="tabs_active_indicator">@android:color/background_light</color>
<!-- themed overlay colors for full playback activity -->
<color name="overlay_background_light">#ffeeeeee</color>

View File

@ -39,7 +39,8 @@ Copyright (C) 2015 Adrian Ulrich <adrian@blinkenlights.ch>
</style>
<style name="Library" parent="VanillaBase">
<item name="android:actionBarStyle">@style/Universal.LibraryActionBar</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
</style>
<!-- universal styles -->
@ -48,11 +49,6 @@ Copyright (C) 2015 Adrian Ulrich <adrian@blinkenlights.ch>
<item name="android:background">@color/vanillaPrimary</item>
</style>
<style name="Universal.LibraryActionBar" parent="android:Widget.Material.ActionBar">
<item name="android:displayOptions"></item>
<item name="android:background">@color/vanillaPrimary</item>
</style>
<!-- dark theme -->
<style name="Dark.VanillaBase" parent="android:Theme.Material">
@ -73,7 +69,8 @@ Copyright (C) 2015 Adrian Ulrich <adrian@blinkenlights.ch>
</style>
<style name="Dark.Library" parent="Dark.VanillaBase">
<item name="android:actionBarStyle">@style/Universal.LibraryActionBar</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
</style>

View File

@ -46,10 +46,8 @@ THE SOFTWARE.
<item name="android:displayOptions">showTitle|homeAsUp</item>
</style>
<style name="Library" parent="VanillaBase">
<item name="android:actionBarStyle">@style/LibraryActionBar</item>
</style>
<style name="LibraryActionBar" parent="android:Widget.Holo.ActionBar">
<item name="android:displayOptions"></item>
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
</style>
</resources>

View File

@ -23,8 +23,6 @@ import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.TextView;
import android.os.Build;
/**
* Simple wrapper for SlidingTabLayout which takes
* care of setting sane per-platform defaults
@ -52,26 +50,11 @@ public class VanillaTabLayout extends SlidingTabLayout {
protected TextView createDefaultTabView(Context context) {
TextView view = super.createDefaultTabView(context);
view.setTextColor(getResources().getColorStateList(ch.blinkenlights.android.vanilla.R.color.tab_text_selector));
view.setBackgroundResource(ch.blinkenlights.android.vanilla.R.drawable.unbound_ripple_light);
view.setMaxLines(1);
view.setEllipsize(TextUtils.TruncateAt.END);
view.setTextSize(14);
return view;
}
/**
* Borrow elevation of given action bar
*
* @param ab The active action bar
*/
public void inheritElevation(ActionBar ab) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
return; // noop on earlier releases
float elevation = ab.getElevation();
ab.setElevation(0.0f);
setElevation(elevation);
}
}

View File

@ -1,70 +0,0 @@
/*
* Copyright (C) 2015 Adrian Ulrich <adrian@blinkenlights.ch>
*
* 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 ch.blinkenlights.android.vanilla;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.LinearLayout;
import android.os.Build;
import android.util.DisplayMetrics;
/**
* LinearLayout that contains some hacks for sizing inside an ActionBar.
*/
public class ActionBarControls extends LinearLayout {
private final int dpiElementLp = 52; // Size of the ActionBarSearch icon in 5.x (50 + some slack)
private final int dpiElementHolo = 64; // Size of the ActionBarSearch icon in HOLO
private final int dpiMaxWidth = 350; // Never use more then 350 DPIs
private final int visibleElements = 2; // The ActionBarSearch + Menu icons are visible
public ActionBarControls(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void onMeasure(int ws, int hs) {
super.onMeasure(ws, hs);
final float density = getResources().getDisplayMetrics().density;
final int dpiElement = ( android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? dpiElementLp : dpiElementHolo );
int widthMode = MeasureSpec.getMode(ws);
if (widthMode != MeasureSpec.EXACTLY) {
float dpiAvailable = (getSmallestAxisPx() / density) - (dpiElement * visibleElements);
if (dpiAvailable > dpiMaxWidth || dpiAvailable < 1) {
dpiAvailable = dpiMaxWidth;
}
setMeasuredDimension((int)(dpiAvailable * density), (int)(dpiElement * density));
}
}
/**
* Returns the smaller axis of the display dimensions
* @return The dimension of the smaller axis in pixels
*/
private final int getSmallestAxisPx() {
DisplayMetrics metrics = getResources().getDisplayMetrics();
return (metrics.widthPixels > metrics.heightPixels ? metrics.heightPixels : metrics.widthPixels);
}
}

View File

@ -0,0 +1,283 @@
/*
* Copyright (C) 2016 Adrian Ulrich <adrian@blinkenlights.ch>
*
* 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 ch.blinkenlights.android.vanilla;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.graphics.Bitmap;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupMenu;
import android.widget.SearchView;
import android.widget.TextView;
public class BottomBarControls extends LinearLayout
implements View.OnClickListener
, PopupMenu.OnMenuItemClickListener
{
/**
* The application context
*/
private final Context mContext;
/**
* The title of the currently playing song
*/
private TextView mTitle;
/**
* The artist of the currently playing song
*/
private TextView mArtist;
/**
* Cover image
*/
private ImageView mCover;
/**
* A layout hosting the song information
*/
private LinearLayout mControlsContent;
/**
* Standard android search view
*/
private SearchView mSearchView;
/**
* ControlsContent click consumer, may be null
*/
private View.OnClickListener mParentClickConsumer;
/**
* Owner of our options menu and consumer of clicks
*/
private Activity mParentMenuConsumer;
public BottomBarControls(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
}
@Override
public void onFinishInflate() {
mTitle = (TextView)findViewById(R.id.title);
mArtist = (TextView)findViewById(R.id.artist);
mCover = (ImageView)findViewById(R.id.cover);
mSearchView = (SearchView)findViewById(R.id.search_view);
mControlsContent = (LinearLayout)findViewById(R.id.content_controls);
styleSearchView(mSearchView, mContext.getResources().getColor(android.R.color.background_light));
super.onFinishInflate();
}
@Override
public void onClick(View view) {
Object tag = view.getTag();
if (tag instanceof PopupMenu) {
((PopupMenu)tag).show();
} else if (tag instanceof MenuItem) {
mParentMenuConsumer.onOptionsItemSelected((MenuItem)tag);
} else if (view == mControlsContent && mParentClickConsumer != null) {
// dispatch this click to parent, claiming it came from
// the top view (= this)
mParentClickConsumer.onClick(this);
}
}
@Override
public boolean onMenuItemClick(MenuItem item) {
return mParentMenuConsumer.onOptionsItemSelected(item);
}
@Override
public Parcelable onSaveInstanceState() {
// Forcefully hide (and clear) search as we are not going to restore the state
showSearch(false);
return super.onSaveInstanceState();
}
/**
* Sets the ControlsContent to be clickable
*/
public void setOnClickListener(View.OnClickListener listener) {
mParentClickConsumer = listener;
mControlsContent.setOnClickListener(this);
}
/**
* Configures a query text listener for the search view
*/
public void setOnQueryTextListener(SearchView.OnQueryTextListener owner) {
mSearchView.setOnQueryTextListener(owner);
}
/**
* Boots the options menu
*
* @param owner the activity who will receive our callbacks
*/
public void enableOptionsMenu(Activity owner) {
mParentMenuConsumer = owner;
ImageButton menuButton = getImageButton(getResources().getDrawable(R.drawable.ic_menu_moreoverflow));
PopupMenu popupMenu = (menuMargin() ? new PopupMenu(mContext, menuButton, Gravity.RIGHT) : new PopupMenu(mContext, menuButton));
popupMenu.setOnMenuItemClickListener(this);
// Let parent populate the menu
mParentMenuConsumer.onCreateOptionsMenu(popupMenu.getMenu());
// The menu is now ready, we an now add all invisible
// items to the toolbar
Menu menu = popupMenu.getMenu();
for (int i=0; i < menu.size(); i++) {
MenuItem menuItem = menu.getItem(i);
if (menuItem.isVisible() == false) {
ImageButton button = getImageButton(menuItem.getIcon());
button.setTag(menuItem);
button.setOnClickListener(this);
mControlsContent.addView(button, -1);
}
}
// Add menu button at end of view
menuButton.setTag(popupMenu);
menuButton.setOnClickListener(this);
mControlsContent.addView(menuButton, -1);
}
/**
* Opens the OptionsMenu of this view
*/
public void openMenu() {
// simulates a click on the rightmost child which should be the options menu
mControlsContent.getChildAt(mControlsContent.getChildCount()-1).performClick();
}
/**
* Sets the search view to given state
*
* @param visible enables or disables the search box visibility
* @return boolean old state
*/
public boolean showSearch(boolean visible) {
boolean wasVisible = mSearchView.getVisibility() == View.VISIBLE;
if (wasVisible != visible) {
mSearchView.setVisibility(visible ? View.VISIBLE : View.GONE);
mControlsContent.setVisibility(visible ? View.GONE : View.VISIBLE);
if (visible)
mSearchView.setIconified(false); // requests focus AND shows the soft keyboard even if the view already was expanded
else
mSearchView.setQuery("", false);
}
return wasVisible;
}
/**
* Updates the cover image of this view
*
* @param cover the bitmap to display. Will use a placeholder image if cover is null
*/
public void setCover(Bitmap cover) {
if (cover == null)
mCover.setImageResource(R.drawable.fallback_cover);
else
mCover.setImageBitmap(cover);
}
/**
* Updates the song metadata
*
* @param song the song info to display, may be null
*/
public void setSong(Song song) {
if (song == null) {
mTitle.setText(null);
mArtist.setText(null);
mCover.setImageBitmap(null);
} else {
Resources res = mContext.getResources();
String title = song.title == null ? res.getString(R.string.unknown) : song.title;
String artist = song.artist == null ? res.getString(R.string.unknown) : song.artist;
mTitle.setText(title);
mArtist.setText(artist);
}
}
/**
* Returns a new image button to be placed on the bar
*
* @param drawable The icon to use
*/
private ImageButton getImageButton(Drawable drawable) {
ImageButton button = new ImageButton(mContext);
button.setImageDrawable(drawable);
button.setBackgroundResource(R.drawable.unbound_ripple_light);
if (menuMargin()) {
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.rightMargin = (int)(getResources().getDisplayMetrics().density * 4.0f);
button.setLayoutParams(params);
}
return button;
}
/**
* Changing the colors of a search view is a MAJOR pain using XML
* This cheap trick just loop trough the view and changes the
* color of all text- and image views to 'style'
*
* @param view the view to search
* @param color the color to apply
*/
private void styleSearchView(View view, int color) {
if (view != null) {
if (view instanceof TextView) {
((TextView)view).setTextColor(color);
} else if (view instanceof ImageView) {
((ImageView)view).setColorFilter(color);
} else if (view instanceof ViewGroup) {
ViewGroup group = (ViewGroup)view;
for (int i=0; i< group.getChildCount(); i++) {
styleSearchView(group.getChildAt(i), color);
}
}
}
}
/**
* Returns true if we need to add a margin to the menu.
* Because ...reasons.
*/
private boolean menuMargin() {
return ThemeHelper.usesHoloTheme() == false;
}
}

View File

@ -129,12 +129,8 @@ public class LibraryActivity
public ViewPager mViewPager;
private View mActionControls;
private TextView mTitle;
private TextView mArtist;
private ImageView mCover;
private BottomBarControls mBottomBarControls;
private View mPermissionRequest;
private MenuItem mSearchMenuItem;
private HorizontalScrollView mLimiterScroller;
private ViewGroup mLimiterViews;
@ -186,12 +182,10 @@ public class LibraryActivity
SharedPreferences settings = PlaybackService.getSettings(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;
mBottomBarControls = (BottomBarControls)findViewById(R.id.bottombar_controls);
mBottomBarControls.setOnClickListener(this);
mBottomBarControls.setOnQueryTextListener(this);
mBottomBarControls.enableOptionsMenu(this);
mPermissionRequest = (View)findViewById(R.id.permission_request);
@ -202,7 +196,6 @@ public class LibraryActivity
}
mVanillaTabLayout = (VanillaTabLayout)findViewById(R.id.sliding_tabs);
mVanillaTabLayout.inheritElevation(getActionBar());
mVanillaTabLayout.setOnPageChangeListener(pagerAdapter);
loadTabOrder();
@ -291,17 +284,9 @@ public class LibraryActivity
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
Limiter limiter = mPagerAdapter.getCurrentLimiter();
MenuItem menu_item = mSearchMenuItem;
if (menu_item != null) {
// Check if we can collapse the search view
// if we can, then it was open and we handled this
// action
boolean did_collapse = menu_item.collapseActionView();
if (did_collapse == true) {
break;
}
}
if (mBottomBarControls.showSearch(false))
break;
if (limiter != null) {
int pos = -1;
@ -336,6 +321,10 @@ public class LibraryActivity
finish();
}
break;
case KeyEvent.KEYCODE_MENU:
// We intercept these to avoid showing the activity-default menu
mBottomBarControls.openMenu();
break;
default:
return false;
}
@ -522,10 +511,7 @@ public class LibraryActivity
runOnUiThread(new Runnable() {
@Override
public void run() {
if (cover == null)
mCover.setImageResource(R.drawable.fallback_cover);
else
mCover.setImageBitmap(cover);
mBottomBarControls.setCover(cover);
}
});
}
@ -533,7 +519,7 @@ public class LibraryActivity
@Override
public void onClick(View view)
{
if (view == mCover || view == mActionControls) {
if (view == mBottomBarControls) {
openPlaybackActivity();
} else if (view == mPermissionRequest) {
PermissionRequestActivity.requestPermissions(this, getIntent());
@ -811,25 +797,12 @@ public class LibraryActivity
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
MenuItem controls = menu.add(0, MENU_PLAYBACK, 0, R.string.playback_view);
controls.setActionView(mActionControls);
controls.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
// Call super after adding the now-playing view as this should be the first item
// called before super to have it on top
menu.add(0, MENU_PLAYBACK, 0, R.string.playback_view);
super.onCreateOptionsMenu(menu);
// Check if we're running on Android 5.0 or higher
if (ThemeHelper.usesHoloTheme()) {
// Keep using the old icon
mSearchMenuItem = menu.add(0, MENU_SEARCH, 0, R.string.search).setIcon(R.drawable.ic_menu_search);
} else {
// Use the new material search icon
mSearchMenuItem = menu.add(0, MENU_SEARCH, 0, R.string.search).setIcon(R.drawable.ic_action_search);
}
mSearchMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | MenuItem.SHOW_AS_ACTION_ALWAYS);
SearchView mSearchView = new SearchView(getActionBar().getThemedContext());
mSearchView.setOnQueryTextListener(this);
mSearchMenuItem.setActionView(mSearchView);
MenuItem search = menu.add(0, MENU_SEARCH, 0, R.string.search).setIcon(R.drawable.ic_menu_search);
search.setVisible(false);
menu.add(0, MENU_SORT, 0, R.string.sort_by).setIcon(R.drawable.ic_menu_sort_alphabetically);
menu.add(0, MENU_SHOW_QUEUE, 0, R.string.show_queue);
@ -850,7 +823,7 @@ public class LibraryActivity
{
switch (item.getItemId()) {
case MENU_SEARCH:
// this does nothing: expanding ishandled by mSearchView
mBottomBarControls.showSearch(true);
return true;
case MENU_PLAYBACK:
openPlaybackActivity();
@ -963,22 +936,9 @@ public class LibraryActivity
{
super.onSongChange(song);
if (mTitle != null) {
if (song == null) {
mTitle.setText(null);
mArtist.setText(null);
mCover.setImageBitmap(null);
} else {
Resources res = getResources();
String title = song.title == null ? res.getString(R.string.unknown) : song.title;
String artist = song.artist == null ? res.getString(R.string.unknown) : song.artist;
mTitle.setText(title);
mArtist.setText(artist);
// Update and generate the cover in a background thread
mHandler.sendMessage(mHandler.obtainMessage(MSG_UPDATE_COVER, song));
}
mCover.setVisibility(CoverCache.mCoverLoadMode == 0 ? View.GONE : View.VISIBLE);
}
mBottomBarControls.setSong(song);
if (song != null)
mHandler.sendMessage(mHandler.obtainMessage(MSG_UPDATE_COVER, song));
}
@Override