1 /*
2  * Copyright (C) 2021 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 package com.android.settingslib.collapsingtoolbar;
18 
19 import android.app.ActionBar;
20 import android.content.pm.PackageManager;
21 import android.os.Bundle;
22 import android.view.LayoutInflater;
23 import android.view.View;
24 import android.view.ViewGroup;
25 import android.widget.Toolbar;
26 
27 import androidx.annotation.Nullable;
28 import androidx.fragment.app.FragmentActivity;
29 
30 import com.android.settingslib.utils.BuildCompatUtils;
31 import com.android.settingslib.widget.R;
32 
33 import com.google.android.material.appbar.AppBarLayout;
34 import com.google.android.material.appbar.CollapsingToolbarLayout;
35 
36 /**
37  * A base Activity that has a collapsing toolbar layout is used for the activities intending to
38  * enable the collapsing toolbar function.
39  */
40 public class CollapsingToolbarBaseActivity extends FragmentActivity {
41 
42     private class DelegateCallback implements CollapsingToolbarDelegate.HostCallback {
43         @Nullable
44         @Override
setActionBar(Toolbar toolbar)45         public ActionBar setActionBar(Toolbar toolbar) {
46             CollapsingToolbarBaseActivity.super.setActionBar(toolbar);
47             return CollapsingToolbarBaseActivity.super.getActionBar();
48         }
49 
50         @Override
setOuterTitle(CharSequence title)51         public void setOuterTitle(CharSequence title) {
52             CollapsingToolbarBaseActivity.super.setTitle(title);
53         }
54     }
55 
56     private CollapsingToolbarDelegate mToolbardelegate;
57 
58     private int mCustomizeLayoutResId = 0;
59 
60     @Override
onCreate(@ullable Bundle savedInstanceState)61     protected void onCreate(@Nullable Bundle savedInstanceState) {
62         super.onCreate(savedInstanceState);
63         // for backward compatibility on R devices or wearable devices due to small device size.
64         if (mCustomizeLayoutResId > 0 && (!BuildCompatUtils.isAtLeastS() || isWatch())) {
65             super.setContentView(mCustomizeLayoutResId);
66             return;
67         }
68 
69         View view = getToolbarDelegate().onCreateView(getLayoutInflater(), null);
70         super.setContentView(view);
71     }
72 
73     @Override
setContentView(int layoutResID)74     public void setContentView(int layoutResID) {
75         final ViewGroup parent = (mToolbardelegate == null) ? findViewById(R.id.content_frame)
76                 : mToolbardelegate.getContentFrameLayout();
77         if (parent != null) {
78             parent.removeAllViews();
79         }
80         LayoutInflater.from(this).inflate(layoutResID, parent);
81     }
82 
83     @Override
setContentView(View view)84     public void setContentView(View view) {
85         final ViewGroup parent = (mToolbardelegate == null) ? findViewById(R.id.content_frame)
86                 : mToolbardelegate.getContentFrameLayout();
87         if (parent != null) {
88             parent.addView(view);
89         }
90     }
91 
92     @Override
setContentView(View view, ViewGroup.LayoutParams params)93     public void setContentView(View view, ViewGroup.LayoutParams params) {
94         final ViewGroup parent = (mToolbardelegate == null) ? findViewById(R.id.content_frame)
95                 : mToolbardelegate.getContentFrameLayout();
96         if (parent != null) {
97             parent.addView(view, params);
98         }
99     }
100 
101     /**
102      * This method allows an activity to replace the default layout with a customize layout. Notice
103      * that it will no longer apply the features being provided by this class when this method
104      * gets called.
105      */
setCustomizeContentView(int layoutResId)106     protected void setCustomizeContentView(int layoutResId) {
107         mCustomizeLayoutResId = layoutResId;
108     }
109 
110     @Override
setTitle(CharSequence title)111     public void setTitle(CharSequence title) {
112         getToolbarDelegate().setTitle(title);
113     }
114 
115     @Override
setTitle(int titleId)116     public void setTitle(int titleId) {
117         setTitle(getText(titleId));
118     }
119 
120     @Override
onNavigateUp()121     public boolean onNavigateUp() {
122         if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
123             getSupportFragmentManager().popBackStackImmediate();
124         }
125 
126         // Closes the activity if there is no fragment inside the stack. Otherwise the activity will
127         // has a blank screen since there is no any fragment.
128         if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
129             finishAfterTransition();
130         }
131         return true;
132     }
133 
134     @Override
onBackPressed()135     public void onBackPressed() {
136         super.onBackPressed();
137 
138         // Closes the activity if there is no fragment inside the stack. Otherwise the activity will
139         // has a blank screen since there is no any fragment. onBackPressed() in Activity.java only
140         // handles popBackStackImmediate(). This will close activity to avoid a blank screen.
141         if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
142             finishAfterTransition();
143         }
144     }
145 
146     /**
147      * Returns an instance of collapsing toolbar.
148      */
149     @Nullable
getCollapsingToolbarLayout()150     public CollapsingToolbarLayout getCollapsingToolbarLayout() {
151         return getToolbarDelegate().getCollapsingToolbarLayout();
152     }
153 
154     /**
155      * Return an instance of app bar.
156      */
157     @Nullable
getAppBarLayout()158     public AppBarLayout getAppBarLayout() {
159         return getToolbarDelegate().getAppBarLayout();
160     }
161 
isWatch()162     private boolean isWatch() {
163         PackageManager packageManager = getPackageManager();
164         if (packageManager == null) {
165             return false;
166         }
167         return packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH);
168     }
169 
getToolbarDelegate()170     private CollapsingToolbarDelegate getToolbarDelegate() {
171         if (mToolbardelegate == null) {
172             mToolbardelegate = new CollapsingToolbarDelegate(new DelegateCallback());
173         }
174         return mToolbardelegate;
175     }
176 }
177