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.