Skip to content

Commit

Permalink
Created track list activity and fragment.
Browse files Browse the repository at this point in the history
  • Loading branch information
williamwong committed Jun 20, 2015
1 parent df061e0 commit c0d1770
Show file tree
Hide file tree
Showing 12 changed files with 489 additions and 4 deletions.
11 changes: 10 additions & 1 deletion app/src/main/AndroidManifest.xml
Expand Up @@ -12,13 +12,22 @@
<activity
android:name=".activities.MainActivity"
android:label="@string/app_name"
android:windowSoftInputMode="stateUnchanged">
android:launchMode="singleTop"
android:windowSoftInputMode="stateUnchanged" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".activities.TrackActivity"
android:label="@string/title_activity_track"
android:parentActivityName=".activities.MainActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="org.williamwong.spotifystreamer.activities.MainActivity" />
</activity>
</application>

</manifest>
@@ -1,13 +1,16 @@
package org.williamwong.spotifystreamer.activities;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;

import org.williamwong.spotifystreamer.R;
import org.williamwong.spotifystreamer.fragments.ArtistFragment;
import org.williamwong.spotifystreamer.fragments.TrackFragment;

public class MainActivity extends AppCompatActivity {
public class MainActivity extends AppCompatActivity implements ArtistFragment.Callbacks{

@Override
protected void onCreate(Bundle savedInstanceState) {
Expand Down Expand Up @@ -37,4 +40,12 @@ public boolean onOptionsItemSelected(MenuItem item) {

return super.onOptionsItemSelected(item);
}

@Override
public void onArtistSelected(String spotifyId, String artistName) {
Intent trackIntent = new Intent(this, TrackActivity.class);
trackIntent.putExtra(TrackFragment.SPOTIFY_ID, spotifyId);
trackIntent.putExtra(TrackFragment.ARTIST_NAME, artistName);
startActivity(trackIntent);
}
}
@@ -0,0 +1,59 @@
package org.williamwong.spotifystreamer.activities;

import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;

import org.williamwong.spotifystreamer.R;
import org.williamwong.spotifystreamer.fragments.TrackFragment;

public class TrackActivity extends AppCompatActivity {

private static final String TRACK_FRAGMENT_TAG = "trackFragment";
private TrackFragment mTrackFragment;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_track);

String spotifyId = getIntent().getStringExtra(TrackFragment.SPOTIFY_ID);
String artistName = getIntent().getStringExtra(TrackFragment.ARTIST_NAME);

if (savedInstanceState != null) {
mTrackFragment = (TrackFragment) getSupportFragmentManager().findFragmentByTag(TRACK_FRAGMENT_TAG);
} else if (mTrackFragment == null) {
mTrackFragment = TrackFragment.newInstance(spotifyId, artistName);
}

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.tracksContainer, mTrackFragment, TRACK_FRAGMENT_TAG);
ft.commit();

}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_track, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();

//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}

return super.onOptionsItemSelected(item);
}
}
@@ -0,0 +1,61 @@
package org.williamwong.spotifystreamer.adapters;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.squareup.picasso.Picasso;

import org.williamwong.spotifystreamer.R;
import org.williamwong.spotifystreamer.models.TrackModel;

import java.util.List;

/**
* Created by w.wong on 6/19/2015.
*/
public class TrackAdapter extends ArrayAdapter<TrackModel> {

public TrackAdapter(Context context, List<TrackModel> objects) {
super(context, 0, objects);
}

private static class ViewHolder {
TextView trackNameTextView;
TextView albumNameTextView;
ImageView trackThumbnailImageView;

public ViewHolder(View v) {
trackNameTextView = (TextView) v.findViewById(R.id.trackNameTextView);
albumNameTextView = (TextView) v.findViewById(R.id.albumNameTextView);
trackThumbnailImageView = (ImageView) v.findViewById(R.id.trackThumbnailImageView);
}
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
TrackModel track = getItem(position);

ViewHolder viewHolder;
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item_track, parent, false);
viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}

viewHolder.trackNameTextView.setText(track.getTrackName());
viewHolder.albumNameTextView.setText(track.getAlbumName());
Picasso.with(getContext())
.load(track.getImageUrl())
.fit().centerCrop()
.into(viewHolder.trackThumbnailImageView);

return convertView;
}
}
@@ -1,5 +1,6 @@
package org.williamwong.spotifystreamer.fragments;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
Expand All @@ -11,6 +12,7 @@
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
Expand Down Expand Up @@ -44,6 +46,7 @@ public class ArtistFragment extends Fragment {
private SpotifyService mSpotify = new SpotifyApi().getService();
private ArrayList<ArtistModel> mArtistModels;
private ArtistAdapter mArtistAdapter;
private Callbacks mCallbacks;

public ArtistFragment() {
}
Expand All @@ -63,6 +66,15 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
ListView artistsListView = (ListView) view.findViewById(R.id.artistsListView);
mArtistAdapter = new ArtistAdapter(getActivity(), mArtistModels);
artistsListView.setAdapter(mArtistAdapter);
artistsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (mCallbacks != null) {
ArtistModel artist = mArtistModels.get(position);
mCallbacks.onArtistSelected(artist.getSpotifyId(), artist.getName());
}
}
});

EditText searchArtistEditText = (EditText) view.findViewById(R.id.searchArtistEditText);
searchArtistEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
Expand Down Expand Up @@ -145,7 +157,25 @@ public void onSaveInstanceState(Bundle outState) {
outState.putParcelableArrayList(ARTIST_MODELS_KEY, mArtistModels);
}

@Override
public void onAttach(Activity activity) {
super.onAttach(activity);

if (!(activity instanceof Callbacks)) {
throw new IllegalStateException("Activity must implement fragment's callbacks.");
}

mCallbacks = (Callbacks) activity;
}

@Override
public void onDetach() {
super.onDetach();

mCallbacks = null;
}

public interface Callbacks {
void onArtistSelected(String id);
void onArtistSelected(String spotifyId, String artistName);
}
}
@@ -0,0 +1,148 @@
package org.williamwong.spotifystreamer.fragments;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;

import org.williamwong.spotifystreamer.R;
import org.williamwong.spotifystreamer.adapters.TrackAdapter;
import org.williamwong.spotifystreamer.models.TrackModel;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import kaaes.spotify.webapi.android.SpotifyApi;
import kaaes.spotify.webapi.android.SpotifyService;
import kaaes.spotify.webapi.android.models.Image;
import kaaes.spotify.webapi.android.models.Track;
import kaaes.spotify.webapi.android.models.Tracks;
import retrofit.Callback;
import retrofit.RetrofitError;
import retrofit.client.Response;

/**
* A fragment containing a list of top ten tracks from an artist.
* TODO Add artist name to ActionBar subtitle
*/
public class TrackFragment extends Fragment {


public static final String TRACK_MODELS_KEY = "trackModels";
public static final String SPOTIFY_ID = "spotifyId";
public static final String ARTIST_NAME = "artistName";
private static final int MIN_THUMBNAIL_WIDTH = 200;

private SpotifyService mSpotify = new SpotifyApi().getService();
private ArrayList<TrackModel> mTrackModels;
private TrackAdapter mTrackAdapter;
private String mSpotifyId;
private String mArtistName;

public TrackFragment() {
}

public static TrackFragment newInstance(String spotifyId, String artistName) {
TrackFragment trackFragment = new TrackFragment();
Bundle args = new Bundle();
args.putSerializable(SPOTIFY_ID, spotifyId);
args.putSerializable(ARTIST_NAME, artistName);
trackFragment.setArguments(args);
return trackFragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

if (getArguments().containsKey(SPOTIFY_ID)) {
mSpotifyId = getArguments().getString(SPOTIFY_ID);
}
if (getArguments().containsKey(ARTIST_NAME)) {
mArtistName = getArguments().getString(ARTIST_NAME);
}
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_track, container, false);

if (savedInstanceState != null &&
savedInstanceState.getParcelableArrayList(TRACK_MODELS_KEY) != null) {
mTrackModels = savedInstanceState.getParcelableArrayList(TRACK_MODELS_KEY);
} else {
mTrackModels = new ArrayList<>();
searchTracks(mSpotifyId);
}

ListView trackListView = (ListView) view.findViewById(R.id.tracksListView);
mTrackAdapter = new TrackAdapter(getActivity(), mTrackModels);
trackListView.setAdapter(mTrackAdapter);

return view;
}

private void searchTracks(String mSpotifyId) {
Map<String, Object> options = new HashMap<>();
options.put("country", "US");
mSpotify.getArtistTopTrack(mSpotifyId, options, new Callback<Tracks>() {
Handler handler = new Handler(Looper.getMainLooper());
@Override
public void success(final Tracks tracks, Response response) {
handler.post(new Runnable() {
@Override
public void run() {
updateTracks(tracks.tracks);
}
});
}

@Override
public void failure(RetrofitError error) {

}
});
}

private void updateTracks(List<Track> tracks) {
mTrackModels.clear();
for (Track track : tracks) {
TrackModel trackModel = new TrackModel();
trackModel.setTrackName(track.name);
trackModel.setAlbumName(track.album.name);

List<Image> images = track.album.images;
if(images != null && !images.isEmpty()) {
int imageIndex = 0;
for (int i = 0; i < images.size(); i++) {
boolean isLast = (i + 1 == images.size());
if (isLast) {
imageIndex = i;
break;
} else if (images.get(i + 1).width < MIN_THUMBNAIL_WIDTH) {
imageIndex = i;
break;
}
}
trackModel.setImageUrl(images.get(imageIndex).url);
}
// TODO set placeholder image
mTrackModels.add(trackModel);
}

mTrackAdapter.notifyDataSetChanged();
}

@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelableArrayList(TRACK_MODELS_KEY, mTrackModels);
}
}

0 comments on commit c0d1770

Please sign in to comment.