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