diff options
Diffstat (limited to 'java/com/android/dialer/main/impl')
6 files changed, 222 insertions, 17 deletions
diff --git a/java/com/android/dialer/main/impl/MainActivity.java b/java/com/android/dialer/main/impl/MainActivity.java index fc7e670b0..8bdb295c7 100644 --- a/java/com/android/dialer/main/impl/MainActivity.java +++ b/java/com/android/dialer/main/impl/MainActivity.java @@ -21,24 +21,35 @@ import android.content.Intent; import android.net.Uri; import android.os.Bundle; 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.view.View; +import android.text.TextUtils; +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; import com.android.dialer.contactsfragment.ContactsFragment.OnContactSelectedListener; +import com.android.dialer.dialpadview.DialpadFragment; +import com.android.dialer.dialpadview.DialpadFragment.DialpadListener; +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.speeddial.SpeedDialFragment; import com.android.dialer.voicemail.listui.NewVoicemailFragment; /** This is the main activity for dialer. It hosts favorites, call log, search, dialpad, etc... */ public final class MainActivity extends AppCompatActivity - implements View.OnClickListener, OnContactSelectedListener { + implements OnContactSelectedListener, OnDialpadQueryChangedListener, DialpadListener { + + private SearchController searchController; /** * @param context Context of the application package implementing MainActivity class. @@ -59,29 +70,168 @@ public final class MainActivity extends AppCompatActivity } private void initLayout() { - findViewById(R.id.fab).setOnClickListener(this); + FloatingActionButton fab = findViewById(R.id.fab); + fab.setOnClickListener(v -> searchController.showDialpad(true)); + MainToolbar toolbar = findViewById(R.id.toolbar); toolbar.setSearchBarListener(new MainSearchBarListener()); - setSupportActionBar(toolbar); + searchController = new SearchController(fab, toolbar); + setSupportActionBar(findViewById(R.id.toolbar)); + BottomNavBar navBar = findViewById(R.id.bottom_nav_bar); navBar.setOnTabSelectedListener(new MainBottomNavBarBottomNavTabListener()); + // TODO(calderwoodra): Implement last tab navBar.selectTab(BottomNavBar.TabIndex.SPEED_DIAL); } @Override - public void onClick(View v) { - if (v.getId() == R.id.fab) { - // open dialpad search - } - } - - @Override public void onContactSelected(ImageView photo, Uri contactUri, long contactId) { // TODO(calderwoodra): Add impression logging QuickContact.showQuickContact( this, photo, contactUri, QuickContact.MODE_LARGE, null /* excludeMimes */); } + @Override // OnDialpadQueryChangedListener + public void onDialpadQueryChanged(String query) { + // TODO(calderwoodra): update search fragment + } + + @Override // DialpadListener + public void getLastOutgoingCall(LastOutgoingCallCallback callback) { + // TODO(calderwoodra): migrate CallLogAsync class outside of dialer/app and call it here. + } + + @Override // DialpadListener + public void onDialpadShown() { + searchController.getDialpadFragment().slideUp(true); + } + + @Override // DialpadListener + public void onCallPlacedFromDialpad() { + // TODO(calderwoodra): logging + } + + @Override + public void onBackPressed() { + if (searchController.onBackPressed()) { + return; + } + super.onBackPressed(); + } + + /** Search controller for handling all the logic related to hiding/showing search and dialpad. */ + private final class SearchController { + + private static final String DIALPAD_FRAGMENT_TAG = "dialpad_fragment_tag"; + private static final String SEARCH_FRAGMENT_TAG = "search_fragment_tag"; + + private final FloatingActionButton fab; + private final MainToolbar toolbar; + + private boolean isDialpadVisible; + private boolean isSearchVisible; + + private SearchController(FloatingActionButton fab, MainToolbar toolbar) { + 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); + isDialpadVisible = true; + isSearchVisible = true; + + fab.hide(); + toolbar.slideUp(animate); + 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.search_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) { + Assert.checkArgument(isDialpadVisible); + isDialpadVisible = false; + + 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) {} + + @Override + public void onAnimationEnd(Animation animation) { + if (!(isFinishing() || isDestroyed())) { + getFragmentManager().beginTransaction().remove(dialpadFragment).commit(); + } + } + + @Override + public void onAnimationRepeat(Animation animation) {} + }); + } + + /** + * Should be called when the user presses the back button. + * + * @return true if {@link #onBackPressed()} handled to action. + */ + public boolean onBackPressed() { + if (isDialpadVisible && !TextUtils.isEmpty(getDialpadFragment().getQuery())) { + hideDialpad(true); + return true; + } else if (isSearchVisible) { + closeSearch(true); + return true; + } else { + return false; + } + } + + /** Calls {@link #hideDialpad(boolean)} and removes the search fragment. */ + private void closeSearch(boolean animate) { + Assert.checkArgument(isSearchVisible); + if (isDialpadVisible) { + hideDialpad(animate); + } + getFragmentManager().beginTransaction().remove(getSearchFragment()).commit(); + isSearchVisible = false; + } + + private DialpadFragment getDialpadFragment() { + return (DialpadFragment) getFragmentManager().findFragmentByTag(DIALPAD_FRAGMENT_TAG); + } + + private NewSearchFragment getSearchFragment() { + return (NewSearchFragment) getFragmentManager().findFragmentByTag(SEARCH_FRAGMENT_TAG); + } + } + /** * Implementation of {@link SearchBarListener} that holds the logic for how to handle search bar * events. diff --git a/java/com/android/dialer/main/impl/res/layout/bottom_nav_item.xml b/java/com/android/dialer/main/impl/res/layout/bottom_nav_item.xml index 28ad964dd..f9f2b6102 100644 --- a/java/com/android/dialer/main/impl/res/layout/bottom_nav_item.xml +++ b/java/com/android/dialer/main/impl/res/layout/bottom_nav_item.xml @@ -37,5 +37,6 @@ android:id="@+id/bottom_nav_item_text" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textSize="12sp"/> + android:textSize="12sp" + android:gravity="center_horizontal"/> </com.android.dialer.main.impl.BottomNavItem>
\ No newline at end of file diff --git a/java/com/android/dialer/main/impl/res/layout/main_activity.xml b/java/com/android/dialer/main/impl/res/layout/main_activity.xml index 31ff19dd3..0b0652af5 100644 --- a/java/com/android/dialer/main/impl/res/layout/main_activity.xml +++ b/java/com/android/dialer/main/impl/res/layout/main_activity.xml @@ -21,10 +21,7 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - <include - android:id="@+id/toolbar" - layout="@layout/toolbar_layout"/> - + <!-- Holds SpeedDial, Call Log, Contacts and Voicemail fragments --> <FrameLayout android:id="@+id/fragment_container" android:layout_width="match_parent" @@ -32,14 +29,26 @@ android:layout_below="@+id/toolbar" android:layout_above="@+id/bottom_nav_bar"/> + <!-- BottomNavBar --> <include android:id="@+id/bottom_nav_bar" layout="@layout/bottom_nav_bar_layout" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_gravity="bottom" android:layout_alignParentBottom="true"/> + <!-- Holds search and dialpad fragments --> + <FrameLayout + android:id="@+id/search_fragment_container" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_below="@+id/toolbar"/> + + <!-- MainToolbar --> + <include + android:id="@+id/toolbar" + layout="@layout/toolbar_layout"/> + <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" diff --git a/java/com/android/dialer/main/impl/res/values/strings.xml b/java/com/android/dialer/main/impl/res/values/strings.xml index ff136e877..f530fa2bf 100644 --- a/java/com/android/dialer/main/impl/res/values/strings.xml +++ b/java/com/android/dialer/main/impl/res/values/strings.xml @@ -22,6 +22,9 @@ TODO(38502365): Remove this once we're ready to launch the new UI. --> <string name="nui_shortcut_name">Phone NUI</string> + <!-- Title for the activity that dials the phone, when launched directly into the dialpad --> + <string name="dialpad_activity_title">Phone Keypad</string> + <!-- The description text for the call log tab. --> <string name="main_call_history_tab_description" tools:ignore="UnusedResources">Call history</string> diff --git a/java/com/android/dialer/main/impl/res/values/styles.xml b/java/com/android/dialer/main/impl/res/values/styles.xml index f94897a8b..26f880dc4 100644 --- a/java/com/android/dialer/main/impl/res/values/styles.xml +++ b/java/com/android/dialer/main/impl/res/values/styles.xml @@ -19,5 +19,8 @@ <item name="android:colorPrimary">@color/dialtacts_theme_color</item> <item name="android:colorPrimaryDark">@color/dialer_theme_color_dark</item> <item name="android:colorAccent">@color/dialer_secondary_color</item> + + <!-- Theme needed for DialpadFragment --> + <item name="dialpad_style">@style/Dialpad.Light</item> </style> </resources> diff --git a/java/com/android/dialer/main/impl/toolbar/MainToolbar.java b/java/com/android/dialer/main/impl/toolbar/MainToolbar.java index 6d9b7da6b..b32217230 100644 --- a/java/com/android/dialer/main/impl/toolbar/MainToolbar.java +++ b/java/com/android/dialer/main/impl/toolbar/MainToolbar.java @@ -17,16 +17,24 @@ package com.android.dialer.main.impl.toolbar; import android.content.Context; +import android.support.annotation.VisibleForTesting; import android.support.v7.widget.PopupMenu.OnMenuItemClickListener; import android.support.v7.widget.Toolbar; import android.util.AttributeSet; import android.view.MenuItem; +import android.view.animation.AccelerateDecelerateInterpolator; import android.widget.ImageButton; +import com.android.dialer.common.Assert; /** Toolbar for {@link com.android.dialer.main.impl.MainActivity}. */ public final class MainToolbar extends Toolbar implements OnMenuItemClickListener { + private static final int SLIDE_DURATION = 300; + private static final AccelerateDecelerateInterpolator SLIDE_INTERPOLATOR = + new AccelerateDecelerateInterpolator(); + private SearchBarListener listener; + private boolean isSlideUp; public MainToolbar(Context context, AttributeSet attrs) { super(context, attrs); @@ -57,4 +65,35 @@ public final class MainToolbar extends Toolbar implements OnMenuItemClickListene this.listener = listener; ((SearchBarView) findViewById(R.id.search_view_container)).setSearchBarListener(listener); } + + /** Slides the toolbar up and off the screen. */ + public void slideUp(boolean animate) { + Assert.checkArgument(!isSlideUp); + isSlideUp = true; + animate() + .translationY(-getHeight()) + .setDuration(animate ? SLIDE_DURATION : 0) + .setInterpolator(SLIDE_INTERPOLATOR) + .start(); + } + + /** + * Slides the toolbar down and back onto the screen. + * + * @param animate + */ + public void slideDown(boolean animate) { + Assert.checkArgument(isSlideUp); + isSlideUp = false; + animate() + .translationY(0) + .setDuration(animate ? SLIDE_DURATION : 0) + .setInterpolator(SLIDE_INTERPOLATOR) + .start(); + } + + @VisibleForTesting + public boolean isSlideUp() { + return isSlideUp; + } } |