Android Open Source - AudioBook Bookshelf Fragment






From Project

Back to project page AudioBook.

License

The source code is released under:

Creative Commons Legal Code Attribution-NonCommercial 3.0 Unported CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT C...

If you think the Android project AudioBook listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/**
 *  This work is licensed under the Creative Commons Attribution-NonCommercial-
 *  NoDerivs 3.0 Unported License. To view a copy of this license, visit
 *  http://creativecommons.org/licenses/by-nc-nd/3.0/ or send a letter to 
 *  Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 
 *  94041, USA.//from  www. j  av a2s .c  o  m
 * 
 *  Use of this work is permitted only in accordance with license rights granted.
 *  Materials provided "AS IS"; no representations or warranties provided.
 * 
 *  Copyright ? 2012 Marcus Parkkinen, Aki K?kel?, Fredrik ?hs.
 **/

package edu.chalmers.dat255.audiobookplayer.view;

import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import edu.chalmers.dat255.audiobookplayer.R;
import edu.chalmers.dat255.audiobookplayer.constants.Constants;
import edu.chalmers.dat255.audiobookplayer.interfaces.IBookshelfGUIEvents;
import edu.chalmers.dat255.audiobookplayer.model.Bookshelf;
import edu.chalmers.dat255.audiobookplayer.util.TextFormatter;

/**
 * Graphical representation of the bookshelf.
 * 
 * @author Marcus Parkkinen, Fredrik ?hs
 * @version 0.6
 */
public class BookshelfFragment extends Fragment {
  private static final String TAG = "BookshelfFragment.class";
  private ExpandableBookshelfAdapter adapter;
  private IBookshelfGUIEvents fragmentOwner;
  private ExpandableListView bookshelfList;

  /**
   * Simple interface forcing the enum classes to provide a method to get
   * text.
   * 
   */
  private interface IContextMenuItem {
    /**
     * This method should be used to provide the text to be shown by the
     * menu items.
     * 
     * @return The text to be displayed.
     */
    String getText();
  }

  /**
   * Enum providing name and ID for context menu items
   * 
   */
  private enum GroupContextMenuItem implements IContextMenuItem {
    Delete {
      public String getText() {
        return "Delete";
      }
    },
    Edit {
      public String getText() {
        return "Edit";
      }
    };
  }

  /**
   * Enum providing name and ID for context menu items
   * 
   */
  private enum ChildContextMenuItem implements IContextMenuItem {
    Delete {
      public String getText() {
        return "Delete";
      }
    },
    MoveUp {
      public String getText() {
        return "Move Up";
      }
    },
    MoveDown {
      public String getText() {
        return "Move Down";
      }
    };
  }

  /*
   * (non-Javadoc)
   * 
   * @see android.support.v4.app.Fragment#onAttach(android.app.Activity)
   */
  @Override
  public void onAttach(Activity activity) {
    super.onAttach(activity);
    boolean ownerImplementsEvents = true;

    try {
      fragmentOwner = (IBookshelfGUIEvents) activity;
    } catch (ClassCastException e) {
      ownerImplementsEvents = false;
    }
    if (!ownerImplementsEvents) {
      throw new ClassCastException(activity.toString()
          + " does not implement "
          + IBookshelfGUIEvents.class.getName());
    }
  }

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
      Bundle savedInstanceState) {
    // Provide the layout of this fragment to the parent container
    View view = inflater.inflate(R.layout.fragment_bookshelf, container,
        false);

    /**************************************************************/
    /**//**/
    /* Instantiate member variables */
    /**//**/
    /**************************************************************/
    if (adapter == null) {
      adapter = new ExpandableBookshelfAdapter(view.getContext(), null);
    }

    /**************************************************************/
    /**//**/
    /* Get button layout, and add a listener method to it */
    /**//**/
    /**************************************************************/

    ImageButton addButton = (ImageButton) view.findViewById(R.id.addBook);
    // adds a listener to the button
    addButton.setOnClickListener(new OnClickListener() {
      public void onClick(View v) {
        // Get the parent activity

        // Make sure that the activity is not at the end of its
        // lifecycle
        if (getActivity() != null) {
          // inform mainactivity this button has been pressed
          addBookButtonPressed();
        }
      }
    });

    /******************************************************************************/
    /**//**/
    /* Get the list layout, and add listener methods and an adapter to it */
    /**//**/
    /******************************************************************************/
    bookshelfList = (ExpandableListView) view
        .findViewById(R.id.bookshelfList);

    /*
     * hides the by default visible arrow which indicates whether a group is
     * expanded or not
     */
    bookshelfList.setGroupIndicator(null);
    // set the bookshelf list as a context menu
    registerForContextMenu(bookshelfList);
    // sets the bookshelf lists adapter
    bookshelfList.setAdapter(adapter);

    // Access the bookshelf reference
    if (getArguments().getSerializable(Constants.Reference.BOOKSHELF) instanceof Bookshelf) {
      bookshelfUpdated((Bookshelf) getArguments().getSerializable(
          Constants.Reference.BOOKSHELF));
    }
    // return the view when it has been processed.
    return view;
  }

  // these warnings can be suppressed as the type has already been checked
  @SuppressWarnings("rawtypes")
  @Override
  public void onCreateContextMenu(ContextMenu menu, View v,
      ContextMenuInfo menuInfo) {
    // check that the menuInfo is of the correct type
    // this method is allowed to have quite a high cyclomatic complexity as
    // it would otherwise cause code duplication

    if (menuInfo instanceof ExpandableListContextMenuInfo
        && adapter != null) {
      ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) menuInfo;
      // get the provided book position
      int bookIndex = ExpandableListView
          .getPackedPositionGroup(info.packedPosition);
      // trackIndex will be -1 if group is clicked
      int trackIndex = ExpandableListView
          .getPackedPositionChild(info.packedPosition);
      // get the type of the context menu
      int type = ExpandableListView
          .getPackedPositionType(info.packedPosition);
      // create an empty array to prevent trying to loop over an
      // uninitialized variable
      IContextMenuItem[] menuItems = new IContextMenuItem[0];
      String title = "";
      // fill the context menu with the correct items
      if (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
        // get all menu items from the child context menu
        menuItems = ChildContextMenuItem.values();
        // set the context menu's title to that of the value of the
        // child
        title = adapter.getChild(bookIndex, trackIndex);

      } else if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
        // get all menu items from the group context menu
        menuItems = GroupContextMenuItem.values();
        // set the context menu's title to that of the value of the book
        title = adapter.getGroup(bookIndex);
      }
      // set the title
      menu.setHeaderTitle(title);
      // populate the context menu with items in the order they were
      // declared in the enum declaration.
      for (IContextMenuItem item : menuItems) {
        // as this only loops when menuItems is of either of type
        // GroupContextMenuItem[] or ChildContextMenuItem[], Enum can be
        // used as a raw type
        menu.add(Menu.NONE, ((Enum) item).ordinal(),
            ((Enum) item).ordinal(), item.getText());
      }
    }
  }

  /*
   * (non-Javadoc)
   * 
   * @see
   * android.support.v4.app.Fragment#onContextItemSelected(android.view.MenuItem
   * )
   */
  @Override
  public boolean onContextItemSelected(MenuItem item) {
    if (getActivity() == null) {
      return false;
    }

    // this method is allowed to have quite a high cyclomatic complexity as
    // it would otherwise cause code duplication
    ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) item
        .getMenuInfo();
    // get the provided book position
    int bookIndex = ExpandableListView
        .getPackedPositionGroup(info.packedPosition);
    // will be -1 if the type is group
    int trackIndex = ExpandableListView
        .getPackedPositionChild(info.packedPosition);
    // get the type of the context menu
    int type = ExpandableListView
        .getPackedPositionType(info.packedPosition);

    // create an empty array to prevent trying to loop over an uninitialized
    // variable
    IContextMenuItem[] menuItems = new IContextMenuItem[0];
    // fill the array with the correct items
    if (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
      menuItems = ChildContextMenuItem.values();
    } else if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
      menuItems = GroupContextMenuItem.values();
    }

    // get an item and store it with its dynamic type
    IContextMenuItem menuItem = menuItems[item.getItemId()];

    // if the type of the context menu is group
    if (menuItem instanceof GroupContextMenuItem) {

      // perform the correct task
      executeGroupMenuItem((GroupContextMenuItem) menuItem, bookIndex);

    }
    // if the type of the context menu is that of a child
    else if (menuItem instanceof ChildContextMenuItem) {
      // perform the correct task
      executeChildMenuItem((ChildContextMenuItem) menuItem, bookIndex,
          trackIndex);
    }
    return true;
  }

  /**
   * Private method which executes the correct task depending on which menu
   * item was chosen
   * 
   * @param menuItem
   *            The menu item
   * @param bookIndex
   *            The index of the book to execute the task on
   */
  private void executeGroupMenuItem(GroupContextMenuItem menuItem,
      int bookIndex) {
    switch (menuItem) {
    case Delete:
      removeBook(bookIndex);
      break;
    case Edit:
      // not fully implemented, some method to retrieve a real name should
      // be used
      setBookTitleAt(bookIndex, "NEWNAME");
      break;
    default:
      break;
    }
  }

  /**
   * Private method which executes the correct task depending on which menu
   * item was chosen
   * 
   * @param menuItem
   *            The menu item
   * @param bookIndex
   *            The index of the book containing the track
   * @param trackIndex
   *            The index of the track to execute the task on
   */
  private void executeChildMenuItem(ChildContextMenuItem menuItem,
      int bookIndex, int trackIndex) {
    switch (menuItem) {
    case Delete:
      removeTrack(bookIndex, trackIndex);
      break;
    case MoveUp:
      moveTrack(bookIndex, trackIndex, -1);
      break;
    case MoveDown:
      moveTrack(bookIndex, trackIndex, 1);
      break;
    default:
      break;

    }
  }

  /*
   * (non-Javadoc)
   * 
   * @see
   * edu.chalmers.dat255.audiobookplayer.interfaces.IBookshelfEvents#moveTrack
   * (int, int, int)
   */
  public void moveTrack(int bookIndex, int trackIndex, int offset) {
    fragmentOwner.moveTrack(bookIndex, trackIndex, offset);
  }

  /*
   * (non-Javadoc)
   * 
   * @see
   * edu.chalmers.dat255.audiobookplayer.interfaces.IBookshelfEvents#removeTrack
   * (int, int)
   */
  public void removeTrack(int bookIndex, int trackIndex) {
    fragmentOwner.removeTrack(bookIndex, trackIndex);
  }

  /**
   * @param bookIndex
   * @param trackIndex
   */
  private void childClicked(int bookIndex, int trackIndex) {
    if (getActivity() != null) {
      Log.d(TAG, "Child clicked at + [" + bookIndex + ", " + trackIndex
          + "]");
      setSelectedTrack(bookIndex, trackIndex);
    }
  }

  /**
   * @param bookIndex
   */
  private void groupClicked(int bookIndex) {
    if (getActivity() != null) {
      setSelectedBook(bookIndex);
    }
  }

  /**
   * Updates the adapter with the updated bookshelf and informs it that its
   * data has been added.
   * 
   * @param bs
   *            The updated bookshelf
   */

  public void bookshelfUpdated(Bookshelf bs) {
    Log.d(TAG, "Book added");
    if (adapter != null) {
      adapter.setBookshelf(bs);
      adapter.notifyDataSetChanged();
    }
  }

  /**
   * @param newTime
   */
  public void selectedBookElapsedTimeUpdated(int newTime) {
    adapter.selectedBookElapsedTimeUpdated(newTime);
  }

  /*
   * (non-Javadoc)
   * 
   * @see edu.chalmers.dat255.audiobookplayer.interfaces.IBookshelfGUIEvents#
   * addBookButtonPressed()
   */
  public void addBookButtonPressed() {
    fragmentOwner.addBookButtonPressed();
  }

  /*
   * (non-Javadoc)
   * 
   * @see edu.chalmers.dat255.audiobookplayer.interfaces.IBookshelfEvents#
   * setSelectedBook(int)
   */
  public void setSelectedBook(int bookIndex) {
    fragmentOwner.setSelectedBook(bookIndex);
  }

  /*
   * (non-Javadoc)
   * 
   * @see edu.chalmers.dat255.audiobookplayer.interfaces.IBookshelfEvents#
   * setSelectedTrack(int, int)
   */
  public void setSelectedTrack(int bookIndex, int trackIndex) {
    fragmentOwner.setSelectedTrack(bookIndex, trackIndex);
  }

  /*
   * (non-Javadoc)
   * 
   * @see
   * edu.chalmers.dat255.audiobookplayer.interfaces.IBookshelfEvents#removeBook
   * (int)
   */
  public void removeBook(int bookIndex) {
    fragmentOwner.removeBook(bookIndex);
  }

  /*
   * (non-Javadoc)
   * 
   * @see
   * edu.chalmers.dat255.audiobookplayer.interfaces.IBookshelfEvents#removeTrack
   * (int)
   */
  public void removeTrack(int trackIndex) {
    fragmentOwner.removeTrack(trackIndex);
  }

  /*
   * (non-Javadoc)
   * 
   * @see edu.chalmers.dat255.audiobookplayer.interfaces.IBookshelfEvents#
   * setBookTitleAt(int, java.lang.String)
   */
  public void setBookTitleAt(int bookIndex, String newTitle) {
    fragmentOwner.setBookTitleAt(bookIndex, "NEWNAME");
  }

  /**
   * Private class used to populate the ExpandableListView used in
   * BookshelfFragment.
   * 
   * @author Fredrik ?hs
   * 
   */
  private class ExpandableBookshelfAdapter extends BaseExpandableListAdapter {

    private static final int PROGRESSBAR_MAX = 100;
    private static final int MILLIS_PER_SECOND = 1000;
    private Context context;
    private Bookshelf bookshelf;

    // used to get synchronized time label and progress bar
    private int bookElapsedTime;
    private int bookProgress;
    private View selectedBookView;

    /**
     * Constructs an ExpandableListAdapter with context and listData.
     * 
     * @param context
     *            The context of the application.
     * @param listData
     *            The data to be used to fill the list.
     */
    public ExpandableBookshelfAdapter(Context context, Bookshelf bookshelf) {
      this.context = context;
      setBookshelf(bookshelf);

    }

    /**
     * Updates the adapters class variables.
     * 
     * @param newTime
     * @return
     */
    public void selectedBookElapsedTimeUpdated(int newTime) {
      // if a second has passed
      if (newTime / MILLIS_PER_SECOND > bookElapsedTime
          / MILLIS_PER_SECOND) {
        // store this new value
        bookElapsedTime = newTime;
        // update the label
        setTextViewText(
            selectedBookView,
            R.id.bookshelfBookPosition,
            "Position: "
                + TextFormatter
                    .formatTimeFromMillis(bookElapsedTime));

        // get duration of book in seconds
        int bookDuration = bookshelf.getSelectedBookDuration();
        // calculate the progress
        int calculatedProgress = calculateProgress(newTime,
            bookDuration);
        // if there is no errors and the progress has progressed since
        // the last saved progress
        if ((calculatedProgress >= 0)
            && (calculatedProgress <= PROGRESSBAR_MAX)
            && (calculatedProgress > bookProgress)) {
          // save this new progress
          bookProgress = calculatedProgress;
          // get the progressbar
          ProgressBar pb = (ProgressBar) selectedBookView
              .findViewById(R.id.bookshelfProgressBar);
          // check that the progressbar is not null and set it to the
          // new progress
          if (pb != null) {
            pb.setProgress(bookProgress);
          }
        }
      }

    }

    /**
     * Method that calculates a roofed progress, i.e. time = 51, duration =
     * 1000 would return a progress of 6
     * 
     * @param elapsedTime
     *            The time elapsed.
     * @param duration
     *            The total duration.
     * @return A roofed progress.
     */
    private int calculateProgress(int elapsedTime, int duration) {
      if (elapsedTime < 0 || duration <= 0) {
        return 0;
      }
      int floored = PROGRESSBAR_MAX * elapsedTime / duration;
      int rest = PROGRESSBAR_MAX * elapsedTime % duration;
      if (rest == 0) {
        return floored;
      }
      return floored + 1;
    }

    /**
     * Set the bookshelf for when the data should update
     * 
     * @param bookshelf
     *            The new bookshelf copy.
     */
    public final void setBookshelf(Bookshelf bookshelf) {
      this.bookshelf = bookshelf;
    }

    /**
     * @param bookIndex
     *            The position of the book.
     * @param trackIndex
     *            The position of the track.
     * @return The title of the track at given position, null if incorrect
     *         index.
     */
    public String getChild(int bookIndex, int trackIndex) {
      if (bookshelf == null) {
        return "";
      }
      return bookshelf.getTrackTitleAt(bookIndex, trackIndex);
    }

    /**
     * @param bookIndex
     *            The position of the book.
     * @param trackIndex
     *            The position of the track.
     * @return The id of the track at given position.
     */
    public long getChildId(int bookIndex, int trackIndex) {
      return trackIndex;
    }

    /**
     * @param bookIndex
     *            The position of the book.
     * @return The amount of tracks in the book at given position.
     */
    public int getChildrenCount(int bookIndex) {
      if (bookshelf != null) {
        return bookshelf.getNumberOfTracksAt(bookIndex);
      }
      return 0;
    }

    /**
     * Converts the view of a track to display properly.
     * 
     * @param bookIndex
     *            The position of the book.
     * @param trackIndex
     *            The position of the track.
     * @param isLastChild
     *            Whether the track is the last child in the expandable list
     *            view group.
     * @param convertView
     *            The view to be converted.
     * @param parent
     *            The view of the ExpandableListView.
     * @return The converted view.
     */
    public View getChildView(final int bookIndex, final int trackIndex,
        boolean isLastChild, View convertView, ViewGroup parent) {
      View cView = convertView;
      if (cView == null) {
        LayoutInflater vi = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        // inflate it into parent.
        cView = vi.inflate(R.layout.bookshelf_child_row, parent, false);
      }

      // the expandable list view is stored as final to use it in
      // listeners
      final ExpandableListView expandableListView = (ExpandableListView) parent;
      // set the text of the child
      setTextViewText(cView, R.id.bookshelfTrackTitle,
          bookshelf.getTrackTitleAt(bookIndex, trackIndex));
      // get the position of the track from the book
      int duration = bookshelf.getTrackDurationAt(bookIndex, trackIndex);
      // convert and set the duration of the track
      setTextViewText(cView, R.id.bookshelfTrackTime,
          TextFormatter.formatTimeFromMillis(duration));

      cView.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
          trackClicked(bookIndex, trackIndex, expandableListView);
        }

      });

      // set long click to show the child's context menu
      cView.setOnLongClickListener(new OnLongClickListener() {

        public boolean onLongClick(View v) {
          expandableListView.showContextMenu();
          return false;
        }

      });

      return cView;
    }

    /**
     * Private method to be called when a track is clicked
     * 
     * @param bookIndex
     *            The index of the book the track resides within
     * @param trackIndex
     *            The index of the track
     * @param expandableListView
     *            The expandable list view
     */
    private void trackClicked(final int bookIndex, final int trackIndex,
        final ExpandableListView expandableListView) {
      // store the index of the book of the track clicked for
      // correct redrawal
      // force the expandable list view to redraw
      expandableListView.invalidateViews();
      // inform the bookshelfFragment's listener that a child has
      // been selected
      BookshelfFragment.this.childClicked(bookIndex, trackIndex);
      // store for synchronization
      selectedBookView = expandableListView.getChildAt(bookIndex);
      try {
        bookElapsedTime = bookshelf.getBookElapsedTime();
      } catch (IndexOutOfBoundsException e) {
        bookElapsedTime = 0;
      }
      bookProgress = calculateProgress(bookElapsedTime,
          bookshelf.getSelectedBookDuration());
    }

    /**
     * @param bookIndex
     *            The position of the book.
     * @return The books title at given position
     */
    public String getGroup(int bookIndex) {
      if (bookshelf == null) {
        return "";
      }
      try {
        return bookshelf.getBookTitleAt(bookIndex);
      } catch (IndexOutOfBoundsException e) {
        return "";
      }
    }

    /**
     * @return The number of books.
     */
    public int getGroupCount() {
      if (bookshelf != null) {
        return bookshelf.getNumberOfBooks();
      }
      return 0;
    }

    /**
     * @param bookIndex
     *            The position of the book.
     * @return The id of the book.
     */
    public long getGroupId(int bookIndex) {
      return bookIndex;
    }

    /**
     * Converts the view of a book to display it properly.
     * 
     * @param bookIndex
     *            The position of the book.
     * @param isExpanded
     *            Whether the book is expanded or not.
     * @param convertView
     *            The book's view.
     * @param parent
     *            The expandable list view
     * @return The converted view.
     */
    public View getGroupView(final int bookIndex, final boolean isExpanded,
        View convertView, ViewGroup parent) {
      View cView = convertView;
      if (cView == null) {
        LayoutInflater vi = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        // inflate it into its parent
        cView = vi.inflate(R.layout.bookshelf_group_row, parent, false);
      }
      // set book as final to use in listeners

      // set the expandableListView as final to use in listeners
      final ExpandableListView expandableListView = (ExpandableListView) parent;
      // get duration from book
      int duration = bookshelf.getBookDurationAt(bookIndex);

      // prevent problems with a duration of 0
      if (duration == 0) {
        return cView;
      }
      // get the elapsed time of the book
      int time = 0;
      int progress = 0;

      // set title, author, time and duration of book
      setTextViewText(cView, R.id.bookshelfBookTitle,
          bookshelf.getBookTitleAt(bookIndex));
      // set the color of the books title to red if selected,
      if (bookIndex == bookshelf.getSelectedBookIndex()) {
        setTextViewTextColor(cView, R.id.bookshelfBookTitle, Color.RED);
        time = bookElapsedTime;
        progress = bookProgress;
      }
      // and white otherwise.
      else {
        setTextViewTextColor(cView, R.id.bookshelfBookTitle,
            Color.WHITE);
        try {
          time = bookshelf.getBookElapsedTime();
        } catch (IndexOutOfBoundsException e) {
          time = 0;
        }
        progress = calculateProgress(time, duration);
      }
      setTextViewText(cView, R.id.bookshelfAuthor,
          bookshelf.getBookAuthorAt(bookIndex));
      // format the string of the elapsed time of the book
      String timeString = time == 0 ? "N/A" : TextFormatter
          .formatTimeFromMillis(time);
      setTextViewText(cView, R.id.bookshelfBookPosition, "Position: "
          + timeString);
      setTextViewText(cView, R.id.bookshelfBookDuration, "Duration: "
          + TextFormatter.formatTimeFromMillis(duration));

      // set the progress of the progress bar
      ProgressBar progressBar = (ProgressBar) cView
          .findViewById(R.id.bookshelfProgressBar);
      // make sure progress is within its boundaries before setting it
      if (progress >= 0 && progress <= PROGRESSBAR_MAX) {
        progressBar.setProgress(progress);
      }
      // set cover art
      ImageView imageView = (ImageView) cView
          .findViewById(R.id.bookshelfBookCover);
      // in future versions this cover art should be gotten from the file
      imageView.setImageResource(R.drawable.img_no_cover);
      // click the cover art to toggle the books tracks visibility
      imageView.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
          if (isExpanded) {
            expandableListView.collapseGroup(bookIndex);
          } else {
            expandableListView.expandGroup(bookIndex);
          }
        }
      });
      // sets the on click listener for the rest of the view
      // store convertview as final to reach it inside this method
      final View finalConvertView = cView;
      cView.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
          bookClicked(bookIndex, isExpanded, expandableListView,
              finalConvertView);
        }

      });
      // set long click to show the group's context menu
      cView.setOnLongClickListener(new OnLongClickListener() {

        public boolean onLongClick(View v) {
          expandableListView.showContextMenu();
          return false;
        }

      });

      return cView;
    }

    /**
     * Private method to be called when a book is clicked.
     * 
     * @param bookIndex
     *            Index of the book clicked
     * @param isExpanded
     *            Whether or not the book is expanded in the expandable list
     *            view
     * @param expandableListView
     *            The expandable list view
     * @param convertView
     *            The view to be set as selected
     */
    private void bookClicked(final int bookIndex, final boolean isExpanded,
        final ExpandableListView expandableListView,
        final View convertView) {
      // expand the selected item
      if (!isExpanded) {
        expandableListView.expandGroup(bookIndex);
      }
      // scroll to the selected item
      expandableListView.setSelectionFromTop(bookIndex, 0);
      // invalidates views to force redraw thus setting the
      // correct textcolor
      expandableListView.invalidateViews();
      // inform the BookshelfFragment that this button has been
      // pressed.
      BookshelfFragment.this.groupClicked(bookIndex);
      // store the view so that text can update
      selectedBookView = convertView;
      try {
        bookElapsedTime = bookshelf.getBookElapsedTime();
      } catch (IndexOutOfBoundsException e) {
        bookElapsedTime = 0;
      }
      bookProgress = calculateProgress(bookElapsedTime,
          bookshelf.getSelectedBookDuration());
    }

    /**
     * Private help class used to prevent code duplication
     * 
     * @param view
     *            The TextView to where the text will be displayed.
     * @param id
     *            The id of the TextView.
     * @param text
     *            The text to be displayed.
     */
    private void setTextViewText(View view, int id, String text) {
      if (view != null) {
        TextView textView = (TextView) view.findViewById(id);
        if (textView != null) {
          textView.setText(text);
        }
      }
    }

    /**
     * Private help class used to prevent code duplication.
     * 
     * @param view
     *            The TextView to where the text color will be set.
     * @param id
     *            The id of the TextView.
     * @param color
     *            The color to be set.
     */
    private void setTextViewTextColor(View view, int id, int color) {
      if (view != null) {
        TextView textView = (TextView) view.findViewById(id);
        if (textView != null) {
          textView.setTextColor(color);
        }
      }
    }

    /*
     * (non-Javadoc)
     * 
     * @see android.widget.ExpandableListAdapter#hasStableIds()
     */
    public boolean hasStableIds() {
      return true;
    }

    /**
     * @param bookIndex
     *            The position of the book.
     * @param trackIndex
     *            The position of the track.
     * @return Whether the track at given position is selectable.
     */
    public boolean isChildSelectable(int bookIndex, int trackIndex) {
      return true;
    }
  }
}




Java Source Code List

edu.chalmers.dat255.audiobookplayer.constants.Constants.java
edu.chalmers.dat255.audiobookplayer.constants.PlaybackStatus.java
edu.chalmers.dat255.audiobookplayer.ctrl.BookshelfControllerTest.java
edu.chalmers.dat255.audiobookplayer.ctrl.BookshelfController.java
edu.chalmers.dat255.audiobookplayer.ctrl.PlayerControllerTest.java
edu.chalmers.dat255.audiobookplayer.ctrl.PlayerController.java
edu.chalmers.dat255.audiobookplayer.instrumentation.AllTests.java
edu.chalmers.dat255.audiobookplayer.interfaces.IBookUpdates.java
edu.chalmers.dat255.audiobookplayer.interfaces.IBookshelfEvents.java
edu.chalmers.dat255.audiobookplayer.interfaces.IBookshelfGUIEvents.java
edu.chalmers.dat255.audiobookplayer.interfaces.IPlayerEvents.java
edu.chalmers.dat255.audiobookplayer.interfaces.ITrackUpdates.java
edu.chalmers.dat255.audiobookplayer.model.BookTest.java
edu.chalmers.dat255.audiobookplayer.model.Book.java
edu.chalmers.dat255.audiobookplayer.model.BookshelfTest.java
edu.chalmers.dat255.audiobookplayer.model.Bookshelf.java
edu.chalmers.dat255.audiobookplayer.model.TagTest.java
edu.chalmers.dat255.audiobookplayer.model.Tag.java
edu.chalmers.dat255.audiobookplayer.model.TrackTest.java
edu.chalmers.dat255.audiobookplayer.model.Track.java
edu.chalmers.dat255.audiobookplayer.util.BookCreatorTest.java
edu.chalmers.dat255.audiobookplayer.util.BookCreator.java
edu.chalmers.dat255.audiobookplayer.util.BookshelfHandlerTest.java
edu.chalmers.dat255.audiobookplayer.util.BookshelfHandler.java
edu.chalmers.dat255.audiobookplayer.util.FileParserTest.java
edu.chalmers.dat255.audiobookplayer.util.FileParser.java
edu.chalmers.dat255.audiobookplayer.util.JsonParserTest.java
edu.chalmers.dat255.audiobookplayer.util.JsonParser.java
edu.chalmers.dat255.audiobookplayer.util.TextFormatterTest.java
edu.chalmers.dat255.audiobookplayer.util.TextFormatter.java
edu.chalmers.dat255.audiobookplayer.util.TrackCreatorTest.java
edu.chalmers.dat255.audiobookplayer.util.TrackCreator.java
edu.chalmers.dat255.audiobookplayer.view.BookshelfFragment.java
edu.chalmers.dat255.audiobookplayer.view.BrowserActivityTest.java
edu.chalmers.dat255.audiobookplayer.view.BrowserActivity.java
edu.chalmers.dat255.audiobookplayer.view.MainActivity.java
edu.chalmers.dat255.audiobookplayer.view.PlayerFragment.java
edu.chalmers.dat255.audiobookplayer.view.ViewPagerAdapter.java