Loading java/com/android/dialer/main/impl/MainActivity.java +3 −213 Original line number Diff line number Diff line Loading @@ -24,13 +24,8 @@ import android.provider.ContactsContract.QuickContact; import android.support.design.widget.FloatingActionButton; import android.support.v4.app.FragmentTransaction; import android.support.v7.app.AppCompatActivity; import android.text.TextUtils; import android.view.View; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.widget.ImageView; import com.android.dialer.calllog.ui.NewCallLogFragment; import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; import com.android.dialer.contactsfragment.ContactsFragment; import com.android.dialer.contactsfragment.ContactsFragment.Header; Loading @@ -41,13 +36,9 @@ import com.android.dialer.dialpadview.DialpadFragment.LastOutgoingCallCallback; import com.android.dialer.dialpadview.DialpadFragment.OnDialpadQueryChangedListener; import com.android.dialer.main.impl.BottomNavBar.OnBottomNavTabSelectedListener; import com.android.dialer.main.impl.toolbar.MainToolbar; import com.android.dialer.main.impl.toolbar.SearchBarListener; import com.android.dialer.searchfragment.list.NewSearchFragment; import com.android.dialer.searchfragment.list.NewSearchFragment.SearchFragmentListener; import com.android.dialer.speeddial.SpeedDialFragment; import com.android.dialer.util.ViewUtil; import com.android.dialer.voicemail.listui.NewVoicemailFragment; import com.google.common.base.Optional; /** This is the main activity for dialer. It hosts favorites, call log, search, dialpad, etc... */ public final class MainActivity extends AppCompatActivity Loading @@ -59,7 +50,7 @@ public final class MainActivity extends AppCompatActivity private static final String IS_FAB_HIDDEN_KEY = "is_fab_hidden"; private SearchController searchController; private MainSearchController searchController; private FloatingActionButton fab; /** Loading Loading @@ -92,7 +83,7 @@ public final class MainActivity extends AppCompatActivity // TODO(calderwoodra): Implement last tab navBar.selectTab(BottomNavBar.TabIndex.SPEED_DIAL); searchController = new SearchController(navBar, fab, toolbar); searchController = new MainSearchController(this, navBar, fab, toolbar); toolbar.setSearchBarListener(searchController); } Loading Loading @@ -129,7 +120,7 @@ public final class MainActivity extends AppCompatActivity @Override // DialpadListener public void onDialpadShown() { searchController.getDialpadFragment().slideUp(true); searchController.onDialpadShown(); } @Override // DialpadListener Loading Loading @@ -161,207 +152,6 @@ public final class MainActivity extends AppCompatActivity // TODO(calderwoodra): logging } /** * Search controller for handling all the logic related to entering and exiting the search UI. * * <p>Components modified are: * * <ul> * <li>Bottom Nav Bar, completely hidden when in search ui. * <li>FAB, visible in dialpad search when dialpad is hidden. Otherwise, FAB is hidden. * <li>Toolbar, expanded and visible when dialpad is hidden. Otherwise, hidden off screen. * <li>Dialpad, shown through fab clicks and hidden with Android back button. * </ul> * * @see #onBackPressed() */ private final class SearchController implements SearchBarListener { private static final String DIALPAD_FRAGMENT_TAG = "dialpad_fragment_tag"; private static final String SEARCH_FRAGMENT_TAG = "search_fragment_tag"; private final BottomNavBar bottomNav; private final FloatingActionButton fab; private final MainToolbar toolbar; private SearchController( BottomNavBar bottomNav, FloatingActionButton fab, MainToolbar toolbar) { this.bottomNav = bottomNav; this.fab = fab; this.toolbar = toolbar; } /** Shows the dialpad, hides the FAB and slides the toolbar off screen. */ public void showDialpad(boolean animate) { Assert.checkArgument(!isDialpadVisible()); fab.hide(); toolbar.slideUp(animate); toolbar.expand(animate, Optional.absent()); setTitle(R.string.dialpad_activity_title); android.app.FragmentTransaction transaction = getFragmentManager().beginTransaction(); // Show Search if (getSearchFragment() == null) { NewSearchFragment searchFragment = NewSearchFragment.newInstance(false); transaction.add(R.id.search_fragment_container, searchFragment, SEARCH_FRAGMENT_TAG); } else if (!isSearchVisible()) { transaction.show(getSearchFragment()); } // Show Dialpad if (getDialpadFragment() == null) { DialpadFragment dialpadFragment = new DialpadFragment(); transaction.add(R.id.dialpad_fragment_container, dialpadFragment, DIALPAD_FRAGMENT_TAG); } else { DialpadFragment dialpadFragment = getDialpadFragment(); transaction.show(dialpadFragment); } transaction.commit(); } /** Hides the dialpad, reveals the FAB and slides the toolbar back onto the screen. */ public void hideDialpad(boolean animate, boolean bottomNavVisible) { Assert.checkArgument(isDialpadVisible()); fab.show(); toolbar.slideDown(animate); setTitle(R.string.main_activity_label); DialpadFragment dialpadFragment = getDialpadFragment(); dialpadFragment.setAnimate(animate); dialpadFragment.slideDown( animate, new AnimationListener() { @Override public void onAnimationStart(Animation animation) { // Slide the bottom nav on animation start so it's (not) visible when the dialpad // finishes animating down. if (bottomNavVisible) { showBottomNav(); } else { hideBottomNav(); } } @Override public void onAnimationEnd(Animation animation) { if (!(isFinishing() || isDestroyed())) { getFragmentManager().beginTransaction().remove(dialpadFragment).commit(); } } @Override public void onAnimationRepeat(Animation animation) {} }); } private void hideBottomNav() { bottomNav.setVisibility(View.INVISIBLE); if (bottomNav.getHeight() == 0) { ViewUtil.doOnGlobalLayout(bottomNav, v -> fab.setTranslationY(bottomNav.getHeight())); } else { fab.setTranslationY(bottomNav.getHeight()); } } private void showBottomNav() { bottomNav.setVisibility(View.VISIBLE); fab.setTranslationY(0); } /** * Should be called when the user presses the back button. * * @return true if #onBackPressed() handled to action. */ public boolean onBackPressed() { if (isDialpadVisible() && !TextUtils.isEmpty(getDialpadFragment().getQuery())) { hideDialpad(/* animate=*/ true, /* bottomNavVisible=*/ false); return true; } else if (isSearchVisible()) { closeSearch(true); return true; } else { return false; } } /** Calls {@link #hideDialpad(boolean, boolean)} and removes the search fragment. */ private void closeSearch(boolean animate) { Assert.checkArgument(isSearchVisible()); if (isDialpadVisible()) { hideDialpad(animate, /* bottomNavVisible=*/ true); } else if (!fab.isShown()) { fab.show(); } showBottomNav(); toolbar.collapse(animate); getFragmentManager().beginTransaction().remove(getSearchFragment()).commit(); } private DialpadFragment getDialpadFragment() { return (DialpadFragment) getFragmentManager().findFragmentByTag(DIALPAD_FRAGMENT_TAG); } private NewSearchFragment getSearchFragment() { return (NewSearchFragment) getFragmentManager().findFragmentByTag(SEARCH_FRAGMENT_TAG); } private boolean isDialpadVisible() { DialpadFragment fragment = getDialpadFragment(); return fragment != null && fragment.isAdded() && !fragment.isHidden() && fragment.isDialpadSlideUp(); } private boolean isSearchVisible() { NewSearchFragment fragment = getSearchFragment(); return fragment != null && fragment.isAdded() && !fragment.isHidden(); } /** * Opens search in regular/search bar search mode. * * <p>Hides fab, expands toolbar and starts the search fragment. */ @Override public void onSearchBarClicked() { fab.hide(); toolbar.expand(/* animate=*/ true, Optional.absent()); android.app.FragmentTransaction transaction = getFragmentManager().beginTransaction(); // Show Search if (getSearchFragment() == null) { NewSearchFragment searchFragment = NewSearchFragment.newInstance(false); transaction.add(R.id.search_fragment_container, searchFragment, SEARCH_FRAGMENT_TAG); } else if (!isSearchVisible()) { transaction.show(getSearchFragment()); } transaction.commit(); } @Override public void onSearchBackButtonClicked() { closeSearch(true); } @Override public void onSearchQueryUpdated(String query) {} @Override public void onVoiceButtonClicked(VoiceSearchResultCallback voiceSearchResultCallback) {} @Override public void openSettings() {} @Override public void sendFeedback() {} } /** * Implementation of {@link OnBottomNavTabSelectedListener} that handles logic for showing each of * the main tabs. Loading java/com/android/dialer/main/impl/MainSearchController.java 0 → 100644 +246 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.dialer.main.impl; import android.support.design.widget.FloatingActionButton; import android.text.TextUtils; import android.view.View; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import com.android.dialer.common.Assert; import com.android.dialer.dialpadview.DialpadFragment; import com.android.dialer.dialpadview.DialpadFragment.DialpadListener; import com.android.dialer.main.impl.toolbar.MainToolbar; import com.android.dialer.main.impl.toolbar.SearchBarListener; import com.android.dialer.searchfragment.list.NewSearchFragment; import com.android.dialer.util.ViewUtil; import com.google.common.base.Optional; /** * Search controller for handling all the logic related to entering and exiting the search UI. * * <p>Components modified are: * * <ul> * <li>Bottom Nav Bar, completely hidden when in search ui. * <li>FAB, visible in dialpad search when dialpad is hidden. Otherwise, FAB is hidden. * <li>Toolbar, expanded and visible when dialpad is hidden. Otherwise, hidden off screen. * <li>Dialpad, shown through fab clicks and hidden with Android back button. * </ul> * * @see #onBackPressed() */ final class MainSearchController implements SearchBarListener { private static final String DIALPAD_FRAGMENT_TAG = "dialpad_fragment_tag"; private static final String SEARCH_FRAGMENT_TAG = "search_fragment_tag"; private final MainActivity mainActivity; private final BottomNavBar bottomNav; private final FloatingActionButton fab; private final MainToolbar toolbar; MainSearchController( MainActivity mainActivity, BottomNavBar bottomNav, FloatingActionButton fab, MainToolbar toolbar) { this.mainActivity = mainActivity; this.bottomNav = bottomNav; this.fab = fab; this.toolbar = toolbar; } /** Shows the dialpad, hides the FAB and slides the toolbar off screen. */ public void showDialpad(boolean animate) { Assert.checkArgument(!isDialpadVisible()); fab.hide(); toolbar.slideUp(animate); toolbar.expand(animate, Optional.absent()); mainActivity.setTitle(R.string.dialpad_activity_title); android.app.FragmentTransaction transaction = mainActivity.getFragmentManager().beginTransaction(); // Show Search if (getSearchFragment() == null) { NewSearchFragment searchFragment = NewSearchFragment.newInstance(false); transaction.add(R.id.search_fragment_container, searchFragment, SEARCH_FRAGMENT_TAG); } else if (!isSearchVisible()) { transaction.show(getSearchFragment()); } // Show Dialpad if (getDialpadFragment() == null) { DialpadFragment dialpadFragment = new DialpadFragment(); transaction.add(R.id.dialpad_fragment_container, dialpadFragment, DIALPAD_FRAGMENT_TAG); } else { DialpadFragment dialpadFragment = getDialpadFragment(); transaction.show(dialpadFragment); } transaction.commit(); } /** Hides the dialpad, reveals the FAB and slides the toolbar back onto the screen. */ private void hideDialpad(boolean animate, boolean bottomNavVisible) { Assert.checkArgument(isDialpadVisible()); fab.show(); toolbar.slideDown(animate); mainActivity.setTitle(R.string.main_activity_label); DialpadFragment dialpadFragment = getDialpadFragment(); dialpadFragment.setAnimate(animate); dialpadFragment.slideDown( animate, new AnimationListener() { @Override public void onAnimationStart(Animation animation) { // Slide the bottom nav on animation start so it's (not) visible when the dialpad // finishes animating down. if (bottomNavVisible) { showBottomNav(); } else { hideBottomNav(); } } @Override public void onAnimationEnd(Animation animation) { if (!(mainActivity.isFinishing() || mainActivity.isDestroyed())) { mainActivity.getFragmentManager().beginTransaction().remove(dialpadFragment).commit(); } } @Override public void onAnimationRepeat(Animation animation) {} }); } private void hideBottomNav() { bottomNav.setVisibility(View.INVISIBLE); if (bottomNav.getHeight() == 0) { ViewUtil.doOnGlobalLayout(bottomNav, v -> fab.setTranslationY(bottomNav.getHeight())); } else { fab.setTranslationY(bottomNav.getHeight()); } } private void showBottomNav() { bottomNav.setVisibility(View.VISIBLE); fab.setTranslationY(0); } /** Should be called when {@link DialpadListener#onDialpadShown()} is called. */ public void onDialpadShown() { getDialpadFragment().slideUp(true); } /** * Should be called when the user presses the back button. * * @return true if #onBackPressed() handled to action. */ public boolean onBackPressed() { if (isDialpadVisible() && !TextUtils.isEmpty(getDialpadFragment().getQuery())) { hideDialpad(/* animate=*/ true, /* bottomNavVisible=*/ false); return true; } else if (isSearchVisible()) { closeSearch(true); return true; } else { return false; } } /** Calls {@link #hideDialpad(boolean, boolean)} and removes the search fragment. */ private void closeSearch(boolean animate) { Assert.checkArgument(isSearchVisible()); if (isDialpadVisible()) { hideDialpad(animate, /* bottomNavVisible=*/ true); } else if (!fab.isShown()) { fab.show(); } showBottomNav(); toolbar.collapse(animate); mainActivity.getFragmentManager().beginTransaction().remove(getSearchFragment()).commit(); } private DialpadFragment getDialpadFragment() { return (DialpadFragment) mainActivity.getFragmentManager().findFragmentByTag(DIALPAD_FRAGMENT_TAG); } private NewSearchFragment getSearchFragment() { return (NewSearchFragment) mainActivity.getFragmentManager().findFragmentByTag(SEARCH_FRAGMENT_TAG); } private boolean isDialpadVisible() { DialpadFragment fragment = getDialpadFragment(); return fragment != null && fragment.isAdded() && !fragment.isHidden() && fragment.isDialpadSlideUp(); } private boolean isSearchVisible() { NewSearchFragment fragment = getSearchFragment(); return fragment != null && fragment.isAdded() && !fragment.isHidden(); } /** * Opens search in regular/search bar search mode. * * <p>Hides fab, expands toolbar and starts the search fragment. */ @Override public void onSearchBarClicked() { fab.hide(); toolbar.expand(/* animate=*/ true, Optional.absent()); android.app.FragmentTransaction transaction = mainActivity.getFragmentManager().beginTransaction(); // Show Search if (getSearchFragment() == null) { NewSearchFragment searchFragment = NewSearchFragment.newInstance(false); transaction.add(R.id.search_fragment_container, searchFragment, SEARCH_FRAGMENT_TAG); } else if (!isSearchVisible()) { transaction.show(getSearchFragment()); } transaction.commit(); } @Override public void onSearchBackButtonClicked() { closeSearch(true); } @Override public void onSearchQueryUpdated(String query) {} @Override public void onVoiceButtonClicked(VoiceSearchResultCallback voiceSearchResultCallback) {} @Override public void openSettings() {} @Override public void sendFeedback() {} } Loading
java/com/android/dialer/main/impl/MainActivity.java +3 −213 Original line number Diff line number Diff line Loading @@ -24,13 +24,8 @@ import android.provider.ContactsContract.QuickContact; import android.support.design.widget.FloatingActionButton; import android.support.v4.app.FragmentTransaction; import android.support.v7.app.AppCompatActivity; import android.text.TextUtils; import android.view.View; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.widget.ImageView; import com.android.dialer.calllog.ui.NewCallLogFragment; import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; import com.android.dialer.contactsfragment.ContactsFragment; import com.android.dialer.contactsfragment.ContactsFragment.Header; Loading @@ -41,13 +36,9 @@ import com.android.dialer.dialpadview.DialpadFragment.LastOutgoingCallCallback; import com.android.dialer.dialpadview.DialpadFragment.OnDialpadQueryChangedListener; import com.android.dialer.main.impl.BottomNavBar.OnBottomNavTabSelectedListener; import com.android.dialer.main.impl.toolbar.MainToolbar; import com.android.dialer.main.impl.toolbar.SearchBarListener; import com.android.dialer.searchfragment.list.NewSearchFragment; import com.android.dialer.searchfragment.list.NewSearchFragment.SearchFragmentListener; import com.android.dialer.speeddial.SpeedDialFragment; import com.android.dialer.util.ViewUtil; import com.android.dialer.voicemail.listui.NewVoicemailFragment; import com.google.common.base.Optional; /** This is the main activity for dialer. It hosts favorites, call log, search, dialpad, etc... */ public final class MainActivity extends AppCompatActivity Loading @@ -59,7 +50,7 @@ public final class MainActivity extends AppCompatActivity private static final String IS_FAB_HIDDEN_KEY = "is_fab_hidden"; private SearchController searchController; private MainSearchController searchController; private FloatingActionButton fab; /** Loading Loading @@ -92,7 +83,7 @@ public final class MainActivity extends AppCompatActivity // TODO(calderwoodra): Implement last tab navBar.selectTab(BottomNavBar.TabIndex.SPEED_DIAL); searchController = new SearchController(navBar, fab, toolbar); searchController = new MainSearchController(this, navBar, fab, toolbar); toolbar.setSearchBarListener(searchController); } Loading Loading @@ -129,7 +120,7 @@ public final class MainActivity extends AppCompatActivity @Override // DialpadListener public void onDialpadShown() { searchController.getDialpadFragment().slideUp(true); searchController.onDialpadShown(); } @Override // DialpadListener Loading Loading @@ -161,207 +152,6 @@ public final class MainActivity extends AppCompatActivity // TODO(calderwoodra): logging } /** * Search controller for handling all the logic related to entering and exiting the search UI. * * <p>Components modified are: * * <ul> * <li>Bottom Nav Bar, completely hidden when in search ui. * <li>FAB, visible in dialpad search when dialpad is hidden. Otherwise, FAB is hidden. * <li>Toolbar, expanded and visible when dialpad is hidden. Otherwise, hidden off screen. * <li>Dialpad, shown through fab clicks and hidden with Android back button. * </ul> * * @see #onBackPressed() */ private final class SearchController implements SearchBarListener { private static final String DIALPAD_FRAGMENT_TAG = "dialpad_fragment_tag"; private static final String SEARCH_FRAGMENT_TAG = "search_fragment_tag"; private final BottomNavBar bottomNav; private final FloatingActionButton fab; private final MainToolbar toolbar; private SearchController( BottomNavBar bottomNav, FloatingActionButton fab, MainToolbar toolbar) { this.bottomNav = bottomNav; this.fab = fab; this.toolbar = toolbar; } /** Shows the dialpad, hides the FAB and slides the toolbar off screen. */ public void showDialpad(boolean animate) { Assert.checkArgument(!isDialpadVisible()); fab.hide(); toolbar.slideUp(animate); toolbar.expand(animate, Optional.absent()); setTitle(R.string.dialpad_activity_title); android.app.FragmentTransaction transaction = getFragmentManager().beginTransaction(); // Show Search if (getSearchFragment() == null) { NewSearchFragment searchFragment = NewSearchFragment.newInstance(false); transaction.add(R.id.search_fragment_container, searchFragment, SEARCH_FRAGMENT_TAG); } else if (!isSearchVisible()) { transaction.show(getSearchFragment()); } // Show Dialpad if (getDialpadFragment() == null) { DialpadFragment dialpadFragment = new DialpadFragment(); transaction.add(R.id.dialpad_fragment_container, dialpadFragment, DIALPAD_FRAGMENT_TAG); } else { DialpadFragment dialpadFragment = getDialpadFragment(); transaction.show(dialpadFragment); } transaction.commit(); } /** Hides the dialpad, reveals the FAB and slides the toolbar back onto the screen. */ public void hideDialpad(boolean animate, boolean bottomNavVisible) { Assert.checkArgument(isDialpadVisible()); fab.show(); toolbar.slideDown(animate); setTitle(R.string.main_activity_label); DialpadFragment dialpadFragment = getDialpadFragment(); dialpadFragment.setAnimate(animate); dialpadFragment.slideDown( animate, new AnimationListener() { @Override public void onAnimationStart(Animation animation) { // Slide the bottom nav on animation start so it's (not) visible when the dialpad // finishes animating down. if (bottomNavVisible) { showBottomNav(); } else { hideBottomNav(); } } @Override public void onAnimationEnd(Animation animation) { if (!(isFinishing() || isDestroyed())) { getFragmentManager().beginTransaction().remove(dialpadFragment).commit(); } } @Override public void onAnimationRepeat(Animation animation) {} }); } private void hideBottomNav() { bottomNav.setVisibility(View.INVISIBLE); if (bottomNav.getHeight() == 0) { ViewUtil.doOnGlobalLayout(bottomNav, v -> fab.setTranslationY(bottomNav.getHeight())); } else { fab.setTranslationY(bottomNav.getHeight()); } } private void showBottomNav() { bottomNav.setVisibility(View.VISIBLE); fab.setTranslationY(0); } /** * Should be called when the user presses the back button. * * @return true if #onBackPressed() handled to action. */ public boolean onBackPressed() { if (isDialpadVisible() && !TextUtils.isEmpty(getDialpadFragment().getQuery())) { hideDialpad(/* animate=*/ true, /* bottomNavVisible=*/ false); return true; } else if (isSearchVisible()) { closeSearch(true); return true; } else { return false; } } /** Calls {@link #hideDialpad(boolean, boolean)} and removes the search fragment. */ private void closeSearch(boolean animate) { Assert.checkArgument(isSearchVisible()); if (isDialpadVisible()) { hideDialpad(animate, /* bottomNavVisible=*/ true); } else if (!fab.isShown()) { fab.show(); } showBottomNav(); toolbar.collapse(animate); getFragmentManager().beginTransaction().remove(getSearchFragment()).commit(); } private DialpadFragment getDialpadFragment() { return (DialpadFragment) getFragmentManager().findFragmentByTag(DIALPAD_FRAGMENT_TAG); } private NewSearchFragment getSearchFragment() { return (NewSearchFragment) getFragmentManager().findFragmentByTag(SEARCH_FRAGMENT_TAG); } private boolean isDialpadVisible() { DialpadFragment fragment = getDialpadFragment(); return fragment != null && fragment.isAdded() && !fragment.isHidden() && fragment.isDialpadSlideUp(); } private boolean isSearchVisible() { NewSearchFragment fragment = getSearchFragment(); return fragment != null && fragment.isAdded() && !fragment.isHidden(); } /** * Opens search in regular/search bar search mode. * * <p>Hides fab, expands toolbar and starts the search fragment. */ @Override public void onSearchBarClicked() { fab.hide(); toolbar.expand(/* animate=*/ true, Optional.absent()); android.app.FragmentTransaction transaction = getFragmentManager().beginTransaction(); // Show Search if (getSearchFragment() == null) { NewSearchFragment searchFragment = NewSearchFragment.newInstance(false); transaction.add(R.id.search_fragment_container, searchFragment, SEARCH_FRAGMENT_TAG); } else if (!isSearchVisible()) { transaction.show(getSearchFragment()); } transaction.commit(); } @Override public void onSearchBackButtonClicked() { closeSearch(true); } @Override public void onSearchQueryUpdated(String query) {} @Override public void onVoiceButtonClicked(VoiceSearchResultCallback voiceSearchResultCallback) {} @Override public void openSettings() {} @Override public void sendFeedback() {} } /** * Implementation of {@link OnBottomNavTabSelectedListener} that handles logic for showing each of * the main tabs. Loading
java/com/android/dialer/main/impl/MainSearchController.java 0 → 100644 +246 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.dialer.main.impl; import android.support.design.widget.FloatingActionButton; import android.text.TextUtils; import android.view.View; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import com.android.dialer.common.Assert; import com.android.dialer.dialpadview.DialpadFragment; import com.android.dialer.dialpadview.DialpadFragment.DialpadListener; import com.android.dialer.main.impl.toolbar.MainToolbar; import com.android.dialer.main.impl.toolbar.SearchBarListener; import com.android.dialer.searchfragment.list.NewSearchFragment; import com.android.dialer.util.ViewUtil; import com.google.common.base.Optional; /** * Search controller for handling all the logic related to entering and exiting the search UI. * * <p>Components modified are: * * <ul> * <li>Bottom Nav Bar, completely hidden when in search ui. * <li>FAB, visible in dialpad search when dialpad is hidden. Otherwise, FAB is hidden. * <li>Toolbar, expanded and visible when dialpad is hidden. Otherwise, hidden off screen. * <li>Dialpad, shown through fab clicks and hidden with Android back button. * </ul> * * @see #onBackPressed() */ final class MainSearchController implements SearchBarListener { private static final String DIALPAD_FRAGMENT_TAG = "dialpad_fragment_tag"; private static final String SEARCH_FRAGMENT_TAG = "search_fragment_tag"; private final MainActivity mainActivity; private final BottomNavBar bottomNav; private final FloatingActionButton fab; private final MainToolbar toolbar; MainSearchController( MainActivity mainActivity, BottomNavBar bottomNav, FloatingActionButton fab, MainToolbar toolbar) { this.mainActivity = mainActivity; this.bottomNav = bottomNav; this.fab = fab; this.toolbar = toolbar; } /** Shows the dialpad, hides the FAB and slides the toolbar off screen. */ public void showDialpad(boolean animate) { Assert.checkArgument(!isDialpadVisible()); fab.hide(); toolbar.slideUp(animate); toolbar.expand(animate, Optional.absent()); mainActivity.setTitle(R.string.dialpad_activity_title); android.app.FragmentTransaction transaction = mainActivity.getFragmentManager().beginTransaction(); // Show Search if (getSearchFragment() == null) { NewSearchFragment searchFragment = NewSearchFragment.newInstance(false); transaction.add(R.id.search_fragment_container, searchFragment, SEARCH_FRAGMENT_TAG); } else if (!isSearchVisible()) { transaction.show(getSearchFragment()); } // Show Dialpad if (getDialpadFragment() == null) { DialpadFragment dialpadFragment = new DialpadFragment(); transaction.add(R.id.dialpad_fragment_container, dialpadFragment, DIALPAD_FRAGMENT_TAG); } else { DialpadFragment dialpadFragment = getDialpadFragment(); transaction.show(dialpadFragment); } transaction.commit(); } /** Hides the dialpad, reveals the FAB and slides the toolbar back onto the screen. */ private void hideDialpad(boolean animate, boolean bottomNavVisible) { Assert.checkArgument(isDialpadVisible()); fab.show(); toolbar.slideDown(animate); mainActivity.setTitle(R.string.main_activity_label); DialpadFragment dialpadFragment = getDialpadFragment(); dialpadFragment.setAnimate(animate); dialpadFragment.slideDown( animate, new AnimationListener() { @Override public void onAnimationStart(Animation animation) { // Slide the bottom nav on animation start so it's (not) visible when the dialpad // finishes animating down. if (bottomNavVisible) { showBottomNav(); } else { hideBottomNav(); } } @Override public void onAnimationEnd(Animation animation) { if (!(mainActivity.isFinishing() || mainActivity.isDestroyed())) { mainActivity.getFragmentManager().beginTransaction().remove(dialpadFragment).commit(); } } @Override public void onAnimationRepeat(Animation animation) {} }); } private void hideBottomNav() { bottomNav.setVisibility(View.INVISIBLE); if (bottomNav.getHeight() == 0) { ViewUtil.doOnGlobalLayout(bottomNav, v -> fab.setTranslationY(bottomNav.getHeight())); } else { fab.setTranslationY(bottomNav.getHeight()); } } private void showBottomNav() { bottomNav.setVisibility(View.VISIBLE); fab.setTranslationY(0); } /** Should be called when {@link DialpadListener#onDialpadShown()} is called. */ public void onDialpadShown() { getDialpadFragment().slideUp(true); } /** * Should be called when the user presses the back button. * * @return true if #onBackPressed() handled to action. */ public boolean onBackPressed() { if (isDialpadVisible() && !TextUtils.isEmpty(getDialpadFragment().getQuery())) { hideDialpad(/* animate=*/ true, /* bottomNavVisible=*/ false); return true; } else if (isSearchVisible()) { closeSearch(true); return true; } else { return false; } } /** Calls {@link #hideDialpad(boolean, boolean)} and removes the search fragment. */ private void closeSearch(boolean animate) { Assert.checkArgument(isSearchVisible()); if (isDialpadVisible()) { hideDialpad(animate, /* bottomNavVisible=*/ true); } else if (!fab.isShown()) { fab.show(); } showBottomNav(); toolbar.collapse(animate); mainActivity.getFragmentManager().beginTransaction().remove(getSearchFragment()).commit(); } private DialpadFragment getDialpadFragment() { return (DialpadFragment) mainActivity.getFragmentManager().findFragmentByTag(DIALPAD_FRAGMENT_TAG); } private NewSearchFragment getSearchFragment() { return (NewSearchFragment) mainActivity.getFragmentManager().findFragmentByTag(SEARCH_FRAGMENT_TAG); } private boolean isDialpadVisible() { DialpadFragment fragment = getDialpadFragment(); return fragment != null && fragment.isAdded() && !fragment.isHidden() && fragment.isDialpadSlideUp(); } private boolean isSearchVisible() { NewSearchFragment fragment = getSearchFragment(); return fragment != null && fragment.isAdded() && !fragment.isHidden(); } /** * Opens search in regular/search bar search mode. * * <p>Hides fab, expands toolbar and starts the search fragment. */ @Override public void onSearchBarClicked() { fab.hide(); toolbar.expand(/* animate=*/ true, Optional.absent()); android.app.FragmentTransaction transaction = mainActivity.getFragmentManager().beginTransaction(); // Show Search if (getSearchFragment() == null) { NewSearchFragment searchFragment = NewSearchFragment.newInstance(false); transaction.add(R.id.search_fragment_container, searchFragment, SEARCH_FRAGMENT_TAG); } else if (!isSearchVisible()) { transaction.show(getSearchFragment()); } transaction.commit(); } @Override public void onSearchBackButtonClicked() { closeSearch(true); } @Override public void onSearchQueryUpdated(String query) {} @Override public void onVoiceButtonClicked(VoiceSearchResultCallback voiceSearchResultCallback) {} @Override public void openSettings() {} @Override public void sendFeedback() {} }