diff options
Diffstat (limited to 'samples/Support7Demos/src/com/example/android')
13 files changed, 599 insertions, 299 deletions
diff --git a/samples/Support7Demos/src/com/example/android/supportv7/app/ActionBarWithDrawerLayout.java b/samples/Support7Demos/src/com/example/android/supportv7/app/ActionBarWithDrawerLayout.java deleted file mode 100644 index a45edc986..000000000 --- a/samples/Support7Demos/src/com/example/android/supportv7/app/ActionBarWithDrawerLayout.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.example.android.supportv7.app; - -import com.example.android.supportv7.R; -import com.example.android.supportv7.Shakespeare; - -import android.content.res.Configuration; -import android.os.Bundle; -import android.support.v4.view.GravityCompat; -import android.support.v4.widget.DrawerLayout; -import android.support.v7.app.ActionBar; -import android.support.v7.app.ActionBarDrawerToggle; -import android.support.v7.app.AppCompatActivity; -import android.view.MenuItem; -import android.view.View; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.ListView; -import android.widget.TextView; - -public class ActionBarWithDrawerLayout extends AppCompatActivity { - private DrawerLayout mDrawerLayout; - private ListView mDrawer; - private TextView mContent; - - private ActionBarHelper mActionBar; - - private ActionBarDrawerToggle mDrawerToggle; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.action_bar_drawer_layout); - mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); - mDrawer = (ListView) findViewById(R.id.start_drawer); - mContent = (TextView) findViewById(R.id.content_text); - - mDrawerLayout.setDrawerListener(new DemoDrawerListener()); - - // The drawer title must be set in order to announce state changes when - // accessibility is turned on. This is typically a simple description, - // e.g. "Navigation". - mDrawerLayout.setDrawerTitle(GravityCompat.START, getString(R.string.drawer_title)); - - mDrawer.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, - Shakespeare.TITLES)); - mDrawer.setOnItemClickListener(new DrawerItemClickListener()); - - mActionBar = createActionBarHelper(); - mActionBar.init(); - - // ActionBarDrawerToggle provides convenient helpers for tying together the - // prescribed interactions between a top-level sliding drawer and the action bar. - mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, - R.string.drawer_open, R.string.drawer_close); - } - - @Override - protected void onPostCreate(Bundle savedInstanceState) { - super.onPostCreate(savedInstanceState); - - // Sync the toggle state after onRestoreInstanceState has occurred. - mDrawerToggle.syncState(); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - /* - * The action bar home/up action should open or close the drawer. - * mDrawerToggle will take care of this. - */ - if (mDrawerToggle.onOptionsItemSelected(item)) { - return true; - } - return super.onOptionsItemSelected(item); - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - mDrawerToggle.onConfigurationChanged(newConfig); - } - - /** - * This list item click listener implements very simple view switching by changing - * the primary content text. The drawer is closed when a selection is made. - */ - private class DrawerItemClickListener implements ListView.OnItemClickListener { - @Override - public void onItemClick(AdapterView<?> parent, View view, int position, long id) { - mContent.setText(Shakespeare.DIALOGUE[position]); - mActionBar.setTitle(Shakespeare.TITLES[position]); - mDrawerLayout.closeDrawer(mDrawer); - } - } - - /** - * A drawer listener can be used to respond to drawer events such as becoming - * fully opened or closed. You should always prefer to perform expensive operations - * such as drastic relayout when no animation is currently in progress, either before - * or after the drawer animates. - * - * When using ActionBarDrawerToggle, all DrawerLayout listener methods should be forwarded - * if the ActionBarDrawerToggle is not used as the DrawerLayout listener directly. - */ - private class DemoDrawerListener implements DrawerLayout.DrawerListener { - @Override - public void onDrawerOpened(View drawerView) { - mDrawerToggle.onDrawerOpened(drawerView); - mActionBar.onDrawerOpened(); - } - - @Override - public void onDrawerClosed(View drawerView) { - mDrawerToggle.onDrawerClosed(drawerView); - mActionBar.onDrawerClosed(); - } - - @Override - public void onDrawerSlide(View drawerView, float slideOffset) { - mDrawerToggle.onDrawerSlide(drawerView, slideOffset); - } - - @Override - public void onDrawerStateChanged(int newState) { - mDrawerToggle.onDrawerStateChanged(newState); - } - } - - /** - * Create a compatible helper that will manipulate the action bar if available. - */ - private ActionBarHelper createActionBarHelper() { - return new ActionBarHelper(); - } - - /** - * Action bar helper for use on ICS and newer devices. - */ - private class ActionBarHelper { - private final ActionBar mActionBar; - private CharSequence mDrawerTitle; - private CharSequence mTitle; - - ActionBarHelper() { - mActionBar = getSupportActionBar(); - } - - public void init() { - mActionBar.setDisplayHomeAsUpEnabled(true); - mActionBar.setDisplayShowHomeEnabled(false); - mTitle = mDrawerTitle = getTitle(); - } - - /** - * When the drawer is closed we restore the action bar state reflecting - * the specific contents in view. - */ - public void onDrawerClosed() { - mActionBar.setTitle(mTitle); - } - - /** - * When the drawer is open we set the action bar to a generic title. - * The action bar should only contain data relevant at the top level of - * the nav hierarchy represented by the drawer, as the rest of your content - * will be dimmed down and non-interactive. - */ - public void onDrawerOpened() { - mActionBar.setTitle(mDrawerTitle); - } - - public void setTitle(CharSequence title) { - mTitle = title; - } - } -} diff --git a/samples/Support7Demos/src/com/example/android/supportv7/media/LocalPlayer.java b/samples/Support7Demos/src/com/example/android/supportv7/media/LocalPlayer.java index b3c14c26b..b62f76e93 100644 --- a/samples/Support7Demos/src/com/example/android/supportv7/media/LocalPlayer.java +++ b/samples/Support7Demos/src/com/example/android/supportv7/media/LocalPlayer.java @@ -20,15 +20,12 @@ import android.app.Activity; import android.app.Presentation; import android.content.Context; import android.content.DialogInterface; -import android.content.res.Resources; import android.graphics.Bitmap; import android.media.MediaPlayer; -import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.SystemClock; -import android.support.v4.media.session.MediaSessionCompat; import android.support.v7.media.MediaRouter.RouteInfo; import android.support.v7.media.MediaItemStatus; import android.util.Log; @@ -59,6 +56,7 @@ public abstract class LocalPlayer extends Player implements private final Context mContext; private final Handler mHandler = new Handler(); + private final Handler mUpdateSurfaceHandler = new Handler(mHandler.getLooper()); private MediaPlayer mMediaPlayer; private int mState = STATE_IDLE; private int mSeekToPos; @@ -104,11 +102,6 @@ public abstract class LocalPlayer extends Player implements } } - @Override - public MediaSessionCompat getMediaSession() { - return mMediaSession; - } - // Player @Override public void play(final PlaylistItem item) { @@ -145,7 +138,8 @@ public abstract class LocalPlayer extends Player implements if (mState == STATE_PLAYING || mState == STATE_PAUSED) { mMediaPlayer.seekTo(pos); mSeekToPos = pos; - } else if (mState == STATE_IDLE || mState == STATE_PLAY_PENDING) { + } else if (mState == STATE_IDLE || mState == STATE_PREPARING_FOR_PLAY + || mState == STATE_PREPARING_FOR_PAUSE) { // Seek before onPrepared() arrives, // need to performed delayed seek in onPrepared() mSeekToPos = pos; @@ -175,6 +169,8 @@ public abstract class LocalPlayer extends Player implements if (mState == STATE_PLAYING) { mMediaPlayer.pause(); mState = STATE_PAUSED; + } else if (mState == STATE_PREPARING_FOR_PLAY) { + mState = STATE_PREPARING_FOR_PAUSE; } } @@ -186,8 +182,8 @@ public abstract class LocalPlayer extends Player implements if (mState == STATE_READY || mState == STATE_PAUSED) { mMediaPlayer.start(); mState = STATE_PLAYING; - } else if (mState == STATE_IDLE){ - mState = STATE_PLAY_PENDING; + } else if (mState == STATE_IDLE || mState == STATE_PREPARING_FOR_PAUSE) { + mState = STATE_PREPARING_FOR_PLAY; } } @@ -224,8 +220,10 @@ public abstract class LocalPlayer extends Player implements if (mState == STATE_IDLE) { mState = STATE_READY; updateVideoRect(); - } else if (mState == STATE_PLAY_PENDING) { - mState = STATE_PLAYING; + } else if (mState == STATE_PREPARING_FOR_PLAY + || mState == STATE_PREPARING_FOR_PAUSE) { + int prevState = mState; + mState = mState == STATE_PREPARING_FOR_PLAY ? STATE_PLAYING : STATE_PAUSED; updateVideoRect(); if (mSeekToPos > 0) { if (DEBUG) { @@ -233,7 +231,9 @@ public abstract class LocalPlayer extends Player implements } mMediaPlayer.seekTo(mSeekToPos); } - mMediaPlayer.start(); + if (prevState == STATE_PREPARING_FOR_PLAY) { + mMediaPlayer.start(); + } } if (mCallback != null) { mCallback.onPlaylistChanged(); @@ -294,6 +294,7 @@ public abstract class LocalPlayer extends Player implements protected MediaPlayer getMediaPlayer() { return mMediaPlayer; } protected int getVideoWidth() { return mVideoWidth; } protected int getVideoHeight() { return mVideoHeight; } + protected int getState() { return mState; } protected void setSurface(Surface surface) { mSurface = surface; mSurfaceHolder = null; @@ -313,23 +314,29 @@ public abstract class LocalPlayer extends Player implements } protected void updateSurface() { - if (mMediaPlayer == null) { - // just return if media player is already gone - return; - } - if (mSurface != null) { - // The setSurface API does not exist until V14+. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - ICSMediaPlayer.setSurface(mMediaPlayer, mSurface); - } else { - throw new UnsupportedOperationException("MediaPlayer does not support " - + "setSurface() on this version of the platform."); + mUpdateSurfaceHandler.removeCallbacksAndMessages(null); + mUpdateSurfaceHandler.post(new Runnable() { + @Override + public void run() { + if (mMediaPlayer == null) { + // just return if media player is already gone + return; + } + if (mSurface != null) { + // The setSurface API does not exist until V14+. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + ICSMediaPlayer.setSurface(mMediaPlayer, mSurface); + } else { + throw new UnsupportedOperationException("MediaPlayer does not support " + + "setSurface() on this version of the platform."); + } + } else if (mSurfaceHolder != null) { + mMediaPlayer.setDisplay(mSurfaceHolder); + } else { + mMediaPlayer.setDisplay(null); + } } - } else if (mSurfaceHolder != null) { - mMediaPlayer.setDisplay(mSurfaceHolder); - } else { - mMediaPlayer.setDisplay(null); - } + }); } protected abstract void updateSize(); @@ -351,7 +358,8 @@ public abstract class LocalPlayer extends Player implements } private void updateVideoRect() { - if (mState != STATE_IDLE && mState != STATE_PLAY_PENDING) { + if (mState != STATE_IDLE && mState != STATE_PREPARING_FOR_PLAY + && mState != STATE_PREPARING_FOR_PAUSE) { int width = mMediaPlayer.getVideoWidth(); int height = mMediaPlayer.getVideoHeight(); if (width > 0 && height > 0) { @@ -632,7 +640,10 @@ public abstract class LocalPlayer extends Player implements @Override public Bitmap getSnapshot() { - return mOverlay.getSnapshot(); + if (getState() == STATE_PLAYING || getState() == STATE_PAUSED) { + return mOverlay.getSnapshot(); + } + return null; } } } diff --git a/samples/Support7Demos/src/com/example/android/supportv7/media/MyMediaRouteControllerDialog.java b/samples/Support7Demos/src/com/example/android/supportv7/media/MyMediaRouteControllerDialog.java new file mode 100644 index 000000000..326467174 --- /dev/null +++ b/samples/Support7Demos/src/com/example/android/supportv7/media/MyMediaRouteControllerDialog.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.supportv7.media; + +import android.graphics.Color; +import android.os.Bundle; +import android.support.v7.app.MediaRouteControllerDialog; + +import android.content.Context; +import android.view.View; +import android.widget.TextView; +import com.example.android.supportv7.R; + +/** + * An example MediaRouteControllerDialog for demonstrating + * {@link android.support.v7.app.MediaRouteControllerDialog#onCreateMediaControlView}. + */ +public class MyMediaRouteControllerDialog extends MediaRouteControllerDialog { + public MyMediaRouteControllerDialog(Context context) { + super(context); + } + + @Override + public View onCreateMediaControlView(Bundle savedInstanceState) { + TextView view = new TextView(getContext()); + view.setText(R.string.my_media_control_text); + view.setBackgroundColor(Color.GRAY); + return view; + } +} diff --git a/samples/Support7Demos/src/com/example/android/supportv7/media/OverlayDisplayWindow.java b/samples/Support7Demos/src/com/example/android/supportv7/media/OverlayDisplayWindow.java index 80cc77d9a..1d4aaa12d 100644 --- a/samples/Support7Demos/src/com/example/android/supportv7/media/OverlayDisplayWindow.java +++ b/samples/Support7Demos/src/com/example/android/supportv7/media/OverlayDisplayWindow.java @@ -19,7 +19,6 @@ import com.example.android.supportv7.R; import android.content.Context; import android.graphics.Bitmap; -import android.graphics.Point; import android.graphics.SurfaceTexture; import android.hardware.display.DisplayManager; import android.os.Build; @@ -95,9 +94,9 @@ public abstract class OverlayDisplayWindow { // Watches for significant changes in the overlay display window lifecycle. public interface OverlayWindowListener { - public void onWindowCreated(Surface surface); - public void onWindowCreated(SurfaceHolder surfaceHolder); - public void onWindowDestroyed(); + void onWindowCreated(Surface surface); + void onWindowCreated(SurfaceHolder surfaceHolder); + void onWindowDestroyed(); } /** diff --git a/samples/Support7Demos/src/com/example/android/supportv7/media/Player.java b/samples/Support7Demos/src/com/example/android/supportv7/media/Player.java index fcab57dd9..a5d58971e 100644 --- a/samples/Support7Demos/src/com/example/android/supportv7/media/Player.java +++ b/samples/Support7Demos/src/com/example/android/supportv7/media/Player.java @@ -16,10 +16,7 @@ package com.example.android.supportv7.media; -import android.app.PendingIntent; -import android.content.ComponentName; import android.content.Context; -import android.content.Intent; import android.graphics.Bitmap; import android.support.v4.media.MediaMetadataCompat; import android.support.v4.media.session.MediaSessionCompat; @@ -32,17 +29,22 @@ import android.util.Log; * Abstraction of common playback operations of media items, such as play, * seek, etc. Used by PlaybackManager as a backend to handle actual playback * of media items. + * + * TODO: Introduce prepare() method and refactor subclasses accordingly. */ public abstract class Player { private static final String TAG = "SampleMediaRoutePlayer"; protected static final int STATE_IDLE = 0; - protected static final int STATE_PLAY_PENDING = 1; - protected static final int STATE_READY = 2; - protected static final int STATE_PLAYING = 3; - protected static final int STATE_PAUSED = 4; + protected static final int STATE_PREPARING_FOR_PLAY = 1; + protected static final int STATE_PREPARING_FOR_PAUSE = 2; + protected static final int STATE_READY = 3; + protected static final int STATE_PLAYING = 4; + protected static final int STATE_PAUSED = 5; private static final long PLAYBACK_ACTIONS = PlaybackStateCompat.ACTION_PAUSE | PlaybackStateCompat.ACTION_PLAY; + private static final PlaybackStateCompat INIT_PLAYBACK_STATE = new PlaybackStateCompat.Builder() + .setState(PlaybackStateCompat.STATE_NONE, 0, .0f).build(); protected Callback mCallback; protected MediaSessionCompat mMediaSession; @@ -88,13 +90,18 @@ public abstract class Player { } else { player = new LocalPlayer.OverlayPlayer(context); } - player.initMediaSession(session); + player.setMediaSession(session); + player.initMediaSession(); player.connect(route); return player; } - public MediaSessionCompat getMediaSession() { - return mMediaSession; + protected void initMediaSession() { + if (mMediaSession == null) { + return; + } + mMediaSession.setMetadata(null); + mMediaSession.setPlaybackState(INIT_PLAYBACK_STATE); } protected void updateMetadata() { @@ -138,16 +145,14 @@ public abstract class Player { } } - private void initMediaSession(MediaSessionCompat session) { + private void setMediaSession(MediaSessionCompat session) { mMediaSession = session; - updateMetadata(); } - public interface Callback { void onError(); void onCompletion(); void onPlaylistChanged(); void onPlaylistReady(); } -}
\ No newline at end of file +} diff --git a/samples/Support7Demos/src/com/example/android/supportv7/media/RemotePlayer.java b/samples/Support7Demos/src/com/example/android/supportv7/media/RemotePlayer.java index d47c26069..6ad4f75db 100644 --- a/samples/Support7Demos/src/com/example/android/supportv7/media/RemotePlayer.java +++ b/samples/Support7Demos/src/com/example/android/supportv7/media/RemotePlayer.java @@ -19,10 +19,8 @@ package com.example.android.supportv7.media; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; -import android.net.Uri; import android.os.Bundle; import android.support.v7.media.MediaItemStatus; -import android.support.v7.media.MediaControlIntent; import android.support.v7.media.MediaRouter.ControlRequestCallback; import android.support.v7.media.MediaRouter.RouteInfo; import android.support.v7.media.MediaSessionStatus; @@ -140,7 +138,6 @@ public class RemotePlayer extends Player { } if (item.getState() == MediaItemStatus.PLAYBACK_STATE_PAUSED) { pause(); - publishState(STATE_PAUSED); } else { publishState(STATE_PLAYING); } @@ -385,6 +382,8 @@ public class RemotePlayer extends Player { } if (item.getState() == MediaItemStatus.PLAYBACK_STATE_PAUSED) { pause(); + } else if (item.getState() == MediaItemStatus.PLAYBACK_STATE_PLAYING) { + publishState(STATE_PLAYING); } if (mEnqueuePending) { mEnqueuePending = false; diff --git a/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaButtonReceiver.java b/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaButtonReceiver.java index c2eec8ec5..d35644680 100644 --- a/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaButtonReceiver.java +++ b/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaButtonReceiver.java @@ -16,12 +16,9 @@ package com.example.android.supportv7.media; -import com.example.android.supportv7.R; - import android.content.Context; import android.content.Intent; import android.content.BroadcastReceiver; -import android.util.Log; import android.view.KeyEvent; /** diff --git a/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaRouteProvider.java b/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaRouteProvider.java index 15cf19b7d..4208f5894 100644 --- a/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaRouteProvider.java +++ b/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaRouteProvider.java @@ -16,31 +16,26 @@ package com.example.android.supportv7.media; -import com.example.android.supportv7.R; - +import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.IntentFilter.MalformedMimeTypeException; import android.content.IntentSender; import android.content.res.Resources; -import android.graphics.Bitmap; import android.media.AudioManager; import android.media.MediaRouter; import android.net.Uri; import android.os.Bundle; -import android.app.PendingIntent; import android.support.v7.media.MediaControlIntent; -import android.support.v7.media.MediaItemStatus; +import android.support.v7.media.MediaRouteDescriptor; import android.support.v7.media.MediaRouteProvider; -import android.support.v7.media.MediaRouter.ControlRequestCallback; import android.support.v7.media.MediaRouteProviderDescriptor; -import android.support.v7.media.MediaRouteDescriptor; +import android.support.v7.media.MediaRouter.ControlRequestCallback; import android.support.v7.media.MediaSessionStatus; import android.util.Log; -import android.view.Gravity; -import android.view.Surface; -import android.view.SurfaceHolder; + +import com.example.android.supportv7.R; import java.util.ArrayList; @@ -56,6 +51,7 @@ final class SampleMediaRouteProvider extends MediaRouteProvider { private static final String VARIABLE_VOLUME_BASIC_ROUTE_ID = "variable_basic"; private static final String VARIABLE_VOLUME_QUEUING_ROUTE_ID = "variable_queuing"; private static final String VARIABLE_VOLUME_SESSION_ROUTE_ID = "variable_session"; + private static final int VOLUME_MAX = 10; /** @@ -135,18 +131,16 @@ final class SampleMediaRouteProvider extends MediaRouteProvider { f6.addAction(MediaControlIntent.ACTION_GET_SESSION_STATUS); f6.addAction(MediaControlIntent.ACTION_END_SESSION); - CONTROL_FILTERS_BASIC = new ArrayList<IntentFilter>(); + CONTROL_FILTERS_BASIC = new ArrayList<>(); CONTROL_FILTERS_BASIC.add(f1); CONTROL_FILTERS_BASIC.add(f2); CONTROL_FILTERS_BASIC.add(f3); - CONTROL_FILTERS_QUEUING = - new ArrayList<IntentFilter>(CONTROL_FILTERS_BASIC); + CONTROL_FILTERS_QUEUING = new ArrayList<>(CONTROL_FILTERS_BASIC); CONTROL_FILTERS_QUEUING.add(f4); CONTROL_FILTERS_QUEUING.add(f5); - CONTROL_FILTERS_SESSION = - new ArrayList<IntentFilter>(CONTROL_FILTERS_QUEUING); + CONTROL_FILTERS_SESSION = new ArrayList<>(CONTROL_FILTERS_QUEUING); CONTROL_FILTERS_SESSION.add(f6); } @@ -159,7 +153,6 @@ final class SampleMediaRouteProvider extends MediaRouteProvider { } private int mVolume = 5; - private int mEnqueueCount; public SampleMediaRouteProvider(Context context) { super(context); @@ -218,6 +211,8 @@ final class SampleMediaRouteProvider extends MediaRouteProvider { .setCanDisconnect(true) .build(); + Uri iconUri = Uri.parse("android.resource://com.example.android.supportv7/" + + R.drawable.ic_android); MediaRouteDescriptor routeDescriptor4 = new MediaRouteDescriptor.Builder( VARIABLE_VOLUME_SESSION_ROUTE_ID, r.getString(R.string.variable_volume_session_route_name)) @@ -228,10 +223,10 @@ final class SampleMediaRouteProvider extends MediaRouteProvider { .setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE) .setVolumeMax(VOLUME_MAX) .setVolume(mVolume) + .setIconUri(iconUri) .build(); - MediaRouteProviderDescriptor providerDescriptor = - new MediaRouteProviderDescriptor.Builder() + MediaRouteProviderDescriptor providerDescriptor = new MediaRouteProviderDescriptor.Builder() .addRoute(routeDescriptor1) .addRoute(routeDescriptor2) .addRoute(routeDescriptor3) @@ -412,7 +407,6 @@ final class SampleMediaRouteProvider extends MediaRouteProvider { callback.onError("Failed to open " + uri.toString(), null); } } - mEnqueueCount +=1; return true; } @@ -620,4 +614,4 @@ final class SampleMediaRouteProvider extends MediaRouteProvider { } } } -}
\ No newline at end of file +} diff --git a/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaRouterActivity.java b/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaRouterActivity.java index 0a64c55fb..a40992302 100644 --- a/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaRouterActivity.java +++ b/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaRouterActivity.java @@ -56,6 +56,7 @@ import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; +import android.widget.CheckBox; import android.widget.ImageButton; import android.widget.ListView; import android.widget.SeekBar; @@ -79,6 +80,7 @@ import java.io.File; public class SampleMediaRouterActivity extends AppCompatActivity { private static final String TAG = "SampleMediaRouterActivity"; private static final String DISCOVERY_FRAGMENT_TAG = "DiscoveryFragment"; + private static final boolean ENABLE_DEFAULT_CONTROL_CHECK_BOX = false; private MediaRouter mMediaRouter; private MediaRouteSelector mSelector; @@ -87,6 +89,7 @@ public class SampleMediaRouterActivity extends AppCompatActivity { private TextView mInfoTextView; private ListView mLibraryView; private ListView mPlayListView; + private CheckBox mUseDefaultControlCheckBox; private ImageButton mPauseResumeButton; private ImageButton mStopButton; private SeekBar mSeekBar; @@ -308,6 +311,10 @@ public class SampleMediaRouterActivity extends AppCompatActivity { mInfoTextView = (TextView) findViewById(R.id.info); + mUseDefaultControlCheckBox = (CheckBox) findViewById(R.id.custom_control_view_checkbox); + if (ENABLE_DEFAULT_CONTROL_CHECK_BOX) { + mUseDefaultControlCheckBox.setVisibility(View.VISIBLE); + } mPauseResumeButton = (ImageButton)findViewById(R.id.pause_resume_button); mPauseResumeButton.setOnClickListener(new OnClickListener() { @Override @@ -518,7 +525,7 @@ public class SampleMediaRouterActivity extends AppCompatActivity { mediaRouteActionProvider.setDialogFactory(new MediaRouteDialogFactory() { @Override public MediaRouteControllerDialogFragment onCreateControllerDialogFragment() { - return new ControllerDialogFragment(mPlayer); + return new ControllerDialogFragment(mPlayer, mUseDefaultControlCheckBox); } }); @@ -734,20 +741,23 @@ public class SampleMediaRouterActivity extends AppCompatActivity { public static class ControllerDialogFragment extends MediaRouteControllerDialogFragment { private MediaRouteControllerDialog mControllerDialog; private Player mPlayer; + private CheckBox mUseDefaultControlCheckBox; public ControllerDialogFragment() { super(); } - public ControllerDialogFragment(Player player) { + public ControllerDialogFragment(Player player, CheckBox customControlViewCheckBox) { mPlayer = player; + this.mUseDefaultControlCheckBox = customControlViewCheckBox; } @Override public MediaRouteControllerDialog onCreateControllerDialog( Context context, Bundle savedInstanceState) { - mControllerDialog = super.onCreateControllerDialog(context, - savedInstanceState); + mControllerDialog = this.mUseDefaultControlCheckBox.isChecked() + ? super.onCreateControllerDialog(context, savedInstanceState) + : new MyMediaRouteControllerDialog(context); mControllerDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { @Override public void onDismiss(DialogInterface dialog) { diff --git a/samples/Support7Demos/src/com/example/android/supportv7/media/SessionManager.java b/samples/Support7Demos/src/com/example/android/supportv7/media/SessionManager.java index 1c00192de..6fab2eb6b 100644 --- a/samples/Support7Demos/src/com/example/android/supportv7/media/SessionManager.java +++ b/samples/Support7Demos/src/com/example/android/supportv7/media/SessionManager.java @@ -349,6 +349,8 @@ public class SessionManager implements Player.Callback { if (mCallback != null) { mCallback.onItemChanged(item); } + } else { + mPlayer.initMediaSession(); } updateStatus(); } diff --git a/samples/Support7Demos/src/com/example/android/supportv7/widget/AnimatedRecyclerView.java b/samples/Support7Demos/src/com/example/android/supportv7/widget/AnimatedRecyclerView.java index af5c6532d..6714f6d02 100644 --- a/samples/Support7Demos/src/com/example/android/supportv7/widget/AnimatedRecyclerView.java +++ b/samples/Support7Demos/src/com/example/android/supportv7/widget/AnimatedRecyclerView.java @@ -15,13 +15,20 @@ */ package com.example.android.supportv7.widget; -import android.support.v4.util.ArrayMap; -import android.widget.CompoundButton; import com.example.android.supportv7.R; + +import android.animation.Animator; +import android.animation.ValueAnimator; +import android.annotation.TargetApi; import android.app.Activity; import android.content.Context; +import android.os.Build; import android.os.Bundle; +import android.support.v4.util.ArrayMap; import android.support.v4.view.MenuItemCompat; +import android.support.v4.view.ViewCompat; +import android.support.v4.view.ViewPropertyAnimatorListener; +import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.RecyclerView; import android.util.DisplayMetrics; import android.util.TypedValue; @@ -30,10 +37,10 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; +import android.widget.CompoundButton; import android.widget.TextView; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; public class AnimatedRecyclerView extends Activity { @@ -49,6 +56,7 @@ public class AnimatedRecyclerView extends Activity { boolean mAnimationsEnabled = true; boolean mPredictiveAnimationsEnabled = true; RecyclerView.ItemAnimator mCachedAnimator = null; + boolean mEnableInPlaceChange = true; @Override protected void onCreate(Bundle savedInstanceState) { @@ -57,7 +65,9 @@ public class AnimatedRecyclerView extends Activity { ViewGroup container = (ViewGroup) findViewById(R.id.container); mRecyclerView = new RecyclerView(this); - mCachedAnimator = mRecyclerView.getItemAnimator(); + mCachedAnimator = createAnimator(); + mCachedAnimator.setChangeDuration(2000); + mRecyclerView.setItemAnimator(mCachedAnimator); mRecyclerView.setLayoutManager(new MyLayoutManager(this)); mRecyclerView.setHasFixedSize(true); mRecyclerView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, @@ -91,14 +101,241 @@ public class AnimatedRecyclerView extends Activity { } }); - CheckBox enableChangeAnimations = - (CheckBox) findViewById(R.id.enableChangeAnimations); - enableChangeAnimations.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + CheckBox enableInPlaceChange = (CheckBox) findViewById(R.id.enableInPlaceChange); + enableInPlaceChange.setChecked(mEnableInPlaceChange); + enableInPlaceChange.setOnCheckedChangeListener( + new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + mEnableInPlaceChange = isChecked; + } + }); + } + + private RecyclerView.ItemAnimator createAnimator() { + return new DefaultItemAnimator() { + List<ItemChangeAnimator> mPendingChangeAnimations = new ArrayList<>(); + ArrayMap<RecyclerView.ViewHolder, ItemChangeAnimator> mRunningAnimations + = new ArrayMap<>(); + ArrayMap<MyViewHolder, Long> mPendingSettleList = new ArrayMap<>(); + @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - mCachedAnimator.setSupportsChangeAnimations(isChecked); + public void runPendingAnimations() { + super.runPendingAnimations(); + for (ItemChangeAnimator anim : mPendingChangeAnimations) { + anim.start(); + mRunningAnimations.put(anim.mViewHolder, anim); + } + mPendingChangeAnimations.clear(); + for (int i = mPendingSettleList.size() - 1; i >=0; i--) { + final MyViewHolder vh = mPendingSettleList.keyAt(i); + final long duration = mPendingSettleList.valueAt(i); + ViewCompat.animate(vh.textView).translationX(0f).alpha(1f) + .setDuration(duration).setListener( + new ViewPropertyAnimatorListener() { + @Override + public void onAnimationStart(View view) { + dispatchAnimationStarted(vh); + } + + @Override + public void onAnimationEnd(View view) { + ViewCompat.setTranslationX(vh.textView, 0f); + ViewCompat.setAlpha(vh.textView, 1f); + dispatchAnimationFinished(vh); + } + + @Override + public void onAnimationCancel(View view) { + + } + }).start(); + } + mPendingSettleList.clear(); } - }); + + @Override + public ItemHolderInfo recordPreLayoutInformation(RecyclerView.State state, + RecyclerView.ViewHolder viewHolder, + @AdapterChanges int changeFlags, List<Object> payloads) { + MyItemInfo info = (MyItemInfo) super + .recordPreLayoutInformation(state, viewHolder, changeFlags, payloads); + info.text = ((MyViewHolder) viewHolder).textView.getText(); + return info; + } + + @Override + public ItemHolderInfo recordPostLayoutInformation(RecyclerView.State state, + RecyclerView.ViewHolder viewHolder) { + MyItemInfo info = (MyItemInfo) super.recordPostLayoutInformation(state, viewHolder); + info.text = ((MyViewHolder) viewHolder).textView.getText(); + return info; + } + + + @Override + public boolean canReuseUpdatedViewHolder(RecyclerView.ViewHolder viewHolder) { + return mEnableInPlaceChange; + } + + @Override + public void endAnimation(RecyclerView.ViewHolder item) { + super.endAnimation(item); + for (int i = mPendingChangeAnimations.size() - 1; i >= 0; i--) { + ItemChangeAnimator anim = mPendingChangeAnimations.get(i); + if (anim.mViewHolder == item) { + mPendingChangeAnimations.remove(i); + anim.setFraction(1f); + dispatchChangeFinished(item, true); + } + } + for (int i = mRunningAnimations.size() - 1; i >= 0; i--) { + ItemChangeAnimator animator = mRunningAnimations.get(item); + if (animator != null) { + animator.end(); + mRunningAnimations.removeAt(i); + } + } + for (int i = mPendingSettleList.size() - 1; i >= 0; i--) { + final MyViewHolder vh = mPendingSettleList.keyAt(i); + if (vh == item) { + mPendingSettleList.removeAt(i); + dispatchChangeFinished(item, true); + } + } + } + + @Override + public boolean animateChange(RecyclerView.ViewHolder oldHolder, + RecyclerView.ViewHolder newHolder, ItemHolderInfo preInfo, + ItemHolderInfo postInfo) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1 + || oldHolder != newHolder) { + return super.animateChange(oldHolder, newHolder, preInfo, postInfo); + } + return animateChangeApiHoneycombMr1(oldHolder, newHolder, preInfo, postInfo); + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) + private boolean animateChangeApiHoneycombMr1(RecyclerView.ViewHolder oldHolder, + RecyclerView.ViewHolder newHolder, + ItemHolderInfo preInfo, ItemHolderInfo postInfo) { + endAnimation(oldHolder); + MyItemInfo pre = (MyItemInfo) preInfo; + MyItemInfo post = (MyItemInfo) postInfo; + MyViewHolder vh = (MyViewHolder) oldHolder; + + CharSequence finalText = post.text; + + if (pre.text.equals(post.text)) { + // same content. Just translate back to 0 + final long duration = (long) (getChangeDuration() + * (ViewCompat.getTranslationX(vh.textView) / vh.textView.getWidth())); + mPendingSettleList.put(vh, duration); + // we set it here because previous endAnimation would set it to other value. + vh.textView.setText(finalText); + } else { + // different content, get out and come back. + vh.textView.setText(pre.text); + final ItemChangeAnimator anim = new ItemChangeAnimator(vh, finalText, + getChangeDuration()) { + @Override + public void onAnimationEnd(Animator animation) { + setFraction(1f); + dispatchChangeFinished(mViewHolder, true); + } + + @Override + public void onAnimationStart(Animator animation) { + dispatchChangeStarting(mViewHolder, true); + } + }; + mPendingChangeAnimations.add(anim); + } + return true; + } + + @Override + public ItemHolderInfo obtainHolderInfo() { + return new MyItemInfo(); + } + }; + } + + + @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) + abstract private static class ItemChangeAnimator implements + ValueAnimator.AnimatorUpdateListener, Animator.AnimatorListener { + CharSequence mFinalText; + ValueAnimator mValueAnimator; + MyViewHolder mViewHolder; + final float mMaxX; + final float mStartRatio; + public ItemChangeAnimator(MyViewHolder viewHolder, CharSequence finalText, long duration) { + mViewHolder = viewHolder; + mMaxX = mViewHolder.itemView.getWidth(); + mStartRatio = ViewCompat.getTranslationX(mViewHolder.textView) / mMaxX; + mFinalText = finalText; + mValueAnimator = ValueAnimator.ofFloat(0f, 1f); + mValueAnimator.addUpdateListener(this); + mValueAnimator.addListener(this); + mValueAnimator.setDuration(duration); + mValueAnimator.setTarget(mViewHolder.itemView); + } + + void setFraction(float fraction) { + fraction = mStartRatio + (1f - mStartRatio) * fraction; + if (fraction < .5f) { + ViewCompat.setTranslationX(mViewHolder.textView, fraction * mMaxX); + ViewCompat.setAlpha(mViewHolder.textView, 1f - fraction); + } else { + ViewCompat.setTranslationX(mViewHolder.textView, (1f - fraction) * mMaxX); + ViewCompat.setAlpha(mViewHolder.textView, fraction); + maybeSetFinalText(); + } + } + + @Override + public void onAnimationUpdate(ValueAnimator valueAnimator) { + setFraction(valueAnimator.getAnimatedFraction()); + } + + public void start() { + mValueAnimator.start(); + } + + @Override + public void onAnimationEnd(Animator animation) { + maybeSetFinalText(); + ViewCompat.setAlpha(mViewHolder.textView, 1f); + } + + public void maybeSetFinalText() { + if (mFinalText != null) { + mViewHolder.textView.setText(mFinalText); + mFinalText = null; + } + } + + public void end() { + mValueAnimator.cancel(); + } + + @Override + public void onAnimationStart(Animator animation) { + } + + @Override + public void onAnimationCancel(Animator animation) { + } + + @Override + public void onAnimationRepeat(Animator animation) { + } + } + + private static class MyItemInfo extends DefaultItemAnimator.ItemHolderInfo { + CharSequence text; } @Override @@ -114,6 +351,7 @@ public class AnimatedRecyclerView extends Activity { return super.onOptionsItemSelected(item); } + @SuppressWarnings("unused") public void checkboxClicked(View view) { ViewGroup parent = (ViewGroup) view.getParent(); boolean selected = ((CheckBox) view).isChecked(); @@ -121,6 +359,7 @@ public class AnimatedRecyclerView extends Activity { mAdapter.selectItem(holder, selected); } + @SuppressWarnings("unused") public void itemClicked(View view) { ViewGroup parent = (ViewGroup) view; MyViewHolder holder = (MyViewHolder) mRecyclerView.getChildViewHolder(parent); @@ -462,20 +701,19 @@ public class AnimatedRecyclerView extends Activity { @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { String itemText = mData.get(position); - ((MyViewHolder) holder).textView.setText(itemText); - ((MyViewHolder) holder).expandedText.setText("More text for the expanded version"); + MyViewHolder myViewHolder = (MyViewHolder) holder; + myViewHolder.boundText = itemText; + myViewHolder.textView.setText(itemText); boolean selected = false; if (mSelected.get(itemText) != null) { selected = mSelected.get(itemText); } - ((MyViewHolder) holder).checkBox.setChecked(selected); + myViewHolder.checkBox.setChecked(selected); Boolean expanded = mExpanded.get(itemText); - if (expanded != null && expanded) { - ((MyViewHolder) holder).expandedText.setVisibility(View.VISIBLE); - ((MyViewHolder) holder).textView.setVisibility(View.GONE); + if (Boolean.TRUE.equals(expanded)) { + myViewHolder.textView.setText("More text for the expanded version"); } else { - ((MyViewHolder) holder).expandedText.setVisibility(View.GONE); - ((MyViewHolder) holder).textView.setVisibility(View.VISIBLE); + myViewHolder.textView.setText(itemText); } } @@ -484,28 +722,22 @@ public class AnimatedRecyclerView extends Activity { return mData.size(); } - public void selectItem(String itemText, boolean selected) { - mSelected.put(itemText, selected); - } - public void selectItem(MyViewHolder holder, boolean selected) { - mSelected.put((String) holder.textView.getText().toString(), selected); + mSelected.put(holder.boundText, selected); } public void toggleExpanded(MyViewHolder holder) { - String text = (String) holder.textView.getText(); - mExpanded.put(text, !mExpanded.get(text)); + mExpanded.put(holder.boundText, !mExpanded.get(holder.boundText)); } } static class MyViewHolder extends RecyclerView.ViewHolder { - public TextView expandedText; public TextView textView; public CheckBox checkBox; + public String boundText; public MyViewHolder(View v) { super(v); - expandedText = (TextView) v.findViewById(R.id.expandedText); textView = (TextView) v.findViewById(R.id.text); checkBox = (CheckBox) v.findViewById(R.id.selected); } diff --git a/samples/Support7Demos/src/com/example/android/supportv7/widget/BaseLayoutManagerActivity.java b/samples/Support7Demos/src/com/example/android/supportv7/widget/BaseLayoutManagerActivity.java index 782da523b..002a5745f 100644 --- a/samples/Support7Demos/src/com/example/android/supportv7/widget/BaseLayoutManagerActivity.java +++ b/samples/Support7Demos/src/com/example/android/supportv7/widget/BaseLayoutManagerActivity.java @@ -25,6 +25,7 @@ import com.example.android.supportv7.widget.util.ConfigViewHolder; import android.app.Activity; import android.content.Context; import android.os.Bundle; +import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; @@ -69,7 +70,7 @@ abstract public class BaseLayoutManagerActivity<T extends RecyclerView.LayoutMan mLayoutManager = createLayoutManager(); mRecyclerView.setLayoutManager(mLayoutManager); mRecyclerView.setAdapter(createAdapter()); - mRecyclerView.getItemAnimator().setSupportsChangeAnimations(true); + ((DefaultItemAnimator)mRecyclerView.getItemAnimator()).setSupportsChangeAnimations(true); onRecyclerViewInit(mRecyclerView); } diff --git a/samples/Support7Demos/src/com/example/android/supportv7/widget/DrawerLayoutActivity.java b/samples/Support7Demos/src/com/example/android/supportv7/widget/DrawerLayoutActivity.java new file mode 100644 index 000000000..8cdf927c2 --- /dev/null +++ b/samples/Support7Demos/src/com/example/android/supportv7/widget/DrawerLayoutActivity.java @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.supportv7.widget; + +import android.content.res.Configuration; +import android.os.Bundle; +import android.support.v4.view.GravityCompat; +import android.support.v4.widget.DrawerLayout; +import android.support.v7.app.ActionBarDrawerToggle; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.view.MenuItem; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ListView; +import android.widget.TextView; +import com.example.android.supportv7.R; +import com.example.android.supportv7.Shakespeare; + +/** + * This example illustrates a common usage of the DrawerLayout widget combined with Toolbar + * in the Android support library that respect the + * <a href="https://www.google.com/design/spec/patterns/navigation-drawer.html">Material design + * guidelines</a> for the drawer component. + * + * + * <p>A DrawerLayout should be positioned at the top of your view hierarchy, placing it + * below the action bar but above your content views. The primary content should match_parent + * in both dimensions. Each drawer should define a reasonable width and match_parent for height. + * Drawer views should be positioned after the content view in your layout to preserve proper + * ordering.</p> + * + * <p>When a navigation (left) drawer is present, the host activity should detect presses of + * the action bar's Up affordance as a signal to open and close the navigation drawer. + * Items within the drawer should fall into one of two categories.</p> + * + * <ul> + * <li><strong>View switches</strong>. A view switch follows the same basic policies as + * list or tab navigation in that a view switch does not create navigation history. + * This pattern should only be used at the root activity of a task, leaving some form + * of Up navigation active for activities further down the navigation hierarchy.</li> + * <li><strong>Selective Up</strong>. The drawer allows the user to choose an alternate + * parent for Up navigation. This allows a user to jump across an app's navigation + * hierarchy at will. The application should treat this as it treats Up navigation from + * a different task, replacing the current task stack using TaskStackBuilder or similar. + * This is the only form of navigation drawer that should be used outside of the root + * activity of a task.</li> + * </ul> + * + * <p>Right side drawers should be used for actions, not navigation. This follows the pattern + * established by the Action Bar that navigation should be to the left and actions to the right. + * An action should be an operation performed on the current contents of the window, + * for example enabling or disabling a data overlay on top of the current content.</p> + * + * <p>When the drawer is open, it is above the application toolbar. On Lollipop versions of the + * platform and above the drawer spans the full height of the screen, including behind the system + * status bar.</p> + */ +public class DrawerLayoutActivity extends AppCompatActivity { + private DrawerLayout mDrawerLayout; + private ListView mDrawer; + private TextView mContent; + + private ActionBarDrawerToggle mDrawerToggle; + private Toolbar mToolbar; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.drawer_layout); + + mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); + mDrawer = (ListView) findViewById(R.id.start_drawer); + mContent = (TextView) findViewById(R.id.content_text); + + mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START); + + // The drawer title must be set in order to announce state changes when + // accessibility is turned on. This is typically a simple description, + // e.g. "Navigation". + mDrawerLayout.setDrawerTitle(GravityCompat.START, getString(R.string.drawer_title)); + + mDrawer.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, + Shakespeare.TITLES)); + mDrawer.setOnItemClickListener(new DrawerItemClickListener()); + + // Find the toolbar in our layout and set it as the support action bar on the activity. + // This is required to have the drawer slide "over" the toolbar. + mToolbar = (Toolbar) findViewById(R.id.toolbar); + mToolbar.setTitle(R.string.drawer_title); + setSupportActionBar(mToolbar); + + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + getSupportActionBar().setDisplayShowHomeEnabled(false); + + // ActionBarDrawerToggle provides convenient helpers for tying together the + // prescribed interactions between a top-level sliding drawer and the action bar. + // Note that, as the Javadocs of ActionBarDrawerToggle constructors say, we are + // *not* using a constructor that gets a Toolbar since we're setting our toolbar + // dynamically at runtime. Furthermore, as the drawer is sliding over the toolbar, + // we are suppressing the morphing animation from hamburger to back arrow by + // calling super.onDrawerSlide with slideOffset=0.0f. In case your app only has + // top-level pages and doesn't need back arrow visuals at all, you can set up + // your activity theme to have attribute named "drawerArrowStyle" that points + // to an extension of Widget.AppCompat.DrawerArrowToggle that has its "spinBars" + // attribute set to false. + mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, + R.string.drawer_open, R.string.drawer_close) { + @Override + public void onDrawerOpened(View drawerView) { + super.onDrawerOpened(drawerView); + super.onDrawerSlide(drawerView, 0.0f); + } + + @Override + public void onDrawerSlide(View drawerView, float slideOffset) { + super.onDrawerSlide(drawerView, 0.0f); + } + }; + + mDrawerLayout.setDrawerListener(mDrawerToggle); + + // Configure the background color fill of the system status bar (on supported platform + // versions) and the toolbar itself. We're using the same color, and android:statusBar + // from the theme makes the status bar slightly darker. + final int metalBlueColor = getResources().getColor(R.color.drawer_sample_metal_blue); + mDrawerLayout.setStatusBarBackgroundColor(metalBlueColor); + mToolbar.setBackgroundColor(metalBlueColor); + } + + @Override + protected void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + + // Sync the toggle state after onRestoreInstanceState has occurred. + mDrawerToggle.syncState(); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + /* + * The action bar home/up action should open or close the drawer. + * The drawer toggle will take care of this. + */ + if (mDrawerToggle.onOptionsItemSelected(item)) { + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void onBackPressed() { + // Is the drawer open? + if (mDrawerLayout.isDrawerOpen(mDrawer)) { + // Close the drawer and return. + mDrawerLayout.closeDrawer(mDrawer); + return; + } + + super.onBackPressed(); + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + mDrawerToggle.onConfigurationChanged(newConfig); + } + + /** + * This list item click listener implements very simple view switching by changing + * the primary content text. The drawer is closed when a selection is made. + */ + private class DrawerItemClickListener implements ListView.OnItemClickListener { + @Override + public void onItemClick(AdapterView<?> parent, View view, int position, long id) { + mContent.setText(Shakespeare.DIALOGUE[position]); + mToolbar.setTitle(Shakespeare.TITLES[position]); + mDrawerLayout.closeDrawer(mDrawer); + } + } +} |