package com.aliao.android.hipster; import android.content.Context; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; import android.widget.ListView; import android.widget.TextView; import com.actionbarsherlock.app.SherlockListActivity; import com.parse.ParseImageView; import com.parse.ParseObject; import com.parse.ParseQuery; import com.parse.ParseQueryAdapter; import com.parse.ParseUser; import java.util.HashMap; import java.util.List; /** * Leaderboard activity for showing all Hipster rankings and scores. */ public class LeaderBoardActivity extends SherlockListActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Create an Parse API adapter to query user and score tables, ordered by score. ParseQueryAdapter.QueryFactory<ParseObject> factory = new ParseQueryAdapter.QueryFactory<ParseObject>() { public ParseQuery<ParseObject> create() { ParseQuery<ParseObject> leaderQuery = ParseQuery.getQuery( ParseHipsterActions.Score.SCORE_CLASS); leaderQuery.orderByDescending(ParseHipsterActions.Score.SCORE_FIELD); leaderQuery.include(ParseHipsterActions.Score.USER_FIELD); return leaderQuery; } }; ParseUserAdapter adapter = new ParseUserAdapter(this, factory); // Set the ListView adapter. ListView listView = getListView(); listView.setAdapter(adapter); listView.setCacheColorHint(Color.TRANSPARENT); } private static class ParseUserAdapter extends ParseQueryAdapter<ParseObject> { private final Context context; // Map from user score object id to overall rank (1-based). Needed because we can't easily add an // additional rank field to the current database object. private final HashMap<String, Integer> userRankingMap; // Placeholder image to display before the user photo is downloaded. private final Drawable userPhotoPlaceholder; private int loadIconPadding; public ParseUserAdapter(Context context, QueryFactory<ParseObject> queryFactory) { super(context, queryFactory); this.context = context; // Save the placeholder reference for reuse. userPhotoPlaceholder = context.getResources().getDrawable(R.drawable.ic_person_light); // Generate the user rankings. Parse will call onLoaded for each row in the order of the // query, so we infer the rank. userRankingMap = new HashMap<String, Integer>(); addOnQueryLoadListener(new ParseQueryAdapter.OnQueryLoadListener<ParseObject>() { @Override public void onLoading() { // TODO(aliao): Maybe put in a spinner. } @Override public void onLoaded(List<ParseObject> parseUsers, Exception e) { // Read the current size because Parse supports pagination. int currentRank = userRankingMap.size() + 1; for (int i = 0; i < parseUsers.size(); i++) { userRankingMap.put(parseUsers.get(i).getObjectId(), currentRank + i); } } }); // Calculate padding based on current density. loadIconPadding = context.getResources().getDimensionPixelSize(R.dimen.leaderboard_load_more_item_padding); } @Override public View getItemView(ParseObject scoreObject, View view, ViewGroup parent) { // Get or create the view holder. if (view == null) { view = View.inflate(context, R.layout.leaderboard_list_item, null); ViewHolder viewHolder = new ViewHolder(); viewHolder.scoreText = (TextView) view.findViewById(R.id.score); viewHolder.nameText = (TextView) view.findViewById(R.id.name); viewHolder.rankingText = (TextView) view.findViewById(R.id.rank); viewHolder.imageView = (ParseImageView) view.findViewById(R.id.photo); view.setTag(viewHolder); } ViewHolder viewHolder = (ViewHolder) view.getTag(); // Show the score and rank. viewHolder.scoreText.setText(scoreObject.getInt(ParseHipsterActions.Score.SCORE_FIELD) + " " + context.getString(R.string.points)); int rank = userRankingMap.get(scoreObject.getObjectId()); viewHolder.rankingText.setText(StringUtils.getRankInString(rank)); // Show the name. ParseUser user = scoreObject.getParseUser(ParseHipsterActions.Score.USER_FIELD); viewHolder.nameText.setText(user.getUsername()); // ParseImageView handles loading image asynchronously and cleaning up resources ParseImageView imageView = viewHolder.imageView; imageView.setParseFile(user.getParseFile(ParseHipsterActions.User.PHOTO_KEY)); imageView.loadInBackground(); imageView.setPlaceholder(userPhotoPlaceholder); return view; } @Override public View getNextPageView(View v, ViewGroup parent) { View loadMoreView = super.getNextPageView(v, parent); // Add more padding to allow bigger touch area. loadMoreView.setPadding(loadIconPadding, loadIconPadding, loadIconPadding, loadIconPadding); return loadMoreView; } // ViewHolder pattern to avoid extra tree traversal. private static class ViewHolder { TextView scoreText; TextView rankingText; TextView nameText; ParseImageView imageView; } } }