Home | History | Annotate | Download | only in widget
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 
     18 package com.example.android.supportv4.widget;
     19 
     20 import android.app.ActionBar;
     21 import android.app.Activity;
     22 import android.os.Build;
     23 import android.os.Bundle;
     24 import android.support.v4.widget.SlidingPaneLayout;
     25 import android.view.MenuItem;
     26 import android.view.View;
     27 import android.view.ViewTreeObserver;
     28 import android.widget.AdapterView;
     29 import android.widget.ArrayAdapter;
     30 import android.widget.ListView;
     31 import android.widget.TextView;
     32 import com.example.android.supportv4.Shakespeare;
     33 import com.example.android.supportv4.R;
     34 
     35 /**
     36  * This example illustrates a common usage of SlidingPaneLayout in the Android support library.
     37  *
     38  * <p>A SlidingPaneLayout should be positioned at the top of your view hierarchy, placing it
     39  * below the action bar but above your content views. It is ideal as a two-pane layout
     40  * for larger screens, used in place of a horizontal LinearLayout.</p>
     41  *
     42  * <p>What separates SlidingPaneLayout from LinearLayout in this usage is that SlidingPaneLayout
     43  * allows these wide, two-pane layouts to overlap when horizontal space is at a premium. The user
     44  * can then access both panes by physically sliding the content pane into view or out of the way
     45  * or implicitly by moving focus between the two panes. This can greatly simplify development
     46  * of Android apps that support multiple form factors and screen sizes.</p>
     47  *
     48  * <p>When it comes to your navigation hierarchy, the left pane of a SlidingPaneLayout is always
     49  * considered to be one level up from the right content pane. As such, your Action Bar's
     50  * Up navigation should be enabled if the right pane is obscuring the left pane, and invoking it
     51  * should open the panes, revealing the left pane for normal interaction. From this open state
     52  * where the left pane is in primary focus, the Action Bar's Up affordance should act as if
     53  * both panes were fully visible in the activity window and navigate to the activity one level up
     54  * in the app's logical hierarchy. If the activity is the root of the application's task, the up
     55  * affordance should be disabled when the sliding pane is open and showing the left pane.
     56  * This code example illustrates this root activity case.</p>
     57  *
     58  * <p>Note that SlidingPaneLayout differs in usage from DrawerLayout. While DrawerLayout offers
     59  * sliding utility drawers for extended navigation options and actions, the panes of a
     60  * SlidingPaneLayout are firmly part of the content itself. If it would not make sense for
     61  * both panes to be visible all the time on a sufficiently wide screen, DrawerLayout and its
     62  * associated patterns are likely to be a better choice for your usage.</p>
     63  */
     64 public class SlidingPaneLayoutActivity extends Activity {
     65     private SlidingPaneLayout mSlidingLayout;
     66     private ListView mList;
     67     private TextView mContent;
     68 
     69     private ActionBarHelper mActionBar;
     70 
     71     @Override
     72     protected void onCreate(Bundle savedInstanceState) {
     73         super.onCreate(savedInstanceState);
     74 
     75         setContentView(R.layout.sliding_pane_layout);
     76 
     77         mSlidingLayout = (SlidingPaneLayout) findViewById(R.id.sliding_pane_layout);
     78         mList = (ListView) findViewById(R.id.left_pane);
     79         mContent = (TextView) findViewById(R.id.content_text);
     80 
     81         mSlidingLayout.setPanelSlideListener(new SliderListener());
     82         mSlidingLayout.openPane();
     83 
     84         mList.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,
     85                 Shakespeare.TITLES));
     86         mList.setOnItemClickListener(new ListItemClickListener());
     87 
     88         mActionBar = createActionBarHelper();
     89         mActionBar.init();
     90 
     91         mSlidingLayout.getViewTreeObserver().addOnGlobalLayoutListener(new FirstLayoutListener());
     92     }
     93 
     94     @Override
     95     public boolean onOptionsItemSelected(MenuItem item) {
     96         /*
     97          * The action bar up action should open the slider if it is currently closed,
     98          * as the left pane contains content one level up in the navigation hierarchy.
     99          */
    100         if (item.getItemId() == android.R.id.home && !mSlidingLayout.isOpen()) {
    101             mSlidingLayout.smoothSlideOpen();
    102             return true;
    103         }
    104         return super.onOptionsItemSelected(item);
    105     }
    106 
    107     /**
    108      * This list item click listener implements very simple view switching by changing
    109      * the primary content text. The slider is closed when a selection is made to fully
    110      * reveal the content.
    111      */
    112     private class ListItemClickListener implements ListView.OnItemClickListener {
    113         @Override
    114         public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    115             mContent.setText(Shakespeare.DIALOGUE[position]);
    116             mActionBar.setTitle(Shakespeare.TITLES[position]);
    117             mSlidingLayout.smoothSlideClosed();
    118         }
    119     }
    120 
    121     /**
    122      * This panel slide listener updates the action bar accordingly for each panel state.
    123      */
    124     private class SliderListener extends SlidingPaneLayout.SimplePanelSlideListener {
    125         @Override
    126         public void onPanelOpened(View panel) {
    127             mActionBar.onPanelOpened();
    128         }
    129 
    130         @Override
    131         public void onPanelClosed(View panel) {
    132             mActionBar.onPanelClosed();
    133         }
    134     }
    135 
    136     /**
    137      * This global layout listener is used to fire an event after first layout occurs
    138      * and then it is removed. This gives us a chance to configure parts of the UI
    139      * that adapt based on available space after they have had the opportunity to measure
    140      * and layout.
    141      */
    142     private class FirstLayoutListener implements ViewTreeObserver.OnGlobalLayoutListener {
    143         @Override
    144         public void onGlobalLayout() {
    145             mActionBar.onFirstLayout();
    146             mSlidingLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
    147         }
    148     }
    149 
    150     /**
    151      * Create a compatible helper that will manipulate the action bar if available.
    152      */
    153     private ActionBarHelper createActionBarHelper() {
    154         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
    155             return new ActionBarHelperICS();
    156         } else {
    157             return new ActionBarHelper();
    158         }
    159     }
    160 
    161     /**
    162      * Stub action bar helper; this does nothing.
    163      */
    164     private class ActionBarHelper {
    165         public void init() {}
    166         public void onPanelClosed() {}
    167         public void onPanelOpened() {}
    168         public void onFirstLayout() {}
    169         public void setTitle(CharSequence title) {}
    170     }
    171 
    172     /**
    173      * Action bar helper for use on ICS and newer devices.
    174      */
    175     private class ActionBarHelperICS extends ActionBarHelper {
    176         private final ActionBar mActionBar;
    177         private CharSequence mDrawerTitle;
    178         private CharSequence mTitle;
    179 
    180         ActionBarHelperICS() {
    181             mActionBar = getActionBar();
    182         }
    183 
    184         @Override
    185         public void init() {
    186             mActionBar.setDisplayHomeAsUpEnabled(true);
    187             mActionBar.setHomeButtonEnabled(true);
    188             mTitle = mDrawerTitle = getTitle();
    189         }
    190 
    191         @Override
    192         public void onPanelClosed() {
    193             super.onPanelClosed();
    194             mActionBar.setDisplayHomeAsUpEnabled(true);
    195             mActionBar.setHomeButtonEnabled(true);
    196             mActionBar.setTitle(mTitle);
    197         }
    198 
    199         @Override
    200         public void onPanelOpened() {
    201             super.onPanelOpened();
    202             mActionBar.setHomeButtonEnabled(false);
    203             mActionBar.setDisplayHomeAsUpEnabled(false);
    204             mActionBar.setTitle(mDrawerTitle);
    205         }
    206 
    207         @Override
    208         public void onFirstLayout() {
    209             if (mSlidingLayout.canSlide() && !mSlidingLayout.isOpen()) {
    210                 onPanelClosed();
    211             } else {
    212                 onPanelOpened();
    213             }
    214         }
    215 
    216         @Override
    217         public void setTitle(CharSequence title) {
    218             mTitle = title;
    219         }
    220     }
    221 
    222 }
    223