Show lists for all song selector tabs
This commit is contained in:
parent
12af3135f2
commit
4b5d43cced
@ -22,16 +22,16 @@
|
||||
android:id="@android:id/tabcontent"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
<TextView
|
||||
<ListView
|
||||
android:id="@+id/artist_list"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:text="this is another tab" />
|
||||
<TextView
|
||||
android:fastScrollEnabled="true" />
|
||||
<ListView
|
||||
android:id="@+id/album_list"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:text="this is a third tab" />
|
||||
android:fastScrollEnabled="true" />
|
||||
<ListView
|
||||
android:id="@+id/song_list"
|
||||
android:layout_width="fill_parent"
|
||||
|
174
src/org/kreed/vanilla/AbstractAdapter.java
Normal file
174
src/org/kreed/vanilla/AbstractAdapter.java
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Christopher Eby <kreed@kreed.org>
|
||||
*
|
||||
* This file is part of Vanilla Music Player.
|
||||
*
|
||||
* Vanilla Music Player is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Vanilla Music Player is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.kreed.vanilla;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.TypedValue;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.Filter;
|
||||
import android.widget.Filterable;
|
||||
import android.widget.TextView;
|
||||
|
||||
public abstract class AbstractAdapter extends BaseAdapter implements Filterable {
|
||||
protected Context mContext;
|
||||
private List<Song> mObjects;
|
||||
private Song[] mAllObjects;
|
||||
private ArrayFilter mFilter;
|
||||
protected float mSize;
|
||||
protected int mPadding;
|
||||
|
||||
public AbstractAdapter(Context context, Song[] allObjects)
|
||||
{
|
||||
mContext = context;
|
||||
mAllObjects = allObjects;
|
||||
|
||||
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
|
||||
mSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 14, metrics);
|
||||
mPadding = (int)mSize / 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasStableIds()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void updateViews(Song song, TextView upper, TextView lower)
|
||||
{
|
||||
}
|
||||
|
||||
public Filter getFilter()
|
||||
{
|
||||
if (mFilter == null)
|
||||
mFilter = new ArrayFilter();
|
||||
return mFilter;
|
||||
}
|
||||
|
||||
private static final String[] mRanges = { ".", "[2abc]", "[3def]", "[4ghi]", "[5jkl]", "[6mno]", "[7pqrs]", "[8tuv]", "[9wxyz]"};
|
||||
private static Matcher createMatcher(String input)
|
||||
{
|
||||
String patternString = "";
|
||||
for (int i = 0, end = input.length(); i != end; ++i) {
|
||||
char c = input.charAt(i);
|
||||
int value = c - '1';
|
||||
if (value >= 0 && value < 9)
|
||||
patternString += mRanges[value];
|
||||
else
|
||||
patternString += c;
|
||||
}
|
||||
|
||||
return Pattern.compile(patternString, Pattern.CASE_INSENSITIVE).matcher("");
|
||||
}
|
||||
|
||||
private class ArrayFilter extends Filter {
|
||||
@Override
|
||||
protected FilterResults performFiltering(CharSequence filter)
|
||||
{
|
||||
FilterResults results = new FilterResults();
|
||||
|
||||
if (filter == null || filter.length() == 0) {
|
||||
results.values = Arrays.asList(mAllObjects);
|
||||
results.count = mAllObjects.length;
|
||||
} else {
|
||||
String[] words = filter.toString().split("\\s+");
|
||||
Matcher[] matchers = new Matcher[words.length];
|
||||
for (int i = words.length; --i != -1; )
|
||||
matchers[i] = createMatcher(words[i]);
|
||||
|
||||
int count = mAllObjects.length;
|
||||
ArrayList<Song> newValues = new ArrayList<Song>();
|
||||
newValues.ensureCapacity(count);
|
||||
|
||||
outer:
|
||||
for (int i = 0; i != count; ++i) {
|
||||
Song song = mAllObjects[i];
|
||||
|
||||
for (int j = matchers.length; --j != -1; ) {
|
||||
if (song.artist != null && matchers[j].reset(song.artist).find())
|
||||
continue;
|
||||
if (song.album != null && matchers[j].reset(song.album).find())
|
||||
continue;
|
||||
if (song.title != null && matchers[j].reset(song.title).find())
|
||||
continue;
|
||||
continue outer;
|
||||
}
|
||||
|
||||
newValues.add(song);
|
||||
}
|
||||
|
||||
newValues.trimToSize();
|
||||
|
||||
results.values = newValues;
|
||||
results.count = newValues.size();
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected void publishResults(CharSequence constraint, FilterResults results)
|
||||
{
|
||||
mObjects = (List<Song>)results.values;
|
||||
if (results.count == 0)
|
||||
notifyDataSetInvalidated();
|
||||
else
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public int getCount()
|
||||
{
|
||||
if (mObjects == null) {
|
||||
if (mAllObjects == null)
|
||||
return 0;
|
||||
return mAllObjects.length;
|
||||
}
|
||||
return mObjects.size();
|
||||
}
|
||||
|
||||
public Song get(int i)
|
||||
{
|
||||
if (mObjects == null) {
|
||||
if (mAllObjects == null)
|
||||
return null;
|
||||
return mAllObjects[i];
|
||||
}
|
||||
return mObjects.get(i);
|
||||
}
|
||||
|
||||
public Object getItem(int i)
|
||||
{
|
||||
return get(i);
|
||||
}
|
||||
|
||||
public long getItemId(int i)
|
||||
{
|
||||
if (mObjects != null && mObjects.isEmpty())
|
||||
return 0;
|
||||
return get(i).id;
|
||||
}
|
||||
}
|
64
src/org/kreed/vanilla/AlbumAdapter.java
Normal file
64
src/org/kreed/vanilla/AlbumAdapter.java
Normal file
@ -0,0 +1,64 @@
|
||||
package org.kreed.vanilla;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class AlbumAdapter extends AbstractAdapter {
|
||||
private static Song[] filter(Song[] songs)
|
||||
{
|
||||
HashMap<Integer, Song> albums = new HashMap<Integer, Song>();
|
||||
for (int i = songs.length; --i != -1; ) {
|
||||
Song song = songs[i];
|
||||
if (!albums.containsKey(song.albumId))
|
||||
albums.put(song.albumId, song);
|
||||
}
|
||||
Song[] result = albums.values().toArray(new Song[0]);
|
||||
Arrays.sort(result, new Song.AlbumComparator());
|
||||
return result;
|
||||
}
|
||||
|
||||
public AlbumAdapter(Context context, Song[] allSongs)
|
||||
{
|
||||
super(context, filter(allSongs));
|
||||
}
|
||||
|
||||
public View getView(int position, View convertView, ViewGroup parent)
|
||||
{
|
||||
LinearLayout view = null;
|
||||
try {
|
||||
view = (LinearLayout)convertView;
|
||||
} catch (ClassCastException e) {
|
||||
}
|
||||
|
||||
if (view == null) {
|
||||
view = new LinearLayout(mContext);
|
||||
view.setOrientation(LinearLayout.VERTICAL);
|
||||
view.setPadding(mPadding, mPadding, mPadding, mPadding);
|
||||
|
||||
TextView title = new TextView(mContext);
|
||||
title.setSingleLine();
|
||||
title.setTextColor(Color.WHITE);
|
||||
title.setTextSize(mSize);
|
||||
title.setId(0);
|
||||
view.addView(title);
|
||||
|
||||
TextView artist = new TextView(mContext);
|
||||
artist.setSingleLine();
|
||||
artist.setTextSize(mSize);
|
||||
artist.setId(1);
|
||||
view.addView(artist);
|
||||
}
|
||||
|
||||
Song song = get(position);
|
||||
((TextView)view.findViewById(0)).setText(song.album);
|
||||
((TextView)view.findViewById(1)).setText(song.artist);
|
||||
return view;
|
||||
}
|
||||
}
|
68
src/org/kreed/vanilla/ArtistAdapter.java
Normal file
68
src/org/kreed/vanilla/ArtistAdapter.java
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Christopher Eby <kreed@kreed.org>
|
||||
*
|
||||
* This file is part of Vanilla Music Player.
|
||||
*
|
||||
* Vanilla Music Player is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Vanilla Music Player is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.kreed.vanilla;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class ArtistAdapter extends AbstractAdapter {
|
||||
private static Song[] filter(Song[] songs)
|
||||
{
|
||||
HashMap<Integer, Song> artists = new HashMap<Integer, Song>();
|
||||
for (int i = songs.length; --i != -1; ) {
|
||||
Song song = songs[i];
|
||||
if (!artists.containsKey(song.artistId))
|
||||
artists.put(song.artistId, song);
|
||||
}
|
||||
Song[] result = artists.values().toArray(new Song[0]);
|
||||
Arrays.sort(result, new Song.ArtistComparator());
|
||||
return result;
|
||||
}
|
||||
|
||||
public ArtistAdapter(Context context, Song[] allSongs)
|
||||
{
|
||||
super(context, filter(allSongs));
|
||||
}
|
||||
|
||||
public View getView(int position, View convertView, ViewGroup parent)
|
||||
{
|
||||
TextView view = null;
|
||||
try {
|
||||
view = (TextView)convertView;
|
||||
} catch (ClassCastException e) {
|
||||
}
|
||||
|
||||
if (view == null) {
|
||||
view = new TextView(mContext);
|
||||
view.setPadding(mPadding, mPadding, mPadding, mPadding);
|
||||
view.setSingleLine();
|
||||
view.setTextColor(Color.WHITE);
|
||||
view.setTextSize(mSize);
|
||||
}
|
||||
|
||||
view.setText(get(position).artist);
|
||||
return view;
|
||||
}
|
||||
}
|
@ -195,4 +195,18 @@ public class Song implements Parcelable {
|
||||
return a.title.compareTo(b.title);
|
||||
}
|
||||
}
|
||||
|
||||
public static class AlbumComparator implements Comparator<Song> {
|
||||
public int compare(Song a, Song b)
|
||||
{
|
||||
return a.album.compareTo(b.album);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ArtistComparator implements Comparator<Song> {
|
||||
public int compare(Song a, Song b)
|
||||
{
|
||||
return a.artist.compareTo(b.artist);
|
||||
}
|
||||
}
|
||||
}
|
@ -18,47 +18,25 @@
|
||||
|
||||
package org.kreed.vanilla;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.Filter;
|
||||
import android.widget.Filterable;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class SongAdapter extends BaseAdapter implements Filterable {
|
||||
private Context mContext;
|
||||
private List<Song> mObjects;
|
||||
private Song[] mAllObjects;
|
||||
private ArrayFilter mFilter;
|
||||
private float mSize;
|
||||
private int mPadding;
|
||||
|
||||
public SongAdapter(Context context)
|
||||
public class SongAdapter extends AbstractAdapter {
|
||||
private static Song[] sort(Song[] songs)
|
||||
{
|
||||
mContext = context;
|
||||
mAllObjects = Song.getAllSongMetadata();
|
||||
Arrays.sort(mAllObjects, new Song.TitleComparator());
|
||||
|
||||
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
|
||||
mSize = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 14, metrics);
|
||||
mPadding = (int)mSize / 2;
|
||||
Arrays.sort(songs, new Song.TitleComparator());
|
||||
return songs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasStableIds()
|
||||
public SongAdapter(Context context, Song[] allSongs)
|
||||
{
|
||||
return true;
|
||||
super(ContextApplication.getContext(), sort(allSongs));
|
||||
}
|
||||
|
||||
public View getView(int position, View convertView, ViewGroup parent)
|
||||
@ -88,120 +66,9 @@ public class SongAdapter extends BaseAdapter implements Filterable {
|
||||
view.addView(artist);
|
||||
}
|
||||
|
||||
((TextView)view.findViewById(0)).setText(mObjects.get(position).title);
|
||||
((TextView)view.findViewById(1)).setText(mObjects.get(position).artist);
|
||||
Song song = get(position);
|
||||
((TextView)view.findViewById(0)).setText(song.title);
|
||||
((TextView)view.findViewById(1)).setText(song.artist);
|
||||
return view;
|
||||
}
|
||||
|
||||
public Filter getFilter()
|
||||
{
|
||||
if (mFilter == null)
|
||||
mFilter = new ArrayFilter();
|
||||
return mFilter;
|
||||
}
|
||||
|
||||
private static final String[] mRanges = { ".", "[2abc]", "[3def]", "[4ghi]", "[5jkl]", "[6mno]", "[7pqrs]", "[8tuv]", "[9wxyz]"};
|
||||
private static Matcher createMatcher(String input)
|
||||
{
|
||||
String patternString = "";
|
||||
for (int i = 0, end = input.length(); i != end; ++i) {
|
||||
char c = input.charAt(i);
|
||||
int value = c - '1';
|
||||
if (value >= 0 && value < 9)
|
||||
patternString += mRanges[value];
|
||||
else
|
||||
patternString += c;
|
||||
}
|
||||
|
||||
return Pattern.compile(patternString, Pattern.CASE_INSENSITIVE).matcher("");
|
||||
}
|
||||
|
||||
private class ArrayFilter extends Filter {
|
||||
@Override
|
||||
protected FilterResults performFiltering(CharSequence filter)
|
||||
{
|
||||
FilterResults results = new FilterResults();
|
||||
|
||||
if (filter == null || filter.length() == 0) {
|
||||
results.values = Arrays.asList(mAllObjects);
|
||||
results.count = mAllObjects.length;
|
||||
} else {
|
||||
String[] words = filter.toString().split("\\s+");
|
||||
Matcher[] matchers = new Matcher[words.length];
|
||||
for (int i = words.length; --i != -1; )
|
||||
matchers[i] = createMatcher(words[i]);
|
||||
|
||||
int count = mAllObjects.length;
|
||||
ArrayList<Song> newValues = new ArrayList<Song>();
|
||||
newValues.ensureCapacity(count);
|
||||
|
||||
outer:
|
||||
for (int i = 0; i != count; ++i) {
|
||||
Song song = mAllObjects[i];
|
||||
|
||||
for (int j = matchers.length; --j != -1; ) {
|
||||
if (song.artist != null && matchers[j].reset(song.artist).find())
|
||||
continue;
|
||||
if (song.album != null && matchers[j].reset(song.album).find())
|
||||
continue;
|
||||
if (song.title != null && matchers[j].reset(song.title).find())
|
||||
continue;
|
||||
continue outer;
|
||||
}
|
||||
|
||||
newValues.add(song);
|
||||
}
|
||||
|
||||
newValues.trimToSize();
|
||||
|
||||
results.values = newValues;
|
||||
results.count = newValues.size();
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected void publishResults(CharSequence constraint, FilterResults results)
|
||||
{
|
||||
mObjects = (List<Song>)results.values;
|
||||
if (results.count == 0)
|
||||
notifyDataSetInvalidated();
|
||||
else
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public int getCount()
|
||||
{
|
||||
if (mObjects == null) {
|
||||
if (mAllObjects == null)
|
||||
return 0;
|
||||
return mAllObjects.length;
|
||||
}
|
||||
return mObjects.size();
|
||||
}
|
||||
|
||||
public Object getItem(int position)
|
||||
{
|
||||
if (mObjects == null) {
|
||||
if (mAllObjects == null)
|
||||
return 0;
|
||||
return mAllObjects[position];
|
||||
}
|
||||
return mObjects.get(position);
|
||||
}
|
||||
|
||||
public long getItemId(int position)
|
||||
{
|
||||
if (mObjects == null) {
|
||||
if (mAllObjects == null)
|
||||
return 0;
|
||||
return mAllObjects[position].id;
|
||||
}
|
||||
if (mObjects.isEmpty())
|
||||
return 0;
|
||||
return mObjects.get(position).id;
|
||||
}
|
||||
}
|
@ -39,9 +39,11 @@ import android.widget.TextView;
|
||||
|
||||
public class SongSelector extends TabActivity implements AdapterView.OnItemClickListener, TextWatcher, View.OnClickListener {
|
||||
private TabHost mTabHost;
|
||||
private SongAdapter mAdapter;
|
||||
private ListView mListView;
|
||||
private TextView mTextView;
|
||||
private TextView mTextFilter;
|
||||
|
||||
private AbstractAdapter mArtistAdapter;
|
||||
private AbstractAdapter mAlbumAdapter;
|
||||
private AbstractAdapter mSongAdapter;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle)
|
||||
@ -59,14 +61,23 @@ public class SongSelector extends TabActivity implements AdapterView.OnItemClick
|
||||
mTabHost.addTab(mTabHost.newTabSpec("tab_albums").setIndicator(res.getText(R.string.albums), res.getDrawable(R.drawable.tab_albums)).setContent(R.id.album_list));
|
||||
mTabHost.addTab(mTabHost.newTabSpec("tab_songs").setIndicator(res.getText(R.string.songs), res.getDrawable(R.drawable.tab_songs)).setContent(R.id.song_list));
|
||||
|
||||
mAdapter = new SongAdapter(this);
|
||||
Song[] songs = Song.getAllSongMetadata();
|
||||
mArtistAdapter = new ArtistAdapter(this, songs);
|
||||
mAlbumAdapter = new AlbumAdapter(this, songs);
|
||||
mSongAdapter = new SongAdapter(this, songs);
|
||||
|
||||
mListView = (ListView)findViewById(R.id.song_list);
|
||||
mListView.setAdapter(mAdapter);
|
||||
mListView.setOnItemClickListener(this);
|
||||
ListView artistView = (ListView)findViewById(R.id.artist_list);
|
||||
artistView.setAdapter(mArtistAdapter);
|
||||
|
||||
mTextView = (TextView)findViewById(R.id.filter_text);
|
||||
mTextView.addTextChangedListener(this);
|
||||
ListView albumView = (ListView)findViewById(R.id.album_list);
|
||||
albumView.setAdapter(mAlbumAdapter);
|
||||
|
||||
ListView songView = (ListView)findViewById(R.id.song_list);
|
||||
songView.setAdapter(mSongAdapter);
|
||||
songView.setOnItemClickListener(this);
|
||||
|
||||
mTextFilter = (TextView)findViewById(R.id.filter_text);
|
||||
mTextFilter.addTextChangedListener(this);
|
||||
|
||||
View clearButton = findViewById(R.id.clear_button);
|
||||
clearButton.setOnClickListener(this);
|
||||
@ -79,7 +90,7 @@ public class SongSelector extends TabActivity implements AdapterView.OnItemClick
|
||||
inputType = InputType.TYPE_TEXT_VARIATION_FILTER;
|
||||
else
|
||||
inputType = InputType.TYPE_CLASS_TEXT;
|
||||
mTextView.setInputType(inputType);
|
||||
mTextFilter.setInputType(inputType);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -88,8 +99,8 @@ public class SongSelector extends TabActivity implements AdapterView.OnItemClick
|
||||
if (super.onKeyDown(keyCode, event))
|
||||
return true;
|
||||
|
||||
mTextView.requestFocus();
|
||||
return mTextView.onKeyDown(keyCode, event);
|
||||
mTextFilter.requestFocus();
|
||||
return mTextFilter.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
public void onItemClick(AdapterView<?> list, View view, int pos, long id)
|
||||
@ -109,11 +120,11 @@ public class SongSelector extends TabActivity implements AdapterView.OnItemClick
|
||||
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count)
|
||||
{
|
||||
mAdapter.getFilter().filter(s);
|
||||
mSongAdapter.getFilter().filter(s);
|
||||
}
|
||||
|
||||
public void onClick(View view)
|
||||
{
|
||||
mTextView.setText("");
|
||||
mTextFilter.setText("");
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user