I just came across this app and saw this custom animation for a DrawerLayout
.
I\'m guessing it has to take a screenshot first, then draw a custom View
You can do this by translating and scaling the content View
in the onDrawerSlide()
method of a DrawerListener
on your DrawerLayout
. Since the content View
itself is resizing, and there's a separate TextView
that appears in the bottom right corner, we'll stick both of these in another holder ViewGroup
. If that label TextView
isn't needed, the holder ViewGroup
can be omitted, as well.
A basic DrawerLayout
setup for the example:
The example Activity
shows the standard View
initializations, and the DrawerListener
that is actually doing the work.
public class MainActivity extends AppCompatActivity {
private static final float END_SCALE = 0.7f;
private DrawerLayout drawerLayout;
private NavigationView navigationView;
private Toolbar toolbar;
private TextView labelView;
private View contentView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
navigationView = (NavigationView) findViewById(R.id.navigation_view);
toolbar = (Toolbar) findViewById(R.id.toolbar);
labelView = (TextView) findViewById(R.id.label);
contentView = findViewById(R.id.content);
toolbar.setNavigationIcon(new DrawerArrowDrawable(this));
toolbar.setNavigationOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (drawerLayout.isDrawerOpen(navigationView)) {
drawerLayout.closeDrawer(navigationView);
}
else {
drawerLayout.openDrawer(navigationView);
}
}
}
);
drawerLayout.setScrimColor(Color.TRANSPARENT);
drawerLayout.addDrawerListener(new DrawerLayout.SimpleDrawerListener() {
@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
labelView.setVisibility(slideOffset > 0 ? View.VISIBLE : View.GONE);
// Scale the View based on current slide offset
final float diffScaledOffset = slideOffset * (1 - END_SCALE);
final float offsetScale = 1 - diffScaledOffset;
contentView.setScaleX(offsetScale);
contentView.setScaleY(offsetScale);
// Translate the View, accounting for the scaled width
final float xOffset = drawerView.getWidth() * slideOffset;
final float xOffsetDiff = contentView.getWidth() * diffScaledOffset / 2;
final float xTranslation = xOffset - xOffsetDiff;
contentView.setTranslationX(xTranslation);
}
@Override
public void onDrawerClosed(View drawerView) {
labelView.setVisibility(View.GONE);
}
}
);
}
}
The example uses a SimpleDrawerListener
, but the onDrawerSlide()
method can be overridden similarly in an ActionBarDrawerToggle
, if using that. The super
method would need to be called, in that case, to preserve the hamburger-arrow animation.
Do note that DrawerLayout
retains the drawer state during Activity
recreation, so you might need to account for this when handing orientation changes, etc.