/** Sets the KitKat translucent status/nav bar and adjusts the views' boundaries. */ private void setKitKatTranslucentBars() { // KitKat translucent status bar. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { int statusBarHeight = Common.getStatusBarHeight(mContext); int navigationBarHeight = Common.getNavigationBarHeight(mContext); if (mDrawerParentLayout != null) { mDrawerParentLayout.setClipToPadding(false); mDrawerParentLayout.setPadding(0, 0, 0, 0); } if (mControlsLayoutHeaderParent != null) { int bottomPadding = mControlsLayoutHeaderParent.getPaddingBottom(); mControlsLayoutHeaderParent.setClipToPadding(false); RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mControlsLayoutHeaderParent.getLayoutParams(); if (navigationBarHeight > 0) { /* The nav bar already has padding, so remove the extra 15dp * margin that was applied in the layout file. */ params.bottomMargin = 0; } params.bottomMargin += navigationBarHeight; mControlsLayoutHeaderParent.setLayoutParams(params); } } }
@Override public void onPageScrolled( final int pagerPosition, float swipeVelocity, int offsetFromCurrentPosition) { /* swipeVelocity determines whether the viewpager has finished scrolling or not. * Throw in an if statement that only allows the track to change when * swipeVelocity is 0 (which means the page is done scrolling). This ensures * that the tracks don't jump around or get truncated while the user is * swiping between different pages. */ if (mApp.isServiceRunning() && mApp.getService().getCursor().getCount() != 1) { /* Change tracks ONLY when the user has finished the swiping gesture (swipeVelocity will be zero). * Also, don't skip tracks if the new pager position is the same as the current mCursor position (indicates * that the starting and ending position of the pager is the same). */ if (swipeVelocity == 0.0f && pagerPosition != mApp.getService().getCurrentSongIndex()) { if (USER_SCROLL) { mHandler.removeCallbacks(seekbarUpdateRunnable); smoothScrollSeekbar(0); mHandler.postDelayed( new Runnable() { @Override public void run() { mApp.getService().skipToTrack(pagerPosition); } }, 200); } } } }
@Override public void onStart() { super.onStart(); // Initialize the broadcast manager that will listen for track changes. LocalBroadcastManager.getInstance(mContext) .registerReceiver((mReceiver), new IntentFilter(Common.UPDATE_UI_BROADCAST)); /* Check if the service is up and running. If so, send out a broadcast message * that will initialize this activity fully. This code block is what will * initialize this activity fully if it is opened after the service is already * up and running (the onServiceRunning() callback isn't available at this point). */ if (mApp.isServiceRunning() && mApp.getService().getCursor() != null) { String[] updateFlags = new String[] { Common.UPDATE_PAGER_POSTIION, Common.UPDATE_SEEKBAR_DURATION, Common.HIDE_STREAMING_BAR, Common.INIT_PAGER, Common.UPDATE_PLAYBACK_CONTROLS, Common.UPDATE_EQ_FRAGMENT }; String[] flagValues = new String[] { "" + mApp.getService().getCurrentSongIndex(), "" + mApp.getService().getCurrentMediaPlayer().getDuration(), "", "", "", "" }; mApp.broadcastUpdateUICommand(updateFlags, flagValues); } }
/** Sets the shuffle button icon based on the current shuffle mode. */ private void setShuffleButtonIcon() { if (mApp.isServiceRunning()) if (mApp.getService().isShuffleOn() == true) { mShuffleButton.setImageResource(R.drawable.shuffle_highlighted); } else { mShuffleButton.setImageResource(UIElementsHelper.getIcon(mContext, "shuffle")); } else mShuffleButton.setImageResource(UIElementsHelper.getIcon(mContext, "shuffle")); }
/** @deprecated Applies the correct transformer effect to the ViewPager. */ @SuppressWarnings("unused") private void setPlaylistPagerAnimation() { if (mApp.getSharedPreferences().getInt("TRACK_CHANGE_ANIMATION", 0) == 0) { // Don't set a transformer. } else if (mApp.getSharedPreferences().getInt("TRACK_CHANGE_ANIMATION", 0) == 1) { // mViewPager.setPageTransformer(true, new ZoomOutPageTransformer(0.85f)); } else if (mApp.getSharedPreferences().getInt("TRACK_CHANGE_ANIMATION", 0) == 2) { // mViewPager.setPageTransformer(true, new DepthPageTransformer()); } }
/** Sets the play/pause button states. */ private void setPlayPauseButton() { if (mApp.isServiceRunning()) { if (mApp.getService().isPlayingMusic()) { animatePlayToPause(); stopSeekbarStrobeEffect(); } else { animatePauseToPlay(); initSeekbarStrobeEffect(); } } }
/** Sets the repeat button icon based on the current repeat mode. */ private void setRepeatButtonIcon() { if (mApp.isServiceRunning()) if (mApp.getService().getRepeatMode() == Common.REPEAT_OFF) { mRepeatButton.setImageResource(UIElementsHelper.getIcon(mContext, "repeat")); } else if (mApp.getService().getRepeatMode() == Common.REPEAT_PLAYLIST) { mRepeatButton.setImageResource(R.drawable.repeat_highlighted); } else if (mApp.getService().getRepeatMode() == Common.REPEAT_SONG) { mRepeatButton.setImageResource(R.drawable.repeat_song); } else if (mApp.getService().getRepeatMode() == Common.A_B_REPEAT) { mRepeatButton.setImageResource(R.drawable.repeat_song_range); } else mRepeatButton.setImageResource(UIElementsHelper.getIcon(mContext, "repeat")); }
@Override public void onProgressChanged(SeekBar seekBar, int seekBarPosition, boolean changedByUser) { try { long currentSongDuration = mApp.getService().getCurrentMediaPlayer().getDuration(); seekBar.setMax((int) currentSongDuration / 1000); if (changedByUser) mSeekbarIndicatorText.setText( mApp.convertMillisToMinsSecs(seekBar.getProgress() * 1000)); } catch (Exception e) { e.printStackTrace(); } }
@Override public void onClick(View view) { // BZZZT! Give the user a brief haptic feedback touch response. view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); // Update the playback UI elements. if (mApp.getService().isPlayingMusic()) { animatePauseToPlay(); mHandler.removeCallbacks(seekbarUpdateRunnable); } else { animatePlayToPause(); mHandler.post(seekbarUpdateRunnable); } /* * Toggle the playback state in a separate thread. This * will allow the play/pause button animation to remain * buttery smooth. */ new AsyncTask() { @Override protected Object doInBackground(Object[] params) { mApp.getService().togglePlaybackState(); return null; } }.execute(); }
@Override public void onClick(View arg0) { // Remove the seekbar update runnable. mHandler.removeCallbacks(seekbarUpdateRunnable); /* * Scrolling the pager will automatically call the skipToTrack() method. * Since we're passing true for the dispatchToListener parameter, the * onPageSelected() listener will receive a callback once the scrolling * animation completes. This has the side-benefit of letting the animation * finish before starting playback (keeps the animation buttery smooth). */ int newPosition = mViewPager.getCurrentItem() + 1; if (newPosition < mViewPagerAdapter.getCount()) { scrollViewPager(newPosition, true, 1, true); } else { if (mApp.getService().getRepeatMode() == Common.REPEAT_PLAYLIST) mViewPager.setCurrentItem(0, false); else Toast.makeText(mContext, R.string.no_songs_to_skip_to, Toast.LENGTH_SHORT).show(); } // mApp.getService().skipToNextTrack(); }
/** Initializes the view pager. */ private void initViewPager() { try { mViewPager.setVisibility(View.INVISIBLE); mViewPagerAdapter = new PlaylistPagerAdapter(getSupportFragmentManager()); mViewPager.setAdapter(mViewPagerAdapter); mViewPager.setOffscreenPageLimit(0); mViewPager.setOnPageChangeListener(mPageChangeListener); mViewPager.setCurrentItem(mApp.getService().getCurrentSongIndex(), false); FadeAnimation fadeAnimation = new FadeAnimation(mViewPager, 600, 0.0f, 1.0f, new DecelerateInterpolator(2.0f)); fadeAnimation.animate(); } catch (IllegalStateException e) { /* * Catches any exceptions that may occur * as a result of the user rapidly changing * their device's orientation. */ } // Delay loading extra fragments by 1000ms. new Handler() .postDelayed( new Runnable() { @Override public void run() { mViewPager.setOffscreenPageLimit(10); } }, 1000); }
/** Sets the activity's theme based on user preferences. */ private void setTheme() { if (mApp.getCurrentTheme() == Common.DARK_THEME) { this.setTheme(R.style.AppThemeNoActionBar); } else { this.setTheme(R.style.AppThemeLightNoActionBar); } }
@Override public void onClick(View arg0) { // Toggle shuffle on/off. boolean shuffleOn = mApp.getService().toggleShuffleMode(); if (shuffleOn) mShuffleButton.setImageResource(R.drawable.shuffle_highlighted); else mShuffleButton.setImageResource(UIElementsHelper.getIcon(mContext, "shuffle")); }
@Override public void onStopTrackingTouch(SeekBar seekBar) { int seekBarPosition = seekBar.getProgress(); mApp.getService().getCurrentMediaPlayer().seekTo(seekBarPosition * 1000); // Reinitiate the handler. mHandler.post(seekbarUpdateRunnable); // Fade out the indicator after 1000ms. mHandler.postDelayed(fadeOutSeekbarIndicator, 1000); }
/** Displays the "Resuming from xx:xx" toast. */ public void displayAudiobookToast(long resumePlaybackPosition) { try { String resumingFrom = mContext.getResources().getString(R.string.resuming_from) + " " + mApp.convertMillisToMinsSecs(resumePlaybackPosition) + "."; Toast.makeText(mContext, resumingFrom, Toast.LENGTH_LONG).show(); } catch (Exception e) { e.printStackTrace(); } }
public void run() { try { long currentPosition = mApp.getService().getCurrentMediaPlayer().getCurrentPosition(); int currentPositionInSecs = (int) currentPosition / 1000; smoothScrollSeekbar(currentPositionInSecs); // mSeekbar.setProgress(currentPositionInSecs); mHandler.postDelayed(seekbarUpdateRunnable, 100); } catch (Exception e) { e.printStackTrace(); } }
@Override public void onResume() { super.onResume(); if (mIsCreating == false) { setKitKatTranslucentBars(); mHandler.postDelayed(seekbarUpdateRunnable, 100); mIsCreating = false; } // Animate the controls bar in. // animateInControlsBar(); // Update the seekbar. try { setSeekbarDuration(mApp.getService().getCurrentMediaPlayer().getDuration() / 1000); } catch (Exception e) { e.printStackTrace(); } // Load the drawer 1000ms after the activity is loaded. mHandler.postDelayed( new Runnable() { @Override public void run() { initDrawer(); } }, 1000); if (getIntent().hasExtra(START_SERVICE) && getNowPlayingActivityListener() != null) { getNowPlayingActivityListener().onNowPlayingActivityReady(); /** * To prevent the service from being restarted every time this activity is resume, we're gonna * have to remove the "START_SERVICE" extra from the intent. */ getIntent().removeExtra(START_SERVICE); } }
@Override public void onClick(View arg0) { mApp.getService().clearABRepeatRange(); if (mApp.getService().getRepeatMode() == Common.REPEAT_OFF) { mRepeatButton.setImageResource(R.drawable.repeat_highlighted); mApp.getService().setRepeatMode(Common.REPEAT_PLAYLIST); } else if (mApp.getService().getRepeatMode() == Common.REPEAT_PLAYLIST) { mRepeatButton.setImageResource(R.drawable.repeat_song); mApp.getService().setRepeatMode(Common.REPEAT_SONG); } else { mRepeatButton.setImageResource(UIElementsHelper.getIcon(mContext, "repeat")); mApp.getService().setRepeatMode(Common.REPEAT_OFF); } }
/** Sets the seekbar's duration. Also updates the elapsed/remaining duration text. */ private void setSeekbarDuration(int duration) { mSeekbar.setMax(duration); mSeekbar.setProgress(mApp.getService().getCurrentMediaPlayer().getCurrentPosition() / 1000); mHandler.postDelayed(seekbarUpdateRunnable, 100); }
@Override public void onPause() { super.onPause(); if (isFinishing()) mApp.setNowPlayingActivity(null); }
@SuppressLint("NewApi") @Override protected void onCreate(Bundle savedInstanceState) { mContext = getApplicationContext(); mApp = (Common) getApplicationContext(); mApp.setNowPlayingActivity(this); setNowPlayingActivityListener(mApp.getPlaybackKickstarter()); // Set the UI theme. setTheme(); super.onCreate(savedInstanceState); setContentView(R.layout.activity_now_playing); // Set the volume stream for this activity. this.setVolumeControlStream(AudioManager.STREAM_MUSIC); // Drawer layout. if (!mApp.isTabletInLandscape()) { mDrawerLayout = (DrawerLayout) findViewById(R.id.main_activity_drawer_root); mDrawerParentLayout = (FrameLayout) findViewById(R.id.now_playing_drawer_frame_root); mCurrentQueueLayout = (RelativeLayout) findViewById(R.id.queue_drawer); mDrawerLayout.setDrawerListener(mDrawerListener); mDrawerLayout.setBackgroundColor(UIElementsHelper.getBackgroundColor(mContext)); } else { mCurrentQueueLayout = (RelativeLayout) findViewById(R.id.queue_drawer); } // ViewPager. mViewPager = (VelocityViewPager) findViewById(R.id.nowPlayingPlaylistPager); // Seekbar indicator. mSeekbarIndicatorLayoutParent = (RelativeLayout) findViewById(R.id.seekbarIndicatorParent); mSeekbarIndicatorLayout = (RelativeLayout) findViewById(R.id.seekbarIndicator); mSeekbarIndicatorText = (TextView) findViewById(R.id.seekbarIndicatorText); mSeekbarIndicatorLayoutParent.setVisibility(View.GONE); mSeekbarIndicatorLayout.setBackgroundResource( UIElementsHelper.getGridViewCardBackground(mContext)); mSeekbarIndicatorText.setTypeface(TypefaceHelper.getTypeface(mContext, "Roboto-Regular")); mSeekbarIndicatorText.setTextColor(UIElementsHelper.getThemeBasedTextColor(mContext)); // Playback Controls. mControlsLayoutHeaderParent = (RelativeLayout) findViewById(R.id.now_playing_controls_header_parent); mControlsLayoutHeader = (RelativeLayout) findViewById(R.id.now_playing_controls_header); mPlayPauseButtonBackground = (RelativeLayout) findViewById(R.id.playPauseButtonBackground); mPlayPauseButton = (ImageButton) findViewById(R.id.playPauseButton); mNextButton = (ImageButton) findViewById(R.id.nextButton); mPreviousButton = (ImageButton) findViewById(R.id.previousButton); mShuffleButton = (ImageButton) findViewById(R.id.shuffleButton); mRepeatButton = (ImageButton) findViewById(R.id.repeatButton); // Song info/seekbar elements. mSeekbar = (SeekBar) findViewById(R.id.nowPlayingSeekBar); mStreamingProgressBar = (ProgressBar) findViewById(R.id.startingStreamProgressBar); mStreamingProgressBar.setVisibility(View.GONE); try { mSeekbar.setThumb(getResources().getDrawable(R.drawable.transparent_drawable)); } catch (Exception e) { e.printStackTrace(); } mPlayPauseButtonBackground.setBackgroundResource(UIElementsHelper.getShadowedCircle(mContext)); mPlayPauseButton.setImageResource(R.drawable.pause_light); mPlayPauseButton.setId(R.drawable.pause_light); mNextButton.setImageResource(UIElementsHelper.getIcon(mContext, "btn_playback_next")); mPreviousButton.setImageResource(UIElementsHelper.getIcon(mContext, "btn_playback_previous")); if (mApp.getCurrentTheme() == Common.DARK_THEME) { mNextButton.setAlpha(1f); mPreviousButton.setAlpha(1f); } // KitKat specific layout code. setKitKatTranslucentBars(); // Set the control buttons and background. setControlButtonsBackground(); setPlayPauseButton(); setShuffleButtonIcon(); setRepeatButtonIcon(); // Set the click listeners. mSeekbar.setOnSeekBarChangeListener(seekBarChangeListener); mNextButton.setOnClickListener(mOnClickNextListener); mPreviousButton.setOnClickListener(mOnClickPreviousListener); mPlayPauseButton.setOnClickListener(playPauseClickListener); mPlayPauseButtonBackground.setOnClickListener(playPauseClickListener); mShuffleButton.setOnClickListener(shuffleButtonClickListener); mRepeatButton.setOnClickListener(repeatButtonClickListener); // Apply haptic feedback to the play/pause button. mPlayPauseButtonBackground.setHapticFeedbackEnabled(true); mPlayPauseButton.setHapticFeedbackEnabled(true); }