Swipey tabs
BIN
libs/android-support-v4.jar
Normal file
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 935 B |
Before Width: | Height: | Size: 713 B |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 831 B |
Before Width: | Height: | Size: 660 B |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1003 B |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1003 B |
Before Width: | Height: | Size: 873 B |
Before Width: | Height: | Size: 449 B |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 998 B |
Before Width: | Height: | Size: 922 B |
BIN
res/drawable-hdpi/vpi__tab_selected_focused_holo.9.png
Normal file
After Width: | Height: | Size: 147 B |
BIN
res/drawable-hdpi/vpi__tab_selected_holo.9.png
Normal file
After Width: | Height: | Size: 148 B |
BIN
res/drawable-hdpi/vpi__tab_selected_pressed_holo.9.png
Normal file
After Width: | Height: | Size: 147 B |
BIN
res/drawable-hdpi/vpi__tab_unselected_focused_holo.9.png
Normal file
After Width: | Height: | Size: 146 B |
BIN
res/drawable-hdpi/vpi__tab_unselected_holo.9.png
Normal file
After Width: | Height: | Size: 153 B |
BIN
res/drawable-hdpi/vpi__tab_unselected_pressed_holo.9.png
Normal file
After Width: | Height: | Size: 145 B |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 505 B |
Before Width: | Height: | Size: 518 B |
Before Width: | Height: | Size: 1004 B After Width: | Height: | Size: 510 B |
Before Width: | Height: | Size: 472 B |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 764 B |
Before Width: | Height: | Size: 991 B |
Before Width: | Height: | Size: 642 B |
Before Width: | Height: | Size: 570 B |
Before Width: | Height: | Size: 331 B |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 586 B |
Before Width: | Height: | Size: 643 B |
BIN
res/drawable-mdpi/vpi__tab_selected_focused_holo.9.png
Normal file
After Width: | Height: | Size: 148 B |
BIN
res/drawable-mdpi/vpi__tab_selected_holo.9.png
Normal file
After Width: | Height: | Size: 151 B |
BIN
res/drawable-mdpi/vpi__tab_selected_pressed_holo.9.png
Normal file
After Width: | Height: | Size: 150 B |
BIN
res/drawable-mdpi/vpi__tab_unselected_focused_holo.9.png
Normal file
After Width: | Height: | Size: 150 B |
BIN
res/drawable-mdpi/vpi__tab_unselected_holo.9.png
Normal file
After Width: | Height: | Size: 157 B |
BIN
res/drawable-mdpi/vpi__tab_unselected_pressed_holo.9.png
Normal file
After Width: | Height: | Size: 155 B |
BIN
res/drawable-xhdpi/ic_tab_albums_selected.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
res/drawable-xhdpi/ic_tab_artists_selected.png
Normal file
After Width: | Height: | Size: 996 B |
BIN
res/drawable-xhdpi/ic_tab_songs_selected.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
res/drawable-xhdpi/vpi__tab_selected_focused_holo.9.png
Normal file
After Width: | Height: | Size: 147 B |
BIN
res/drawable-xhdpi/vpi__tab_selected_holo.9.png
Normal file
After Width: | Height: | Size: 153 B |
BIN
res/drawable-xhdpi/vpi__tab_selected_pressed_holo.9.png
Normal file
After Width: | Height: | Size: 147 B |
BIN
res/drawable-xhdpi/vpi__tab_unselected_focused_holo.9.png
Normal file
After Width: | Height: | Size: 148 B |
BIN
res/drawable-xhdpi/vpi__tab_unselected_holo.9.png
Normal file
After Width: | Height: | Size: 166 B |
BIN
res/drawable-xhdpi/vpi__tab_unselected_pressed_holo.9.png
Normal file
After Width: | Height: | Size: 149 B |
@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item
|
|
||||||
android:state_selected="true"
|
|
||||||
android:state_pressed="false"
|
|
||||||
android:drawable="@drawable/ic_tab_albums_selected" />
|
|
||||||
<item
|
|
||||||
android:drawable="@drawable/ic_tab_albums_unselected" />
|
|
||||||
</selector>
|
|
@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item
|
|
||||||
android:state_selected="true"
|
|
||||||
android:state_pressed="false"
|
|
||||||
android:drawable="@drawable/ic_tab_artists_selected" />
|
|
||||||
<item
|
|
||||||
android:drawable="@drawable/ic_tab_artists_unselected" />
|
|
||||||
</selector>
|
|
@ -1,5 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item android:drawable="@drawable/ic_tab_files_selected" android:state_selected="true" android:state_pressed="false" />
|
|
||||||
<item android:drawable="@drawable/ic_tab_files_unselected" />
|
|
||||||
</selector>
|
|
@ -1,5 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item android:drawable="@drawable/ic_tab_genres_selected" android:state_selected="true" android:state_pressed="false" />
|
|
||||||
<item android:drawable="@drawable/ic_tab_genres_unselected" />
|
|
||||||
</selector>
|
|
@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item
|
|
||||||
android:state_selected="true"
|
|
||||||
android:state_pressed="false"
|
|
||||||
android:drawable="@drawable/ic_tab_playlists_selected" />
|
|
||||||
<item
|
|
||||||
android:drawable="@drawable/ic_tab_playlists_unselected" />
|
|
||||||
</selector>
|
|
@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item
|
|
||||||
android:state_selected="true"
|
|
||||||
android:state_pressed="false"
|
|
||||||
android:drawable="@drawable/ic_tab_songs_selected" />
|
|
||||||
<item
|
|
||||||
android:drawable="@drawable/ic_tab_songs_unselected" />
|
|
||||||
</selector>
|
|
34
res/drawable/vpi__tab_indicator.xml
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2008 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<!-- Non focused states -->
|
||||||
|
<item android:state_focused="false" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/vpi__tab_unselected_holo" />
|
||||||
|
<item android:state_focused="false" android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/vpi__tab_selected_holo" />
|
||||||
|
|
||||||
|
<!-- Focused states -->
|
||||||
|
<item android:state_focused="true" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/vpi__tab_unselected_focused_holo" />
|
||||||
|
<item android:state_focused="true" android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/vpi__tab_selected_focused_holo" />
|
||||||
|
|
||||||
|
<!-- Pressed -->
|
||||||
|
<!-- Non focused states -->
|
||||||
|
<item android:state_focused="false" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/vpi__tab_unselected_pressed_holo" />
|
||||||
|
<item android:state_focused="false" android:state_selected="true" android:state_pressed="true" android:drawable="@drawable/vpi__tab_selected_pressed_holo" />
|
||||||
|
|
||||||
|
<!-- Focused states -->
|
||||||
|
<item android:state_focused="true" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/vpi__tab_unselected_pressed_holo" />
|
||||||
|
<item android:state_focused="true" android:state_selected="true" android:state_pressed="true" android:drawable="@drawable/vpi__tab_selected_pressed_holo" />
|
||||||
|
</selector>
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!--
|
<!--
|
||||||
Copyright (C) 2010 Christopher Eby <kreed@kreed.org>
|
Copyright (C) 2012 Christopher Eby <kreed@kreed.org>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -20,91 +20,56 @@ 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
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
-->
|
-->
|
||||||
<TabHost
|
<LinearLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:id="@+id/tab_host"
|
android:id="@+id/content"
|
||||||
android:layout_height="fill_parent"
|
android:orientation="vertical"
|
||||||
android:layout_width="fill_parent">
|
android:layout_width="fill_parent"
|
||||||
<LinearLayout
|
android:layout_height="fill_parent">
|
||||||
android:id="@+id/content"
|
<com.viewpagerindicator.TabPageIndicator
|
||||||
android:orientation="vertical"
|
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"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="fill_parent">
|
android:layout_height="0px"
|
||||||
<TabWidget
|
android:layout_weight="1" />
|
||||||
android:id="@android:id/tabs"
|
<HorizontalScrollView
|
||||||
android:layout_width="fill_parent"
|
android:id="@+id/limiter_scroller"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_width="fill_parent"
|
||||||
<FrameLayout
|
android:layout_height="wrap_content"
|
||||||
android:id="@android:id/tabcontent"
|
android:layout_gravity="bottom|left">
|
||||||
android:layout_width="fill_parent"
|
<LinearLayout
|
||||||
android:layout_height="0px"
|
android:id="@+id/limiter_layout"
|
||||||
android:layout_weight="1">
|
android:layout_width="wrap_content"
|
||||||
<ListView
|
android:layout_height="fill_parent" />
|
||||||
android:id="@+id/artist_list"
|
</HorizontalScrollView>
|
||||||
android:visibility="gone"
|
<LinearLayout
|
||||||
android:layout_width="fill_parent"
|
android:id="@+id/search_box"
|
||||||
android:layout_height="fill_parent" />
|
android:layout_width="fill_parent"
|
||||||
<ListView
|
android:layout_height="wrap_content"
|
||||||
android:id="@+id/album_list"
|
android:layout_gravity="bottom"
|
||||||
android:visibility="gone"
|
android:paddingTop="4dip"
|
||||||
android:layout_width="fill_parent"
|
android:paddingLeft="4dip"
|
||||||
android:layout_height="fill_parent" />
|
android:visibility="gone"
|
||||||
<ListView
|
android:background="@drawable/search_background">
|
||||||
android:id="@+id/song_list"
|
<EditText
|
||||||
android:visibility="gone"
|
android:id="@+id/filter_text"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="0px"
|
||||||
android:layout_height="fill_parent" />
|
|
||||||
<ListView
|
|
||||||
android:id="@+id/playlist_list"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="fill_parent" />
|
|
||||||
<ListView
|
|
||||||
android:id="@+id/genre_list"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="fill_parent" />
|
|
||||||
<ListView
|
|
||||||
android:id="@+id/file_list"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="fill_parent" />
|
|
||||||
</FrameLayout>
|
|
||||||
<HorizontalScrollView
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="bottom|left">
|
android:layout_weight="1"
|
||||||
<LinearLayout
|
android:inputType="textFilter" />
|
||||||
android:id="@+id/limiter_layout"
|
<ImageButton
|
||||||
android:layout_width="wrap_content"
|
android:id="@+id/clear_button"
|
||||||
android:layout_height="fill_parent" />
|
android:scaleType="fitCenter"
|
||||||
</HorizontalScrollView>
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/search_box"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="bottom"
|
|
||||||
android:paddingTop="4dip"
|
|
||||||
android:paddingLeft="4dip"
|
android:paddingLeft="4dip"
|
||||||
android:visibility="gone"
|
android:paddingRight="4dip"
|
||||||
android:background="@drawable/search_background">
|
android:paddingBottom="4dip"
|
||||||
<EditText
|
android:layout_width="wrap_content"
|
||||||
android:id="@+id/filter_text"
|
android:layout_height="fill_parent"
|
||||||
android:layout_width="0px"
|
android:background="@null"
|
||||||
android:layout_height="wrap_content"
|
android:src="@drawable/close" />
|
||||||
android:layout_weight="1"
|
|
||||||
android:inputType="textFilter" />
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/clear_button"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:paddingLeft="4dip"
|
|
||||||
android:paddingRight="4dip"
|
|
||||||
android:paddingBottom="4dip"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="fill_parent"
|
|
||||||
android:background="@null"
|
|
||||||
android:src="@drawable/close" />
|
|
||||||
</LinearLayout>
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</TabHost>
|
</LinearLayout>
|
||||||
|
|
||||||
|
205
src/com/viewpagerindicator/TabPageIndicator.java
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011 The Android Open Source Project
|
||||||
|
* Copyright (C) 2011 Jake Wharton
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.viewpagerindicator;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Typeface;
|
||||||
|
import android.support.v4.view.PagerAdapter;
|
||||||
|
import android.support.v4.view.ViewPager;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.util.DisplayMetrics;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.HorizontalScrollView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import org.kreed.vanilla.R;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This widget implements the dynamic action bar tab behavior that can change
|
||||||
|
* across different configurations or circumstances.
|
||||||
|
*/
|
||||||
|
public class TabPageIndicator extends HorizontalScrollView
|
||||||
|
implements ViewPager.OnPageChangeListener
|
||||||
|
, View.OnClickListener
|
||||||
|
{
|
||||||
|
Runnable mTabSelector;
|
||||||
|
|
||||||
|
private final LinearLayout mTabLayout;
|
||||||
|
private ViewPager mViewPager;
|
||||||
|
private ViewPager.OnPageChangeListener mListener;
|
||||||
|
|
||||||
|
private int mSelectedTabIndex;
|
||||||
|
|
||||||
|
public TabPageIndicator(Context context) {
|
||||||
|
this(context, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TabPageIndicator(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
setHorizontalScrollBarEnabled(false);
|
||||||
|
|
||||||
|
mTabLayout = new LinearLayout(getContext());
|
||||||
|
addView(mTabLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.FILL_PARENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
|
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
|
||||||
|
final boolean lockedExpanded = widthMode == MeasureSpec.EXACTLY;
|
||||||
|
setFillViewport(lockedExpanded);
|
||||||
|
|
||||||
|
final int oldWidth = getMeasuredWidth();
|
||||||
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||||
|
final int newWidth = getMeasuredWidth();
|
||||||
|
|
||||||
|
if (lockedExpanded && oldWidth != newWidth) {
|
||||||
|
// Recenter the tab display if we're at a new (scrollable) size.
|
||||||
|
setCurrentItem(mSelectedTabIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void animateToTab(final int position) {
|
||||||
|
final View tabView = mTabLayout.getChildAt(position);
|
||||||
|
if (mTabSelector != null) {
|
||||||
|
removeCallbacks(mTabSelector);
|
||||||
|
}
|
||||||
|
mTabSelector = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
final int scrollPos = tabView.getLeft() - (getWidth() - tabView.getWidth()) / 2;
|
||||||
|
smoothScrollTo(scrollPos, 0);
|
||||||
|
mTabSelector = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
post(mTabSelector);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttachedToWindow() {
|
||||||
|
super.onAttachedToWindow();
|
||||||
|
if (mTabSelector != null) {
|
||||||
|
// Re-post the selector we saved
|
||||||
|
post(mTabSelector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDetachedFromWindow() {
|
||||||
|
super.onDetachedFromWindow();
|
||||||
|
if (mTabSelector != null) {
|
||||||
|
removeCallbacks(mTabSelector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addTab(CharSequence text, int index) {
|
||||||
|
Context context = getContext();
|
||||||
|
DisplayMetrics dm = context.getResources().getDisplayMetrics();
|
||||||
|
|
||||||
|
int padX = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 22, dm);
|
||||||
|
int padY = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 12, dm);
|
||||||
|
|
||||||
|
TextView tabView = new TextView(context);
|
||||||
|
tabView.setBackgroundResource(R.drawable.vpi__tab_indicator);
|
||||||
|
tabView.setPadding(padX, padY, padX, padY);
|
||||||
|
tabView.setGravity(Gravity.CENTER);
|
||||||
|
tabView.setTextColor(0xfff3f3f3);
|
||||||
|
tabView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12);
|
||||||
|
tabView.setTypeface(tabView.getTypeface(), Typeface.BOLD);
|
||||||
|
tabView.setSingleLine();
|
||||||
|
tabView.setTag(index);
|
||||||
|
tabView.setFocusable(true);
|
||||||
|
tabView.setOnClickListener(this);
|
||||||
|
tabView.setText(text);
|
||||||
|
|
||||||
|
mTabLayout.addView(tabView, new LinearLayout.LayoutParams(0, LayoutParams.FILL_PARENT, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPageScrollStateChanged(int arg0) {
|
||||||
|
if (mListener != null) {
|
||||||
|
mListener.onPageScrollStateChanged(arg0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPageScrolled(int arg0, float arg1, int arg2) {
|
||||||
|
if (mListener != null) {
|
||||||
|
mListener.onPageScrolled(arg0, arg1, arg2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPageSelected(int arg0) {
|
||||||
|
setCurrentItem(arg0);
|
||||||
|
if (mListener != null) {
|
||||||
|
mListener.onPageSelected(arg0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setViewPager(ViewPager view) {
|
||||||
|
final PagerAdapter adapter = view.getAdapter();
|
||||||
|
if (adapter == null) {
|
||||||
|
throw new IllegalStateException("ViewPager does not have adapter instance.");
|
||||||
|
}
|
||||||
|
mViewPager = view;
|
||||||
|
view.setOnPageChangeListener(this);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void notifyDataSetChanged() {
|
||||||
|
mTabLayout.removeAllViews();
|
||||||
|
PagerAdapter adapter = mViewPager.getAdapter();
|
||||||
|
final int count = adapter.getCount();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
addTab(adapter.getPageTitle(i), i);
|
||||||
|
}
|
||||||
|
if (mSelectedTabIndex > count) {
|
||||||
|
mSelectedTabIndex = count - 1;
|
||||||
|
}
|
||||||
|
setCurrentItem(mSelectedTabIndex);
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCurrentItem(int item) {
|
||||||
|
if (mViewPager == null) {
|
||||||
|
throw new IllegalStateException("ViewPager has not been bound.");
|
||||||
|
}
|
||||||
|
mSelectedTabIndex = item;
|
||||||
|
final int tabCount = mTabLayout.getChildCount();
|
||||||
|
for (int i = 0; i < tabCount; i++) {
|
||||||
|
final View child = mTabLayout.getChildAt(i);
|
||||||
|
final boolean isSelected = (i == item);
|
||||||
|
child.setSelected(isSelected);
|
||||||
|
if (isSelected) {
|
||||||
|
animateToTab(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
|
||||||
|
mListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
mViewPager.setCurrentItem((Integer)view.getTag());
|
||||||
|
}
|
||||||
|
}
|
@ -90,15 +90,9 @@ public final class CoverBitmap {
|
|||||||
private static void loadIcons(Context context)
|
private static void loadIcons(Context context)
|
||||||
{
|
{
|
||||||
Resources res = context.getResources();
|
Resources res = context.getResources();
|
||||||
Bitmap bitmap = BitmapFactory.decodeResource(res, R.drawable.ic_tab_songs_selected);
|
SONG_ICON = BitmapFactory.decodeResource(res, R.drawable.ic_tab_songs_selected);
|
||||||
SONG_ICON = Bitmap.createScaledBitmap(bitmap, TEXT_SIZE, TEXT_SIZE, false);
|
ALBUM_ICON = BitmapFactory.decodeResource(res, R.drawable.ic_tab_albums_selected);
|
||||||
bitmap.recycle();
|
ARTIST_ICON = BitmapFactory.decodeResource(res, R.drawable.ic_tab_artists_selected);
|
||||||
bitmap = BitmapFactory.decodeResource(res, R.drawable.ic_tab_albums_selected);
|
|
||||||
ALBUM_ICON = Bitmap.createScaledBitmap(bitmap, TEXT_SIZE, TEXT_SIZE, false);
|
|
||||||
bitmap.recycle();
|
|
||||||
bitmap = BitmapFactory.decodeResource(res, R.drawable.ic_tab_artists_selected);
|
|
||||||
ARTIST_ICON = Bitmap.createScaledBitmap(bitmap, TEXT_SIZE, TEXT_SIZE, false);
|
|
||||||
bitmap.recycle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,14 +32,14 @@ import android.database.ContentObserver;
|
|||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.graphics.drawable.PaintDrawable;
|
import android.graphics.drawable.PaintDrawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.provider.MediaStore;
|
import android.provider.MediaStore;
|
||||||
|
import android.support.v4.view.PagerAdapter;
|
||||||
|
import android.support.v4.view.ViewPager;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
@ -55,12 +55,13 @@ import android.view.ViewGroup;
|
|||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
import android.widget.HorizontalScrollView;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.RadioGroup;
|
import android.widget.RadioGroup;
|
||||||
import android.widget.TabHost;
|
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
import com.viewpagerindicator.TabPageIndicator;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import junit.framework.Assert;
|
import junit.framework.Assert;
|
||||||
@ -72,9 +73,9 @@ public class LibraryActivity
|
|||||||
extends PlaybackActivity
|
extends PlaybackActivity
|
||||||
implements AdapterView.OnItemClickListener
|
implements AdapterView.OnItemClickListener
|
||||||
, TextWatcher
|
, TextWatcher
|
||||||
, TabHost.OnTabChangeListener
|
|
||||||
, DialogInterface.OnClickListener
|
, DialogInterface.OnClickListener
|
||||||
, DialogInterface.OnDismissListener
|
, DialogInterface.OnDismissListener
|
||||||
|
, ViewPager.OnPageChangeListener
|
||||||
{
|
{
|
||||||
public static final int ACTION_PLAY = 0;
|
public static final int ACTION_PLAY = 0;
|
||||||
public static final int ACTION_ENQUEUE = 1;
|
public static final int ACTION_ENQUEUE = 1;
|
||||||
@ -87,8 +88,7 @@ public class LibraryActivity
|
|||||||
{ SongTimeline.MODE_PLAY, SongTimeline.MODE_ENQUEUE, -1,
|
{ SongTimeline.MODE_PLAY, SongTimeline.MODE_ENQUEUE, -1,
|
||||||
SongTimeline.MODE_PLAY_ID_FIRST, SongTimeline.MODE_ENQUEUE_ID_FIRST };
|
SongTimeline.MODE_PLAY_ID_FIRST, SongTimeline.MODE_ENQUEUE_ID_FIRST };
|
||||||
|
|
||||||
private TabHost mTabHost;
|
private ViewPager mViewPager;
|
||||||
|
|
||||||
private View mSearchBox;
|
private View mSearchBox;
|
||||||
private boolean mSearchBoxVisible;
|
private boolean mSearchBoxVisible;
|
||||||
private TextView mTextFilter;
|
private TextView mTextFilter;
|
||||||
@ -100,6 +100,7 @@ public class LibraryActivity
|
|||||||
private ImageView mCover;
|
private ImageView mCover;
|
||||||
private View mEmptyQueue;
|
private View mEmptyQueue;
|
||||||
|
|
||||||
|
private HorizontalScrollView mLimiterScroller;
|
||||||
private ViewGroup mLimiterViews;
|
private ViewGroup mLimiterViews;
|
||||||
|
|
||||||
private int mDefaultAction;
|
private int mDefaultAction;
|
||||||
@ -123,6 +124,15 @@ public class LibraryActivity
|
|||||||
* Each adapter, in the same order as MediaUtils.TYPE_*.
|
* Each adapter, in the same order as MediaUtils.TYPE_*.
|
||||||
*/
|
*/
|
||||||
final LibraryAdapter[] mAdapters = new LibraryAdapter[ADAPTER_COUNT];
|
final LibraryAdapter[] mAdapters = new LibraryAdapter[ADAPTER_COUNT];
|
||||||
|
/**
|
||||||
|
* The human-readable title for each page.
|
||||||
|
*/
|
||||||
|
public static final int[] TITLES = { R.string.artists, R.string.albums, R.string.songs,
|
||||||
|
R.string.playlists, R.string.genres, R.string.files };
|
||||||
|
/**
|
||||||
|
* Limiters that should be passed to an adapter constructor.
|
||||||
|
*/
|
||||||
|
public final Limiter[] mPendingLimiters = new Limiter[ADAPTER_COUNT];
|
||||||
MediaAdapter mArtistAdapter;
|
MediaAdapter mArtistAdapter;
|
||||||
MediaAdapter mAlbumAdapter;
|
MediaAdapter mAlbumAdapter;
|
||||||
MediaAdapter mSongAdapter;
|
MediaAdapter mSongAdapter;
|
||||||
@ -135,7 +145,103 @@ public class LibraryActivity
|
|||||||
@Override
|
@Override
|
||||||
public void onChange(boolean selfChange)
|
public void onChange(boolean selfChange)
|
||||||
{
|
{
|
||||||
postRequestRequery(mPlaylistAdapter);
|
if (mPlaylistAdapter != null) {
|
||||||
|
postRequestRequery(mPlaylistAdapter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final PagerAdapter mPagerAdapter = new PagerAdapter() {
|
||||||
|
@Override
|
||||||
|
public Object instantiateItem(ViewGroup container, int position)
|
||||||
|
{
|
||||||
|
ListView view = mLists[position];
|
||||||
|
|
||||||
|
if (view == null) {
|
||||||
|
LibraryAdapter adapter;
|
||||||
|
|
||||||
|
switch (position) {
|
||||||
|
case 0:
|
||||||
|
adapter = mArtistAdapter = new MediaAdapter(LibraryActivity.this, MediaUtils.TYPE_ARTIST, true, true, null);
|
||||||
|
mArtistAdapter.setHeaderText(getHeaderText());
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
adapter = mAlbumAdapter = new MediaAdapter(LibraryActivity.this, MediaUtils.TYPE_ALBUM, true, true, mPendingLimiters[position]);
|
||||||
|
mAlbumAdapter.setHeaderText(getHeaderText());
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
adapter = mSongAdapter = new MediaAdapter(LibraryActivity.this, MediaUtils.TYPE_SONG, false, true, mPendingLimiters[position]);
|
||||||
|
mSongAdapter.setHeaderText(getHeaderText());
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
adapter = mPlaylistAdapter = new MediaAdapter(LibraryActivity.this, MediaUtils.TYPE_PLAYLIST, true, false, null);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
adapter = mGenreAdapter = new MediaAdapter(LibraryActivity.this, MediaUtils.TYPE_GENRE, true, false, null);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
adapter = mFilesAdapter = new FileSystemAdapter(LibraryActivity.this, mPendingLimiters[position]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Invalid position: " + position);
|
||||||
|
}
|
||||||
|
|
||||||
|
view = new ListView(LibraryActivity.this);
|
||||||
|
view.setOnItemClickListener(LibraryActivity.this);
|
||||||
|
view.setOnCreateContextMenuListener(LibraryActivity.this);
|
||||||
|
view.setDivider(null);
|
||||||
|
view.setFastScrollEnabled(true);
|
||||||
|
|
||||||
|
view.setAdapter(adapter);
|
||||||
|
if (position != 5)
|
||||||
|
loadSortOrder((MediaAdapter)adapter);
|
||||||
|
|
||||||
|
String filter = mTextFilter.getText().toString();
|
||||||
|
if (filter.length() != 0) {
|
||||||
|
adapter.setFilter(filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
mAdapters[position] = adapter;
|
||||||
|
mLists[position] = view;
|
||||||
|
mRequeryNeeded[position] = true;
|
||||||
|
|
||||||
|
if (mCurrentAdapter == null && mViewPager.getCurrentItem() == position) {
|
||||||
|
// Special case: for first time initialization onPageSelected
|
||||||
|
// is not called (for initial position = 0) or called before
|
||||||
|
// the adapter is initialized (for all other initial positions).
|
||||||
|
// So do required work here.
|
||||||
|
mCurrentAdapter = adapter;
|
||||||
|
updateLimiterViews();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
requeryIfNeeded(position);
|
||||||
|
container.addView(view);
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroyItem(ViewGroup container, int position, Object object)
|
||||||
|
{
|
||||||
|
container.removeView(mLists[position]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharSequence getPageTitle(int position)
|
||||||
|
{
|
||||||
|
return getResources().getText(TITLES[position]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount()
|
||||||
|
{
|
||||||
|
return ADAPTER_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isViewFromObject(View view, Object object)
|
||||||
|
{
|
||||||
|
return view == object;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -185,44 +291,18 @@ public class LibraryActivity
|
|||||||
mClearButton = findViewById(R.id.clear_button);
|
mClearButton = findViewById(R.id.clear_button);
|
||||||
mClearButton.setOnClickListener(this);
|
mClearButton.setOnClickListener(this);
|
||||||
|
|
||||||
|
mLimiterScroller = (HorizontalScrollView)findViewById(R.id.limiter_scroller);
|
||||||
mLimiterViews = (ViewGroup)findViewById(R.id.limiter_layout);
|
mLimiterViews = (ViewGroup)findViewById(R.id.limiter_layout);
|
||||||
|
|
||||||
mTabHost = (TabHost)findViewById(R.id.tab_host);
|
mViewPager = (ViewPager)findViewById(R.id.pager);
|
||||||
mTabHost.setup();
|
mViewPager.setAdapter(mPagerAdapter);
|
||||||
|
|
||||||
mArtistAdapter = new MediaAdapter(this, MediaUtils.TYPE_ARTIST, true, true, null);
|
TabPageIndicator tabs = (TabPageIndicator)findViewById(R.id.tabs);
|
||||||
mAlbumAdapter = new MediaAdapter(this, MediaUtils.TYPE_ALBUM, true, true, state == null ? null : (Limiter)state.getSerializable("limiter_albums"));
|
tabs.setViewPager(mViewPager);
|
||||||
mSongAdapter = new MediaAdapter(this, MediaUtils.TYPE_SONG, false, true, state == null ? null : (Limiter)state.getSerializable("limiter_songs"));
|
tabs.setOnPageChangeListener(this);
|
||||||
mPlaylistAdapter = new MediaAdapter(this, MediaUtils.TYPE_PLAYLIST, true, false, null);
|
|
||||||
mGenreAdapter = new MediaAdapter(this, MediaUtils.TYPE_GENRE, true, false, null);
|
|
||||||
mFilesAdapter = new FileSystemAdapter(this, state == null ? null : (Limiter)state.getSerializable("limiter_files"));
|
|
||||||
|
|
||||||
setupView(0, R.id.artist_list, R.string.artists, R.drawable.ic_tab_artists, mArtistAdapter);
|
|
||||||
setupView(1, R.id.album_list, R.string.albums, R.drawable.ic_tab_albums, mAlbumAdapter);
|
|
||||||
setupView(2, R.id.song_list, R.string.songs, R.drawable.ic_tab_songs, mSongAdapter);
|
|
||||||
setupView(3, R.id.playlist_list, R.string.playlists, R.drawable.ic_tab_playlists, mPlaylistAdapter);
|
|
||||||
setupView(4, R.id.genre_list, R.string.genres, R.drawable.ic_tab_genres, mGenreAdapter);
|
|
||||||
setupView(5, R.id.file_list, R.string.files, R.drawable.ic_tab_files, mFilesAdapter);
|
|
||||||
|
|
||||||
getContentResolver().registerContentObserver(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI, true, mPlaylistObserver);
|
getContentResolver().registerContentObserver(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI, true, mPlaylistObserver);
|
||||||
|
|
||||||
int currentTab = 0;
|
|
||||||
String filter = null;
|
|
||||||
|
|
||||||
if (state != null) {
|
|
||||||
if (state.getBoolean("search_box_visible"))
|
|
||||||
setSearchBoxVisible(true);
|
|
||||||
currentTab = state.getInt("current_tab", 0);
|
|
||||||
filter = state.getString("filter");
|
|
||||||
}
|
|
||||||
|
|
||||||
mTabHost.setCurrentTab(currentTab);
|
|
||||||
mTabHost.setOnTabChangedListener(this);
|
|
||||||
onTabChanged(null);
|
|
||||||
|
|
||||||
if (filter != null)
|
|
||||||
mTextFilter.setText(filter);
|
|
||||||
|
|
||||||
onNewIntent(getIntent());
|
onNewIntent(getIntent());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,15 +336,29 @@ public class LibraryActivity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRestoreInstanceState(Bundle in)
|
||||||
|
{
|
||||||
|
super.onRestoreInstanceState(in);
|
||||||
|
if (in.getBoolean("search_box_visible"))
|
||||||
|
setSearchBoxVisible(true);
|
||||||
|
mPendingLimiters[1] = (Limiter)in.getSerializable("limiter_albums");
|
||||||
|
mPendingLimiters[2] = (Limiter)in.getSerializable("limiter_songs");
|
||||||
|
mPendingLimiters[5] = (Limiter)in.getSerializable("limiter_files");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSaveInstanceState(Bundle out)
|
protected void onSaveInstanceState(Bundle out)
|
||||||
{
|
{
|
||||||
|
super.onSaveInstanceState(out);
|
||||||
|
|
||||||
out.putBoolean("search_box_visible", mSearchBoxVisible);
|
out.putBoolean("search_box_visible", mSearchBoxVisible);
|
||||||
out.putInt("current_tab", mTabHost.getCurrentTab());
|
if (mAlbumAdapter != null)
|
||||||
out.putString("filter", mTextFilter.getText().toString());
|
out.putSerializable("limiter_albums", mAlbumAdapter.getLimiter());
|
||||||
out.putSerializable("limiter_albums", mAlbumAdapter.getLimiter());
|
if (mSongAdapter != null)
|
||||||
out.putSerializable("limiter_songs", mSongAdapter.getLimiter());
|
out.putSerializable("limiter_songs", mSongAdapter.getLimiter());
|
||||||
out.putSerializable("limiter_files", mFilesAdapter.getLimiter());
|
if (mFilesAdapter != null)
|
||||||
|
out.putSerializable("limiter_files", mFilesAdapter.getLimiter());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -306,21 +400,31 @@ public class LibraryActivity
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns either "Play All" or "Enqueue All", depending on the current
|
||||||
|
* default action.
|
||||||
|
*/
|
||||||
|
private String getHeaderText()
|
||||||
|
{
|
||||||
|
int action = mDefaultAction;
|
||||||
|
if (action == ACTION_LAST_USED)
|
||||||
|
action = mLastAction;
|
||||||
|
return getString(action == ACTION_ENQUEUE || action == ACTION_ENQUEUE_ALL ? R.string.enqueue_all : R.string.play_all);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the first row of the lists with the appropriate action (play all
|
* Update the first row of the lists with the appropriate action (play all
|
||||||
* or enqueue all).
|
* or enqueue all).
|
||||||
*/
|
*/
|
||||||
private void updateHeaders()
|
private void updateHeaders()
|
||||||
{
|
{
|
||||||
int action = mDefaultAction;
|
String text = getHeaderText();
|
||||||
if (action == ACTION_LAST_USED)
|
if (mArtistAdapter != null)
|
||||||
action = mLastAction;
|
mArtistAdapter.setHeaderText(text);
|
||||||
|
if (mAlbumAdapter != null)
|
||||||
int res = action == ACTION_ENQUEUE || action == ACTION_ENQUEUE_ALL ? R.string.enqueue_all : R.string.play_all;
|
mAlbumAdapter.setHeaderText(text);
|
||||||
String text = getString(res);
|
if (mSongAdapter != null)
|
||||||
mArtistAdapter.setHeaderText(text);
|
mSongAdapter.setHeaderText(text);
|
||||||
mAlbumAdapter.setHeaderText(text);
|
|
||||||
mSongAdapter.setHeaderText(text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -386,15 +490,27 @@ public class LibraryActivity
|
|||||||
private void clearLimiter(int type)
|
private void clearLimiter(int type)
|
||||||
{
|
{
|
||||||
if (type == MediaUtils.TYPE_FILE) {
|
if (type == MediaUtils.TYPE_FILE) {
|
||||||
mFilesAdapter.setLimiter(null);
|
if (mFilesAdapter == null) {
|
||||||
requestRequery(mFilesAdapter);
|
mPendingLimiters[5] = null;
|
||||||
|
} else {
|
||||||
|
mFilesAdapter.setLimiter(null);
|
||||||
|
requestRequery(mFilesAdapter);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
mAlbumAdapter.setLimiter(null);
|
if (mAlbumAdapter == null) {
|
||||||
mSongAdapter.setLimiter(null);
|
mPendingLimiters[1] = null;
|
||||||
loadSortOrder(mSongAdapter);
|
} else {
|
||||||
loadSortOrder(mAlbumAdapter);
|
mAlbumAdapter.setLimiter(null);
|
||||||
requestRequery(mSongAdapter);
|
loadSortOrder(mAlbumAdapter);
|
||||||
requestRequery(mAlbumAdapter);
|
requestRequery(mAlbumAdapter);
|
||||||
|
}
|
||||||
|
if (mSongAdapter == null) {
|
||||||
|
mPendingLimiters[2] = null;
|
||||||
|
} else {
|
||||||
|
mSongAdapter.setLimiter(null);
|
||||||
|
loadSortOrder(mSongAdapter);
|
||||||
|
requestRequery(mSongAdapter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
updateLimiterViews();
|
updateLimiterViews();
|
||||||
}
|
}
|
||||||
@ -411,40 +527,64 @@ public class LibraryActivity
|
|||||||
|
|
||||||
switch (limiter.type) {
|
switch (limiter.type) {
|
||||||
case MediaUtils.TYPE_ALBUM:
|
case MediaUtils.TYPE_ALBUM:
|
||||||
mSongAdapter.setLimiter(limiter);
|
if (mSongAdapter == null) {
|
||||||
loadSortOrder(mSongAdapter);
|
mPendingLimiters[2] = limiter;
|
||||||
requestRequery(mSongAdapter);
|
} else {
|
||||||
|
mSongAdapter.setLimiter(limiter);
|
||||||
|
loadSortOrder(mSongAdapter);
|
||||||
|
requestRequery(mSongAdapter);
|
||||||
|
}
|
||||||
tab = 2;
|
tab = 2;
|
||||||
break;
|
break;
|
||||||
case MediaUtils.TYPE_ARTIST:
|
case MediaUtils.TYPE_ARTIST:
|
||||||
mAlbumAdapter.setLimiter(limiter);
|
if (mAlbumAdapter == null) {
|
||||||
mSongAdapter.setLimiter(limiter);
|
mPendingLimiters[1] = limiter;
|
||||||
loadSortOrder(mSongAdapter);
|
} else {
|
||||||
loadSortOrder(mAlbumAdapter);
|
mAlbumAdapter.setLimiter(limiter);
|
||||||
requestRequery(mSongAdapter);
|
loadSortOrder(mAlbumAdapter);
|
||||||
requestRequery(mAlbumAdapter);
|
requestRequery(mAlbumAdapter);
|
||||||
|
}
|
||||||
|
if (mSongAdapter == null) {
|
||||||
|
mPendingLimiters[2] = limiter;
|
||||||
|
} else {
|
||||||
|
mSongAdapter.setLimiter(limiter);
|
||||||
|
loadSortOrder(mSongAdapter);
|
||||||
|
requestRequery(mSongAdapter);
|
||||||
|
}
|
||||||
tab = 1;
|
tab = 1;
|
||||||
break;
|
break;
|
||||||
case MediaUtils.TYPE_GENRE:
|
case MediaUtils.TYPE_GENRE:
|
||||||
mSongAdapter.setLimiter(limiter);
|
if (mAlbumAdapter == null) {
|
||||||
mAlbumAdapter.setLimiter(null);
|
mPendingLimiters[1] = limiter;
|
||||||
loadSortOrder(mSongAdapter);
|
} else {
|
||||||
loadSortOrder(mAlbumAdapter);
|
mAlbumAdapter.setLimiter(limiter);
|
||||||
requestRequery(mSongAdapter);
|
loadSortOrder(mAlbumAdapter);
|
||||||
requestRequery(mAlbumAdapter);
|
requestRequery(mAlbumAdapter);
|
||||||
|
}
|
||||||
|
if (mSongAdapter == null) {
|
||||||
|
mPendingLimiters[2] = null;
|
||||||
|
} else {
|
||||||
|
mSongAdapter.setLimiter(limiter);
|
||||||
|
loadSortOrder(mSongAdapter);
|
||||||
|
requestRequery(mSongAdapter);
|
||||||
|
}
|
||||||
tab = 2;
|
tab = 2;
|
||||||
break;
|
break;
|
||||||
case MediaUtils.TYPE_FILE:
|
case MediaUtils.TYPE_FILE:
|
||||||
mFilesAdapter.setLimiter(limiter);
|
if (mFilesAdapter == null) {
|
||||||
requestRequery(mFilesAdapter);
|
mPendingLimiters[5] = limiter;
|
||||||
|
} else {
|
||||||
|
mFilesAdapter.setLimiter(limiter);
|
||||||
|
requestRequery(mFilesAdapter);
|
||||||
|
}
|
||||||
tab = 5;
|
tab = 5;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Unsupported limiter type: " + limiter.type);
|
throw new IllegalArgumentException("Unsupported limiter type: " + limiter.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (switchTab && mTabHost.getCurrentTab() != tab) {
|
if (switchTab && mViewPager.getCurrentItem() != tab) {
|
||||||
mTabHost.setCurrentTab(tab);
|
mViewPager.setCurrentItem(tab);
|
||||||
} else {
|
} else {
|
||||||
updateLimiterViews();
|
updateLimiterViews();
|
||||||
}
|
}
|
||||||
@ -499,44 +639,44 @@ public class LibraryActivity
|
|||||||
{
|
{
|
||||||
String filter = text.toString();
|
String filter = text.toString();
|
||||||
for (LibraryAdapter adapter : mAdapters) {
|
for (LibraryAdapter adapter : mAdapters) {
|
||||||
adapter.setFilter(filter);
|
if (adapter != null) {
|
||||||
requestRequery(adapter);
|
adapter.setFilter(filter);
|
||||||
|
requestRequery(adapter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateLimiterViews()
|
private void updateLimiterViews()
|
||||||
{
|
{
|
||||||
if (mLimiterViews == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
mLimiterViews.removeAllViews();
|
mLimiterViews.removeAllViews();
|
||||||
|
|
||||||
LibraryAdapter adapter = mCurrentAdapter;
|
LibraryAdapter adapter = mCurrentAdapter;
|
||||||
if (adapter == null)
|
Limiter limiterData;
|
||||||
return;
|
if (adapter != null && (limiterData = adapter.getLimiter()) != null) {
|
||||||
|
String[] limiter = limiterData.names;
|
||||||
|
|
||||||
Limiter limiterData = adapter.getLimiter();
|
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||||
if (limiterData == null)
|
params.leftMargin = 5;
|
||||||
return;
|
for (int i = 0; i != limiter.length; ++i) {
|
||||||
String[] limiter = limiterData.names;
|
PaintDrawable background = new PaintDrawable(Color.GRAY);
|
||||||
|
background.setCornerRadius(5);
|
||||||
|
|
||||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
|
TextView view = new TextView(this);
|
||||||
params.leftMargin = 5;
|
view.setSingleLine();
|
||||||
for (int i = 0; i != limiter.length; ++i) {
|
view.setEllipsize(TextUtils.TruncateAt.MARQUEE);
|
||||||
PaintDrawable background = new PaintDrawable(Color.GRAY);
|
view.setText(limiter[i] + " | X");
|
||||||
background.setCornerRadius(5);
|
view.setTextColor(Color.WHITE);
|
||||||
|
view.setBackgroundDrawable(background);
|
||||||
|
view.setLayoutParams(params);
|
||||||
|
view.setPadding(5, 2, 5, 2);
|
||||||
|
view.setTag(i);
|
||||||
|
view.setOnClickListener(this);
|
||||||
|
mLimiterViews.addView(view);
|
||||||
|
}
|
||||||
|
|
||||||
TextView view = new TextView(this);
|
mLimiterScroller.setVisibility(View.VISIBLE);
|
||||||
view.setSingleLine();
|
} else {
|
||||||
view.setEllipsize(TextUtils.TruncateAt.MARQUEE);
|
mLimiterScroller.setVisibility(View.GONE);
|
||||||
view.setText(limiter[i] + " | X");
|
|
||||||
view.setTextColor(Color.WHITE);
|
|
||||||
view.setBackgroundDrawable(background);
|
|
||||||
view.setLayoutParams(params);
|
|
||||||
view.setPadding(5, 2, 5, 2);
|
|
||||||
view.setTag(i);
|
|
||||||
view.setOnClickListener(this);
|
|
||||||
mLimiterViews.addView(view);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -891,40 +1031,6 @@ public class LibraryActivity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Hook up a ListView to this Activity and the supplied adapter
|
|
||||||
*
|
|
||||||
* @param index Where to put the view and adapter in mLists/mAdapters.
|
|
||||||
* @param id The id of the ListView
|
|
||||||
* @param adapter The adapter to hook up.
|
|
||||||
* @param label The text to show on the tab.
|
|
||||||
* @param icon The icon to show on the tab.
|
|
||||||
*/
|
|
||||||
private void setupView(int index, int id, int label, int icon, LibraryAdapter adapter)
|
|
||||||
{
|
|
||||||
ListView view = (ListView)findViewById(id);
|
|
||||||
view.setOnItemClickListener(this);
|
|
||||||
view.setOnCreateContextMenuListener(this);
|
|
||||||
view.setDivider(null);
|
|
||||||
view.setFastScrollEnabled(true);
|
|
||||||
|
|
||||||
view.setAdapter(adapter);
|
|
||||||
if (adapter instanceof MediaAdapter)
|
|
||||||
loadSortOrder((MediaAdapter)adapter);
|
|
||||||
|
|
||||||
Resources res = getResources();
|
|
||||||
String labelRes = res.getString(label);
|
|
||||||
Drawable iconRes = res.getDrawable(icon);
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
|
|
||||||
mTabHost.addTab(mTabHost.newTabSpec(labelRes).setIndicator(null, iconRes).setContent(id));
|
|
||||||
else
|
|
||||||
mTabHost.addTab(mTabHost.newTabSpec(labelRes).setIndicator(labelRes, iconRes).setContent(id));
|
|
||||||
|
|
||||||
mAdapters[index] = adapter;
|
|
||||||
mLists[index] = view;
|
|
||||||
mRequeryNeeded[index] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call addToPlaylist with the results from a NewPlaylistDialog stored in
|
* Call addToPlaylist with the results from a NewPlaylistDialog stored in
|
||||||
* obj.
|
* obj.
|
||||||
@ -1055,7 +1161,9 @@ public class LibraryActivity
|
|||||||
public void onMediaChange()
|
public void onMediaChange()
|
||||||
{
|
{
|
||||||
for (LibraryAdapter adapter : mAdapters) {
|
for (LibraryAdapter adapter : mAdapters) {
|
||||||
postRequestRequery(adapter);
|
if (adapter != null) {
|
||||||
|
postRequestRequery(adapter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1124,17 +1232,6 @@ public class LibraryActivity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTabChanged(String tag)
|
|
||||||
{
|
|
||||||
LibraryAdapter adapter = mAdapters[mTabHost.getCurrentTab()];
|
|
||||||
mCurrentAdapter = adapter;
|
|
||||||
if (mRequeryNeeded[adapter.getMediaType() - 1]) {
|
|
||||||
runQuery(adapter);
|
|
||||||
}
|
|
||||||
updateLimiterViews();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the saved sort mode for the given adapter. The adapter should
|
* Set the saved sort mode for the given adapter. The adapter should
|
||||||
* be re-queried after calling this.
|
* be re-queried after calling this.
|
||||||
@ -1173,10 +1270,45 @@ public class LibraryActivity
|
|||||||
|
|
||||||
// Force a new FastScroller to be created so the scroll sections
|
// Force a new FastScroller to be created so the scroll sections
|
||||||
// are updated.
|
// are updated.
|
||||||
ListView view = (ListView)mTabHost.getCurrentView();
|
ListView view = mLists[mViewPager.getCurrentItem()];
|
||||||
view.setFastScrollEnabled(false);
|
view.setFastScrollEnabled(false);
|
||||||
view.setFastScrollEnabled(true);
|
view.setFastScrollEnabled(true);
|
||||||
|
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(MSG_SAVE_SORT, adapter));
|
mHandler.sendMessage(mHandler.obtainMessage(MSG_SAVE_SORT, adapter));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requery the adapter at the given position if it exists and needs a requery.
|
||||||
|
*
|
||||||
|
* @param position An index in mAdapters.
|
||||||
|
*/
|
||||||
|
public void requeryIfNeeded(int position)
|
||||||
|
{
|
||||||
|
LibraryAdapter adapter = mAdapters[position];
|
||||||
|
if (adapter != null && mRequeryNeeded[position]) {
|
||||||
|
runQuery(adapter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPageScrollStateChanged(int arg0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPageScrolled(int arg0, float arg1, int arg2)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPageSelected(int position)
|
||||||
|
{
|
||||||
|
mCurrentAdapter = mAdapters[position];
|
||||||
|
requeryIfNeeded(position);
|
||||||
|
if (position < ADAPTER_COUNT - 1)
|
||||||
|
requeryIfNeeded(position + 1);
|
||||||
|
if (position > 0)
|
||||||
|
requeryIfNeeded(position - 1);
|
||||||
|
updateLimiterViews();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|