blob: c2fc76a5166cc7679c3b64ffe1aef59816b43bba [file] [log] [blame]
Ben Linb8c54e72016-06-10 12:13:27 -07001/*
2 * Copyright (C) 2016 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
17package com.android.documentsui;
18
Felipe Leme9de58072018-01-19 16:40:04 -080019import static com.android.documentsui.base.SharedMinimal.VERBOSE;
Ben Linb8c54e72016-06-10 12:13:27 -070020
Tony Huang7cbde882018-11-23 12:14:34 +080021import android.app.Activity;
22import android.content.res.Resources;
23import android.graphics.Outline;
Ben Linb8c54e72016-06-10 12:13:27 -070024import android.graphics.drawable.Drawable;
25import android.util.Log;
26import android.view.View;
Tony Huang7cbde882018-11-23 12:14:34 +080027import android.view.ViewOutlineProvider;
Ben Linb8c54e72016-06-10 12:13:27 -070028
Tony Huangebdfe222019-03-04 16:58:07 +080029import androidx.annotation.Nullable;
30import androidx.appcompat.widget.Toolbar;
31
Tony Huang7cbde882018-11-23 12:14:34 +080032import com.android.documentsui.R;
Steve McKayd0805062016-09-15 14:30:38 -070033import com.android.documentsui.base.RootInfo;
Steve McKayd9caa6a2016-09-15 16:36:45 -070034import com.android.documentsui.base.State;
Ben Linb8c54e72016-06-10 12:13:27 -070035import com.android.documentsui.dirlist.AnimationView;
Ben Linb8c54e72016-06-10 12:13:27 -070036
Tony Huang7cbde882018-11-23 12:14:34 +080037import com.google.android.material.appbar.AppBarLayout;
38import com.google.android.material.appbar.CollapsingToolbarLayout;
39
Ben Line4ffd062017-01-19 15:10:49 -080040import java.util.function.IntConsumer;
Ben Linb8c54e72016-06-10 12:13:27 -070041
42/**
43 * A facade over the portions of the app and drawer toolbars.
44 */
45public class NavigationViewManager {
46
47 private static final String TAG = "NavigationViewManager";
48
Garfield Tand2fc4cd2017-03-15 15:39:14 -070049 private final DrawerController mDrawer;
50 private final Toolbar mToolbar;
51 private final State mState;
52 private final NavigationViewManager.Environment mEnv;
53 private final Breadcrumb mBreadcrumb;
Tony Huang7cbde882018-11-23 12:14:34 +080054 private final View mSearchBarView;
55 private final CollapsingToolbarLayout mCollapsingBarLayout;
56 private final Drawable mDefaultActionBarBackground;
57 private final ViewOutlineProvider mSearchBarOutlineProvider;
Tony Huangebdfe222019-03-04 16:58:07 +080058 private final boolean mShowSearchBar;
Ben Linb8c54e72016-06-10 12:13:27 -070059
60 public NavigationViewManager(
Tony Huang7cbde882018-11-23 12:14:34 +080061 Activity activity,
Ben Linb8c54e72016-06-10 12:13:27 -070062 DrawerController drawer,
Ben Linb8c54e72016-06-10 12:13:27 -070063 State state,
64 NavigationViewManager.Environment env,
65 Breadcrumb breadcrumb) {
66
Tony Huang7cbde882018-11-23 12:14:34 +080067 mToolbar = activity.findViewById(R.id.toolbar);
Ben Linb8c54e72016-06-10 12:13:27 -070068 mDrawer = drawer;
69 mState = state;
70 mEnv = env;
71 mBreadcrumb = breadcrumb;
72 mBreadcrumb.setup(env, state, this::onNavigationItemSelected);
73
74 mToolbar.setNavigationOnClickListener(
75 new View.OnClickListener() {
76 @Override
77 public void onClick(View v) {
78 onNavigationIconClicked();
79 }
80 });
Tony Huang7cbde882018-11-23 12:14:34 +080081 mSearchBarView = activity.findViewById(R.id.searchbar_title);
82 mCollapsingBarLayout = activity.findViewById(R.id.collapsing_toolbar);
83 mDefaultActionBarBackground = mToolbar.getBackground();
Tony Huangebdfe222019-03-04 16:58:07 +080084 mShowSearchBar = activity.getResources().getBoolean(R.bool.show_search_bar);
Tony Huang7cbde882018-11-23 12:14:34 +080085
86 final Resources resources = mToolbar.getResources();
87 final int radius = resources.getDimensionPixelSize(R.dimen.search_bar_radius);
88 final int marginStart =
89 resources.getDimensionPixelSize(R.dimen.search_bar_background_margin_start);
90 final int marginEnd =
91 resources.getDimensionPixelSize(R.dimen.search_bar_background_margin_end);
92 mSearchBarOutlineProvider = new ViewOutlineProvider() {
93 @Override
94 public void getOutline(View view, Outline outline) {
95 outline.setRoundRect(marginStart, 0,
96 view.getWidth() - marginEnd, view.getHeight(), radius);
97 }
98 };
99 }
100
101 public void setSearchBarClickListener(View.OnClickListener listener) {
102 mSearchBarView.setOnClickListener(listener);
Ben Linb8c54e72016-06-10 12:13:27 -0700103 }
104
105 private void onNavigationIconClicked() {
106 if (mDrawer.isPresent()) {
Garfield Tan3f54c9c2017-03-31 14:52:36 -0700107 mDrawer.setOpen(true);
Ben Linb8c54e72016-06-10 12:13:27 -0700108 }
109 }
110
111 void onNavigationItemSelected(int position) {
112 boolean changed = false;
113 while (mState.stack.size() > position + 1) {
114 changed = true;
Garfield Tan2a837422016-10-19 11:50:45 -0700115 mState.stack.pop();
Ben Linb8c54e72016-06-10 12:13:27 -0700116 }
117 if (changed) {
118 mEnv.refreshCurrentRootAndDirectory(AnimationView.ANIM_LEAVE);
119 }
120 }
121
Steve McKay16e0c1f2016-09-15 12:41:13 -0700122 public void update() {
Tony Huang7cbde882018-11-23 12:14:34 +0800123 updateScrollFlag();
124 updateToolbar();
Ben Linb8c54e72016-06-10 12:13:27 -0700125
126 // TODO: Looks to me like this block is never getting hit.
127 if (mEnv.isSearchExpanded()) {
128 mToolbar.setTitle(null);
129 mBreadcrumb.show(false);
130 return;
131 }
132
133 mDrawer.setTitle(mEnv.getDrawerTitle());
134
135 mToolbar.setNavigationIcon(getActionBarIcon());
136 mToolbar.setNavigationContentDescription(R.string.drawer_open);
137
Tony Huangebdfe222019-03-04 16:58:07 +0800138 if (shouldShowSearchBar()) {
Ben Linb8c54e72016-06-10 12:13:27 -0700139 mBreadcrumb.show(false);
Tony Huang7cbde882018-11-23 12:14:34 +0800140 mToolbar.setTitle(null);
141 mSearchBarView.setVisibility(View.VISIBLE);
142 } else if (mState.stack.size() <= 1) {
143 mBreadcrumb.show(false);
144 mSearchBarView.setVisibility(View.GONE);
Ben Linb8c54e72016-06-10 12:13:27 -0700145 String title = mEnv.getCurrentRoot().title;
Steve McKay30535bc2016-11-04 14:16:58 -0700146 if (VERBOSE) Log.v(TAG, "New toolbar title is: " + title);
Ben Linb8c54e72016-06-10 12:13:27 -0700147 mToolbar.setTitle(title);
148 } else {
149 mBreadcrumb.show(true);
150 mToolbar.setTitle(null);
Tony Huang7cbde882018-11-23 12:14:34 +0800151 mSearchBarView.setVisibility(View.GONE);
Ben Linb8c54e72016-06-10 12:13:27 -0700152 mBreadcrumb.postUpdate();
153 }
Tony Huang7cbde882018-11-23 12:14:34 +0800154 }
Ben Linb8c54e72016-06-10 12:13:27 -0700155
Tony Huang7cbde882018-11-23 12:14:34 +0800156 private void updateScrollFlag() {
157 if (mCollapsingBarLayout == null) {
158 return;
159 }
160
161 AppBarLayout.LayoutParams lp =
162 (AppBarLayout.LayoutParams) mCollapsingBarLayout.getLayoutParams();
163 if (shouldShowSearchBar()) {
164 lp.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL
165 | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS
166 | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED);
167 } else {
168 lp.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL
169 | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED);
170 }
171 mCollapsingBarLayout.setLayoutParams(lp);
172 }
173
174 private void updateToolbar() {
175 if (shouldShowSearchBar()) {
176 mToolbar.setBackgroundResource(R.drawable.search_bar_background);
177 mToolbar.setOutlineProvider(mSearchBarOutlineProvider);
178 } else {
179 mToolbar.setBackground(mDefaultActionBarBackground);
180 mToolbar.setOutlineProvider(null);
181 }
182
183 if (mCollapsingBarLayout != null) {
184 View overlayBackground =
185 mCollapsingBarLayout.findViewById(R.id.toolbar_background_layout);
186 overlayBackground.setVisibility(shouldShowSearchBar() ? View.GONE : View.VISIBLE);
187 }
188 }
189
190 private boolean shouldShowSearchBar() {
Tony Huangebdfe222019-03-04 16:58:07 +0800191 return mState.stack.isRecents() && !mEnv.isSearchExpanded() && mShowSearchBar;
Ben Linb8c54e72016-06-10 12:13:27 -0700192 }
193
194 // Hamburger if drawer is present, else sad nullness.
195 private @Nullable Drawable getActionBarIcon() {
196 if (mDrawer.isPresent()) {
197 return mToolbar.getContext().getDrawable(R.drawable.ic_hamburger);
198 } else {
199 return null;
200 }
201 }
202
203 void revealRootsDrawer(boolean open) {
204 mDrawer.setOpen(open);
205 }
206
207 interface Breadcrumb {
Ben Line4ffd062017-01-19 15:10:49 -0800208 void setup(Environment env, State state, IntConsumer listener);
Ben Linb8c54e72016-06-10 12:13:27 -0700209 void show(boolean visibility);
210 void postUpdate();
211 }
212
213 interface Environment {
Steve McKayeed2f4e2016-10-03 20:30:52 -0700214 @Deprecated // Use CommonAddones#getCurrentRoot
Ben Linb8c54e72016-06-10 12:13:27 -0700215 RootInfo getCurrentRoot();
216 String getDrawerTitle();
Steve McKay988d8a32016-09-27 09:41:17 -0700217 @Deprecated // Use CommonAddones#refreshCurrentRootAndDirectory
Ben Linb8c54e72016-06-10 12:13:27 -0700218 void refreshCurrentRootAndDirectory(int animation);
219 boolean isSearchExpanded();
220 }
221}