Resize View Behind Android SlidingDrawer

By | April 14, 2014

I’ll describe my solution on how to resize a view under a SlidingDrawer. When the drawer is collapsed, the view (a map in my app) scales to take the additional place.

I ended up having two layers (two LinearLayouts in a FrameView), each containing its actual contents and a dummy padding view.


<FrameLayout
android:id="@+id/det_frame"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" >

  <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <fragment
      android:id="@+id/det_map"
      android:layout_width="match_parent"
      android:layout_height="0dip"
      android:layout_weight="1" />

    <View
      android:id="@+id/det_map_padding"
      android:layout_width="match_parent"
      android:layout_height="0dp" />
  </LinearLayout>

  <LinearLayout
    android:id="@+id/det_drawer_layer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <View
      android:id="@+id/det_drawer_padding"
      android:layout_width="match_parent"
      android:layout_height="0dp"
      android:layout_weight="1" />

    <SlidingDrawer
      android:id="@+id/drawer"
      android:layout_width="fill_parent"
      android:layout_height="0dp"
      android:layout_weight="1"
      android:allowSingleTap="true"
      android:content="@+id/details_tab_content"
      android:handle="@+id/drawer_handle" >

      <ImageView
        android:id="@+id/drawer_handle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/handle_top" />

      <LinearLayout
        android:id="@+id/details_tab_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:orientation="vertical" >

        <!-- drawer contents-->
      </LinearLayout>
    </SlidingDrawer>
  </LinearLayout>
</FrameLayout>

During runtime, two important things are done. First, the map padding size is adjusted so that it matches the drawer size in the other layer. Then, the padding visibility is changed when the drawer is expanded or collapsed. It would be best to animate the content resizing in sync with the drawer – I will look into it.

import android.app.Fragment;
import android.os.Bundle;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnLayoutChangeListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
import android.widget.SlidingDrawer;
import android.widget.SlidingDrawer.OnDrawerCloseListener;
import android.widget.SlidingDrawer.OnDrawerOpenListener;

@SuppressWarnings("deprecation")
public class MyFragment extends Fragment {
  private int mDrawerOrientation;
  private View mTabContentView;
  private View mMapPaddingView;

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    final View v = inflater.inflate(R.layout.my_layout, container, false);

    LinearLayout layout = (LinearLayout) (v.findViewById(R.id.det_drawer_layer));
    mDrawerOrientation = layout.getOrientation();
    mTabContentView = v.findViewById(R.id.details_tab_content);
    mMapPaddingView = v.findViewById(R.id.det_map_padding);
    final SlidingDrawer slidingDrawer = (SlidingDrawer) v.findViewById(R.id.drawer);

    slidingDrawer.setOnDrawerOpenListener(new OnDrawerOpenListener() {
      @Override
      public void onDrawerOpened() {
        v.findViewById(R.id.det_map_padding).setVisibility(View.VISIBLE);
      }
    });

    slidingDrawer.setOnDrawerCloseListener(new OnDrawerCloseListener() {
      @Override
      public void onDrawerClosed() {
        v.findViewById(R.id.det_map_padding).setVisibility(View.GONE);
      }
    });

    // TODO: this smells. Should open the drawer when the view is laid out
    new Handler().postDelayed(new Runnable() {
      @Override
      public void run() {
        slidingDrawer.open();
      }
    }, 100);

    mTabContentView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
      @Override
      public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
        LayoutParams layoutParams = mMapPaddingView.getLayoutParams();
        if (mDrawerOrientation == LinearLayout.HORIZONTAL) {
          int width = right - left;
          if (width > 0 && layoutParams.width != width) {
            layoutParams.width = width;
            mMapPaddingView.setLayoutParams(layoutParams);
          }
        }
        else {
          int height = bottom - top;
          if (height > 0 && layoutParams.height != height) {
            layoutParams.height = height;
            mMapPaddingView.setLayoutParams(layoutParams);
          }
        }
      }
    });
    return v;
  }
}

Leave a Reply

Your email address will not be published.