summaryrefslogtreecommitdiffstats
path: root/samples/Support7Demos/src/com/example/android
diff options
context:
space:
mode:
Diffstat (limited to 'samples/Support7Demos/src/com/example/android')
-rw-r--r--samples/Support7Demos/src/com/example/android/supportv7/app/ActionBarWithDrawerLayout.java191
-rw-r--r--samples/Support7Demos/src/com/example/android/supportv7/media/LocalPlayer.java75
-rw-r--r--samples/Support7Demos/src/com/example/android/supportv7/media/MyMediaRouteControllerDialog.java44
-rw-r--r--samples/Support7Demos/src/com/example/android/supportv7/media/OverlayDisplayWindow.java7
-rw-r--r--samples/Support7Demos/src/com/example/android/supportv7/media/Player.java33
-rw-r--r--samples/Support7Demos/src/com/example/android/supportv7/media/RemotePlayer.java5
-rw-r--r--samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaButtonReceiver.java3
-rw-r--r--samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaRouteProvider.java34
-rw-r--r--samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaRouterActivity.java18
-rw-r--r--samples/Support7Demos/src/com/example/android/supportv7/media/SessionManager.java2
-rw-r--r--samples/Support7Demos/src/com/example/android/supportv7/widget/AnimatedRecyclerView.java286
-rw-r--r--samples/Support7Demos/src/com/example/android/supportv7/widget/BaseLayoutManagerActivity.java3
-rw-r--r--samples/Support7Demos/src/com/example/android/supportv7/widget/DrawerLayoutActivity.java197
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);
+ }
+ }
+}