Java tutorial
/* This file is part of RateBeer For Android. RateBeer for Android is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. RateBeer for Android 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. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with RateBeer for Android. If not, see <http://www.gnu.org/licenses/>. */ package com.ratebeer.android.gui.fragments; import java.io.File; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.os.Messenger; import android.provider.MediaStore; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.text.Html; import android.text.method.ScrollingMovementMethod; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.Button; import android.widget.ImageView; import android.widget.ListView; import android.widget.RatingBar; import android.widget.TextView; import com.commonsware.cwac.merge.MergeAdapter; import com.googlecode.androidannotations.annotations.AfterViews; import com.googlecode.androidannotations.annotations.EFragment; import com.googlecode.androidannotations.annotations.FragmentArg; import com.googlecode.androidannotations.annotations.InstanceState; import com.googlecode.androidannotations.annotations.OptionsItem; import com.googlecode.androidannotations.annotations.OptionsMenu; import com.googlecode.androidannotations.annotations.ViewById; import com.ratebeer.android.R; import com.ratebeer.android.api.ApiMethod; import com.ratebeer.android.api.CommandFailureResult; import com.ratebeer.android.api.CommandSuccessResult; import com.ratebeer.android.api.UserSettings; import com.ratebeer.android.api.command.GetBeerAvailabilityCommand; import com.ratebeer.android.api.command.GetBeerDetailsCommand; import com.ratebeer.android.api.command.GetBeerDetailsCommand.BeerDetails; import com.ratebeer.android.api.command.GetBeerPhotoAvailableCommand; import com.ratebeer.android.api.command.GetRatingsCommand; import com.ratebeer.android.api.command.GetRatingsCommand.BeerRating; import com.ratebeer.android.api.command.GetUserTicksCommand; import com.ratebeer.android.api.command.GetUserTicksCommand.UserTick; import com.ratebeer.android.api.command.ImageUrls; import com.ratebeer.android.api.command.PostRatingCommand; import com.ratebeer.android.api.command.SearchPlacesCommand.PlaceSearchResult; import com.ratebeer.android.api.command.Style; import com.ratebeer.android.app.RateBeerForAndroid; import com.ratebeer.android.gui.components.PosterService; import com.ratebeer.android.gui.components.RateBeerFragment; import com.ratebeer.android.gui.components.helpers.ActivityUtil; import com.ratebeer.android.gui.components.helpers.ArrayAdapter; import com.ratebeer.android.gui.components.helpers.NfcHelper.NdefUriProvider; import com.ratebeer.android.gui.fragments.AddToCellarFragment.CellarType; import com.viewpagerindicator.TabPageIndicator; @EFragment(R.layout.fragment_beerview) @OptionsMenu({ R.menu.refresh, R.menu.share }) public class BeerViewFragment extends RateBeerFragment implements NdefUriProvider { private static final String DECIMAL_FORMATTER = "%.1f"; private static final int UNKNOWN_RATINGS_COUNT = -1; private static final int ACTIVITY_CAMERA = 0; private static final int ACTIVITY_PICKPHOTO = 1; @FragmentArg @InstanceState protected int beerId; @FragmentArg @InstanceState protected String beerName = null; @FragmentArg @InstanceState protected int ratingsCount = UNKNOWN_RATINGS_COUNT; @InstanceState protected BeerDetails details = null; @InstanceState protected Boolean photoIsAvailable = null; @InstanceState protected ArrayList<BeerRating> ownRatings = null; @InstanceState protected ArrayList<UserTick> ownTicks = null; @InstanceState protected ArrayList<BeerRating> recentRatings = new ArrayList<BeerRating>(); @InstanceState protected ArrayList<PlaceSearchResult> availability = new ArrayList<PlaceSearchResult>(); @ViewById protected ViewPager pager; @ViewById protected TabPageIndicator titles; private View scoreCard; @ViewById(R.id.name) protected TextView nameText; private TextView noscoreyetText, scoreText, stylepctlText, ratingsText; @ViewById(R.id.description) protected TextView descriptionText; @ViewById(R.id.abvstyle) protected Button abvstyleButton; @ViewById(R.id.brewername) protected Button brewernameButton; private Button rateThisButton, drinkingThisButton, addAvailabilityButton, havethisButton, wantthisButton, uploadphotoButton; private View ownratingRow, ownratinglabel, ticklabel, otherratingslabel; private TextView ownratingTotal, ownratingAroma, ownratingAppearance, ownratingTaste, ownratingPalate, ownratingOverall, ownratingUsername, ownratingComments; private RatingBar tickBar; private ListView availabilityView; private TextView availabilityEmpty; private BeerRatingsAdapter recentRatingsAdapter; @ViewById(R.id.image) protected ImageView imageView; private DateFormat displayDateFormat; public BeerViewFragment() { } @AfterViews public void init() { displayDateFormat = android.text.format.DateFormat.getDateFormat(getActivity()); pager.setAdapter(new BeerPagerAdapter()); titles.setViewPager(pager); if (details != null) { publishDetails(details); publishPhotoAvailability(photoIsAvailable); refreshImage(); // Note: always requested, although the image is cached publishOwnRating(ownRatings); publishOwnTick(ownTicks); setRatings(recentRatings); setAvailability(availability); } else { refreshDetails(); refreshPhotoAvailability(); refreshImage(); refreshOwnRating(); refreshOwnTick(); refreshRatings(); refreshAvailability(); } } @OptionsItem(R.id.menu_refresh) protected void onRefresh() { refreshDetails(); refreshPhotoAvailability(); refreshImage(); refreshOwnRating(); refreshOwnTick(); refreshRatings(); refreshAvailability(); } @OptionsItem(R.id.menu_share) protected void onShare() { // Start a share intent for this beer Intent s = new Intent(Intent.ACTION_SEND); s.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); s.setType("text/plain"); s.putExtra(Intent.EXTRA_TEXT, getString(R.string.details_share, beerName, beerId)); startActivity(Intent.createChooser(s, getString(R.string.details_sharebeer))); } private void refreshImage() { RateBeerForAndroid.getImageCache(getActivity()).displayImage(ImageUrls.getBeerPhotoUrl(beerId), imageView); imageView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onShowFullScreenPhoto(); } }); } private void refreshDetails() { execute(new GetBeerDetailsCommand(getUser(), beerId)); } private void refreshPhotoAvailability() { execute(new GetBeerPhotoAvailableCommand(getUser(), beerId)); } private void refreshOwnRating() { if (getUser() != null) { execute(new GetRatingsCommand(getUser(), beerId, getUser().getUserID())); } } private void refreshOwnTick() { if (getUser() != null) { // TODO: Unfortunately we have to retrieve all the user's ticks, since the RB API is limited... execute(new GetUserTicksCommand(getUser())); } } private void refreshRatings() { execute(new GetRatingsCommand(getUser(), beerId)); } private void refreshAvailability() { execute(new GetBeerAvailabilityCommand(getUser(), beerId)); availabilityEmpty.setText(R.string.details_noavailability); } protected void onRateBeerClick() { // Get the original rating if we already rated this beer if (ownRatings != null && ownRatings.size() > 0) { BeerRating ownRating = ownRatings.get(0); // Start new rating fragment, with pre-populated fields SimpleDateFormat df = new SimpleDateFormat("M/d/yyyy h:mm:ss a", Locale.US); load(RateFragment_.buildFromConcrete(beerName, beerId, ownRating.ratingId, df.format(ownRating.timeEntered), ownRating.appearance, ownRating.aroma, ownRating.flavor, ownRating.mouthfeel, ownRating.overall, ownRating.comments)); } else { // Start new rating fragment load(RateFragment_.buildFromBeer(beerName, beerId)); } } protected void onTickBarUpdated(float rating) { int newRating = (int) rating; if (rating <= 0.1) { // Force everything below 0.1 (since the user might not have the finger all the way at 0) as a tick removal newRating = -1; } if (ownTicks != null && ownTicks.size() > 0 && ownTicks.get(0).liked == rating) { // No need to update return; } // Update the user's tick status of this beer Intent i = new Intent(PosterService.ACTION_POSTTICK); i.putExtra(PosterService.EXTRA_BEERID, beerId); i.putExtra(PosterService.EXTRA_BEERNAME, beerName); i.putExtra(PosterService.EXTRA_USERID, getUser().getUserID()); i.putExtra(PosterService.EXTRA_LIKED, newRating); i.putExtra(PosterService.EXTRA_MESSENGER, new Messenger(new Handler() { @Override public void handleMessage(Message msg) { // Callback from the poster service; just refresh the tick status refreshOwnTick(); } })); getActivity().startService(i); } protected void onDrinkingBeerClick() { // Update now drinking status Intent i = new Intent(PosterService.ACTION_SETDRINKINGSTATUS); i.putExtra(PosterService.EXTRA_NEWSTATUS, beerName); i.putExtra(PosterService.EXTRA_BEERID, beerId); getActivity().startService(i); // Manually set the last update date of the drinking status back, so a visit to the home screen refreshes it getSettings().saveUserSettings(new UserSettings(getUser().getUserID(), getUser().getUsername(), getUser().getPassword(), getUser().getDrinkingStatus(), getUser().isPremium(), new Date(1))); } protected void onShowFullScreenPhoto() { // Open the photo in a separate full screen image fragment load(FullScreenImageFragment_.builder().photoLowResUrl(ImageUrls.getBeerPhotoUrl(beerId)) .photoHighResUrl(ImageUrls.getBeerPhotoHighResUrl(beerId)).build()); } protected void onAddAvailability() { // Open availability adding screen load(AddAvailabilityFragment_.builder().beerId(beerId).beerName(beerName).build()); } protected void onWantOrHaveBeerClick(AddToCellarFragment.CellarType cellarType) { // Open add to cellar screen load(AddToCellarFragment_.builder().beerId(beerId).beerName(beerName).cellarType(cellarType).build()); } protected void onStyleClick() { // Infer style from the name; this is a bit of a hack but the RateBeer API doesn't give the style ID :( if (details == null) { return; } Style style = null; for (Style s : Style.ALL_STYLES.values()) { if (s.getName().equals(details.beerStyle)) { style = s; break; } } if (style == null) { Log.d(com.ratebeer.android.gui.components.helpers.Log.LOG_NAME, "Wanted to get the beer style of " + beerName + " (#" + beerId + "), which is " + details.beerStyle + " but can't find it in our own list."); publishException(null, getString(R.string.error_stylenotfound)); return; } // Open style details screen load(StyleViewFragment_.builder().style(style).build()); } protected void onBrewerClick() { load(BrewerViewFragment_.builder().brewerId(details.brewerId).build()); } private void onReviewClick(Integer userId, String username) { // Start the user details screen load(UserViewFragment_.builder().userName(username).userId(userId).build()); } protected void onStartPhotoUpload() { new ChoosePhotoFragment(this).show(getFragmentManager(), ""); } public void onStartPhotoSnapping() { // Start an intent to snap a picture // http://stackoverflow.com/questions/1910608/android-action-image-capture-intent try { if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { File file = new File( RateBeerForAndroid.DEFAULT_FILES_DIR + "/photos/" + Integer.toString(beerId) + ".jpg"); if (!file.exists()) { file.getParentFile().mkdirs(); file.createNewFile(); } Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); i.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file)); startActivityForResult(i, ACTIVITY_CAMERA); } else { publishException(null, getString(R.string.error_nocamera)); } } catch (Exception e) { publishException(null, getString(R.string.error_nocamera)); } } public void onStartPhotoPicking() { Intent i = new Intent(Intent.ACTION_GET_CONTENT); i.setType("image/*"); startActivityForResult(i, ACTIVITY_PICKPHOTO); } // Taken from http://stackoverflow.com/a/4470069/243165 private String getImagePath(Uri uri) { String[] projection = { MediaStore.Images.Media.DATA }; Cursor cursor = getActivity().managedQuery(uri, projection, null, null, null); if (cursor != null) { int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); return cursor.getString(column_index); } else return null; } // NOTE: The @OnActivityResult annotation doesn't work (yet) on Fragments @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); File photo = null; switch (requestCode) { case ACTIVITY_PICKPHOTO: if (data != null && data.getData() != null) { String selectedImagePath = getImagePath(data.getData()); if (selectedImagePath != null) { photo = new File(selectedImagePath); } else { photo = new File(data.getData().getPath()); } } // Note the fall through case ACTIVITY_CAMERA: if (photo == null) { photo = new File( RateBeerForAndroid.DEFAULT_FILES_DIR + "/photos/" + Integer.toString(beerId) + ".jpg"); } if (resultCode == Activity.RESULT_OK && photo != null && photo.exists()) { // Start an upload task for this photo Intent i = new Intent(PosterService.ACTION_UPLOADBEERPHOTO); i.putExtra(PosterService.EXTRA_BEERID, beerId); i.putExtra(PosterService.EXTRA_BEERNAME, beerName); i.putExtra(PosterService.EXTRA_PHOTO, photo); getActivity().startService(i); } break; } } private void onPlaceClick(Integer placeId, String placeName) { // Start the user details screen load(PlaceViewFragment_.builder().placeId(placeId).build()); } @Override public void onTaskSuccessResult(CommandSuccessResult result) { if (result.getCommand().getMethod() == ApiMethod.GetBeerDetails) { publishDetails(((GetBeerDetailsCommand) result.getCommand()).getDetails()); } else if (result.getCommand().getMethod() == ApiMethod.GetUserTicks) { publishOwnTick(((GetUserTicksCommand) result.getCommand()).getUserTicks()); } else if (result.getCommand().getMethod() == ApiMethod.GetBeerRatings) { GetRatingsCommand grc = (GetRatingsCommand) result.getCommand(); if (grc.getForUserId() == GetRatingsCommand.NO_USER) { publishRatings(grc.getRatings()); } else { publishOwnRating(grc.getRatings()); } } else if (result.getCommand().getMethod() == ApiMethod.GetBeerAvailability) { publishAvailability(((GetBeerAvailabilityCommand) result.getCommand()).getPlaces()); } else if (result.getCommand().getMethod() == ApiMethod.GetBeerPhotoAvailable) { publishPhotoAvailability(((GetBeerPhotoAvailableCommand) result.getCommand()).hasPhotoAvailable()); } } private void publishPhotoAvailability(Boolean photoIsAvailable) { this.photoIsAvailable = photoIsAvailable; if (photoIsAvailable == null) { return; } // Show the beer photo upload field, if appropriate setPhotoAvailability(photoIsAvailable); } private void publishDetails(BeerDetails details) { this.details = details; if (details == null) { return; } // Update the beer name and title this.beerName = details.beerName; // Show details setDetails(details); } private void publishOwnRating(ArrayList<BeerRating> ownRatings) { this.ownRatings = ownRatings; // Show the rating setOwnRating(this.ownRatings); } private void publishOwnTick(ArrayList<UserTick> allUserTicks) { if (allUserTicks == null) { this.ownTicks = null; setOwnTick(null); return; } // Unfortunately the API can only send all of the user's ticks at once so we have to find the current beer this.ownTicks = new ArrayList<GetUserTicksCommand.UserTick>(); for (UserTick userTick : allUserTicks) { if (userTick.beerdId == beerId) { // Creat a list with only this beer's user tick in it this.ownTicks.add(userTick); break; } } // Show the tick setOwnTick(this.ownTicks); } private void publishRatings(ArrayList<BeerRating> ratings) { this.recentRatings = ratings; setRatings(ratings); } private void publishAvailability(ArrayList<PlaceSearchResult> places) { this.availability = places; setAvailability(availability); } public void setRatings(ArrayList<BeerRating> ratings) { // First remove our own rating, if it is in there (otherwise it would show twice) if (getUser() != null) { BeerRating toRemove = null; for (BeerRating rating : ratings) { if (rating.userId == getUser().getUserID()) { toRemove = rating; break; } } if (toRemove != null) { ratings.remove(toRemove); } } // Show the new list of ratings otherratingslabel.setVisibility(View.VISIBLE); recentRatingsAdapter.replace(ratings); } public void setAvailability(ArrayList<PlaceSearchResult> places) { // Show the new list of places that have this beer available if (availabilityView.getAdapter() == null) { availabilityView.setAdapter(new AvailabilityAdapter(getActivity(), places)); } else { ((AvailabilityAdapter) availabilityView.getAdapter()).replace(places); } } /** * Overrides the different textual details about this beer, as shown as header * @param details The beer details object containing the texts to show */ public void setDetails(BeerDetails details) { nameText.setText(details.beerName); brewernameButton.setText(getString(R.string.details_bybrewer, details.brewerName)); brewernameButton.setVisibility(View.VISIBLE); boolean noScoreYet = details.overallPerc == GetBeerDetailsCommand.NO_SCORE_YET; noscoreyetText.setVisibility(noScoreYet ? View.VISIBLE : View.GONE); scoreCard.setVisibility(noScoreYet ? View.GONE : View.VISIBLE); scoreText.setText(String.format("%.0f", details.overallPerc)); stylepctlText.setText(String.format("%.0f", details.stylePerc)); ratingsText.setText(ratingsCount == UNKNOWN_RATINGS_COUNT ? "?" : Integer.toString(ratingsCount)); abvstyleButton.setText(getString(R.string.details_abvstyle, details.beerStyle, String.format(DECIMAL_FORMATTER, details.alcohol))); abvstyleButton.setVisibility(View.VISIBLE); descriptionText.setText(Html.fromHtml(details.description == null || details.description.equals("") ? getString(R.string.details_nodescription) : details.description.replace("\n", "<br />"))); descriptionText.setMovementMethod(new ScrollingMovementMethod()); // Only show the buttons bar if we have a signed in user drinkingThisButton.setVisibility(getUser() != null ? View.VISIBLE : View.GONE); addAvailabilityButton.setVisibility(getUser() != null ? View.VISIBLE : View.GONE); // Only show the cellar buttons bar if we have a signed in premium user wantthisButton.setVisibility(getUser() != null && getUser().isPremium() ? View.VISIBLE : View.GONE); havethisButton.setVisibility(getUser() != null && getUser().isPremium() ? View.VISIBLE : View.GONE); } public void setPhotoAvailability(Boolean photoIsAvailable) { uploadphotoButton.setVisibility(photoIsAvailable != null && !photoIsAvailable ? View.VISIBLE : View.GONE); } public void setOwnRating(ArrayList<BeerRating> ownRatings) { if (ownRatings == null) { // Still loading and we didn't have a retained rating object return; } if (ownRatings.size() > 0) { BeerRating ownRating = ownRatings.get(0); ownratinglabel.setVisibility(View.VISIBLE); ownratingRow.setVisibility(View.VISIBLE); ownratingTotal.setText(Float.toString(PostRatingCommand.calculateTotal(ownRating.aroma, ownRating.appearance, ownRating.flavor, ownRating.mouthfeel, ownRating.overall))); ownratingAroma.setText(Integer.toString(ownRating.aroma)); ownratingAppearance.setText(Integer.toString(ownRating.appearance)); ownratingTaste.setText(Integer.toString(ownRating.flavor)); ownratingPalate.setText(Integer.toString(ownRating.mouthfeel)); ownratingOverall.setText(Integer.toString(ownRating.overall)); ownratingUsername.setText(ownRating.userName + " (" + Integer.toString(ownRating.rateCount) + ")"); ownratingComments.setText(ownRating.comments + (ownRating.timeUpdated != null ? " (" + displayDateFormat.format(ownRating.timeUpdated) + ")" : ownRating.timeEntered != null ? " (" + displayDateFormat.format(ownRating.timeEntered) + ")" : "")); rateThisButton.setText(R.string.details_viewrerate); } else { ownratinglabel.setVisibility(View.GONE); ownratingRow.setVisibility(View.GONE); rateThisButton.setText(R.string.details_ratethis); } rateThisButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onRateBeerClick(); } }); } public void setOwnTick(ArrayList<UserTick> ownTicks) { if (ownTicks == null) { // Still loading and we didn't have a retained ticks object return; } if (ownTicks.size() > 0) { UserTick ownTick = ownTicks.get(0); tickBar.setRating(ownTick.liked); } ticklabel.setVisibility(View.VISIBLE); tickBar.setVisibility(View.VISIBLE); tickBar.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() { @Override public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) { if (fromUser) onTickBarUpdated(rating); } }); } @Override public void onTaskFailureResult(CommandFailureResult result) { publishException(null, result.getException()); } /** * This fragment can beam NFC messages describing the currently-visible beer */ @Override public Uri createNdefUri() { return Uri.parse("http://ratebeer.com/b/" + Integer.toString(beerId)); } private class BeerRatingsAdapter extends ArrayAdapter<BeerRating> { private OnClickListener onRowClick = new OnClickListener() { @Override public void onClick(View v) { onReviewClick((Integer) v.findViewById(R.id.total).getTag(), (String) v.findViewById(R.id.username).getTag()); } }; public BeerRatingsAdapter(Context context, List<BeerRating> objects) { super(context, objects); } @Override public View getView(int position, View convertView, ViewGroup parent) { // Get the right view, using a ViewHolder BeerRatingViewHolder holder; if (convertView == null) { convertView = getActivity().getLayoutInflater().inflate(R.layout.list_item_rating, null); ActivityUtil.makeListItemClickable(convertView, onRowClick); holder = new BeerRatingViewHolder(); holder.total = (TextView) convertView.findViewById(R.id.total); holder.aroma = (TextView) convertView.findViewById(R.id.aroma); holder.appearance = (TextView) convertView.findViewById(R.id.appearance); holder.taste = (TextView) convertView.findViewById(R.id.taste); holder.palate = (TextView) convertView.findViewById(R.id.palate); holder.overall = (TextView) convertView.findViewById(R.id.overall); holder.username = (TextView) convertView.findViewById(R.id.username); holder.comments = (TextView) convertView.findViewById(R.id.comments); convertView.setTag(holder); } else { holder = (BeerRatingViewHolder) convertView.getTag(); } // Bind the data BeerRating item = getItem(position); holder.total.setTag(Integer.valueOf(item.userId)); holder.total.setText(item.totalScore); holder.aroma.setText(Integer.toString(item.aroma)); holder.appearance.setText(Integer.toString(item.appearance)); holder.taste.setText(Integer.toString(item.flavor)); holder.palate.setText(Integer.toString(item.mouthfeel)); holder.overall.setText(Integer.toString(item.overall)); holder.username.setTag(item.userName); holder.username.setText(item.userName + " (" + Integer.toString(item.rateCount) + "), " + item.country); holder.comments.setText(item.comments + (item.timeUpdated != null ? " (" + displayDateFormat.format(item.timeUpdated) + ")" : item.timeEntered != null ? " (" + displayDateFormat.format(item.timeEntered) + ")" : "")); return convertView; } } protected static class BeerRatingViewHolder { TextView total, aroma, appearance, taste, palate, overall, username, comments; } private class AvailabilityAdapter extends ArrayAdapter<PlaceSearchResult> { private OnClickListener onRowClick = new OnClickListener() { @Override public void onClick(View v) { onPlaceClick((Integer) v.findViewById(R.id.name).getTag(), ((TextView) v.findViewById(R.id.name)).getText().toString()); } }; public AvailabilityAdapter(Context context, List<PlaceSearchResult> objects) { super(context, objects); } @Override public View getView(int position, View convertView, ViewGroup parent) { // Get the right view, using a ViewHolder AvailabilityViewHolder holder; if (convertView == null) { convertView = getActivity().getLayoutInflater().inflate(R.layout.list_item_placesearchresult, null); ActivityUtil.makeListItemClickable(convertView, onRowClick); holder = new AvailabilityViewHolder(); holder.name = (TextView) convertView.findViewById(R.id.name); holder.city = (TextView) convertView.findViewById(R.id.city); convertView.setTag(holder); } else { holder = (AvailabilityViewHolder) convertView.getTag(); } // Bind the data PlaceSearchResult item = getItem(position); holder.name.setTag(item.placeId); holder.name.setText(item.placeName); holder.city.setText(item.city); return convertView; } } protected static class AvailabilityViewHolder { TextView name, city; } private class BeerRatingsViewAdapter extends MergeAdapter { public BeerRatingsViewAdapter() { // Add the rate button and the views for the user's own rating View fields = getActivity().getLayoutInflater().inflate(R.layout.fragment_beerratings, null); addView(fields, true); rateThisButton = (Button) fields.findViewById(R.id.ratethis); otherratingslabel = fields.findViewById(R.id.otherratingslabel); ownratinglabel = fields.findViewById(R.id.ownratinglabel); ownratingRow = fields.findViewById(R.id.ownrating); ownratingTotal = (TextView) fields.findViewById(R.id.total); ownratingAroma = (TextView) fields.findViewById(R.id.aroma); ownratingAppearance = (TextView) fields.findViewById(R.id.appearance); ownratingTaste = (TextView) fields.findViewById(R.id.taste); ownratingPalate = (TextView) fields.findViewById(R.id.palate); ownratingOverall = (TextView) fields.findViewById(R.id.overall); ownratingUsername = (TextView) fields.findViewById(R.id.username); ownratingComments = (TextView) fields.findViewById(R.id.comments); ticklabel = fields.findViewById(R.id.ticklabel); tickBar = (RatingBar) fields.findViewById(R.id.tick); // Add the recent ratings recentRatingsAdapter = new BeerRatingsAdapter(getActivity(), new ArrayList<BeerRating>()); addAdapter(recentRatingsAdapter); } } private class BeerPagerAdapter extends PagerAdapter { private View pagerDetailsView; private ListView pagerRecentRatingsView; private View pagerAvailabilityView; public BeerPagerAdapter() { LayoutInflater inflater = getActivity().getLayoutInflater(); pagerDetailsView = inflater.inflate(R.layout.fragment_beerdetails, null); pagerRecentRatingsView = (ListView) inflater.inflate(R.layout.fragment_pagerlist, null); pagerAvailabilityView = inflater.inflate(R.layout.fragment_beeravailability, null); // Ratings page pagerRecentRatingsView.setAdapter(new BeerRatingsViewAdapter()); // Availability page availabilityEmpty = (TextView) pagerAvailabilityView.findViewById(R.id.empty); availabilityView = (ListView) pagerAvailabilityView.findViewById(R.id.list); availabilityView.setEmptyView(availabilityEmpty); addAvailabilityButton = (Button) pagerAvailabilityView.findViewById(R.id.addavailability); addAvailabilityButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onAddAvailability(); } }); // Details page if (pagerDetailsView.findViewById(R.id.image) != null) { // Phone version; beer image, description and style button are on the details page in the pager imageView = (ImageView) pagerDetailsView.findViewById(R.id.image); abvstyleButton = (Button) pagerDetailsView.findViewById(R.id.abvstyle); descriptionText = (TextView) pagerDetailsView.findViewById(R.id.description); nameText = (TextView) pagerDetailsView.findViewById(R.id.name); brewernameButton = (Button) pagerDetailsView.findViewById(R.id.brewername); } else { // Tablet version; these fields are not in the pager but directly in the main layout } scoreCard = pagerDetailsView.findViewById(R.id.scorecard); noscoreyetText = (TextView) pagerDetailsView.findViewById(R.id.noscoreyet); scoreText = (TextView) pagerDetailsView.findViewById(R.id.overallpctl); stylepctlText = (TextView) pagerDetailsView.findViewById(R.id.stylepctl); ratingsText = (TextView) pagerDetailsView.findViewById(R.id.ratings); drinkingThisButton = (Button) pagerDetailsView.findViewById(R.id.drinkingthis); havethisButton = (Button) pagerDetailsView.findViewById(R.id.havethis); wantthisButton = (Button) pagerDetailsView.findViewById(R.id.wantthis); uploadphotoButton = (Button) pagerDetailsView.findViewById(R.id.uploadphoto); abvstyleButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onStyleClick(); } }); brewernameButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onBrewerClick(); } }); drinkingThisButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onDrinkingBeerClick(); } }); havethisButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onWantOrHaveBeerClick(CellarType.Have); } }); wantthisButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onWantOrHaveBeerClick(CellarType.Want); } }); uploadphotoButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onStartPhotoUpload(); // When circumventing the photo taking on debugging: //onActivityResult(ACTIVITY_CAMERA, Activity.RESULT_OK, null); } }); } @Override public int getCount() { return 3; } @Override public CharSequence getPageTitle(int position) { switch (position) { case 0: return getActivity().getString(R.string.app_details).toUpperCase(Locale.getDefault()); case 1: return getActivity().getString(R.string.details_recentratings).toUpperCase(Locale.getDefault()); case 2: return getActivity().getString(R.string.details_availability).toUpperCase(Locale.getDefault()); } return null; } @Override public Object instantiateItem(View container, int position) { switch (position) { case 0: ((ViewPager) container).addView(pagerDetailsView, 0); return pagerDetailsView; case 1: ((ViewPager) container).addView(pagerRecentRatingsView, 0); return pagerRecentRatingsView; case 2: ((ViewPager) container).addView(pagerAvailabilityView, 0); return pagerAvailabilityView; } return null; } @Override public void destroyItem(View container, int position, Object object) { ((ViewPager) container).removeView((View) object); } @Override public boolean isViewFromObject(View view, Object object) { return view == (View) object; } } }