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 18package com.example.android.supportv4.widget; 19 20import android.app.ActionBar; 21import android.app.Activity; 22import android.os.Build; 23import android.os.Bundle; 24import android.view.MenuItem; 25import android.view.View; 26import android.view.ViewTreeObserver; 27import android.widget.AdapterView; 28import android.widget.ArrayAdapter; 29import android.widget.ListView; 30import android.widget.TextView; 31 32import androidx.slidingpanelayout.widget.SlidingPaneLayout; 33 34import com.example.android.supportv4.R; 35import 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 */ 66public 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