package com.duckduckgo.mobile.android.actionbar; import android.animation.ValueAnimator; import android.app.Activity; import android.content.Context; import android.graphics.Typeface; import android.os.Build; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v7.view.menu.MenuBuilder; import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.view.animation.Transformation; import android.widget.FrameLayout; import android.widget.ImageButton; import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import com.duckduckgo.mobile.android.R; import com.duckduckgo.mobile.android.activity.KeyboardService; import com.duckduckgo.mobile.android.bus.BusProvider; import com.duckduckgo.mobile.android.events.DisplayHomeScreenEvent; import com.duckduckgo.mobile.android.events.OverflowButtonClickEvent; import com.duckduckgo.mobile.android.fragment.SearchFragment; import com.duckduckgo.mobile.android.fragment.WebFragment; import com.duckduckgo.mobile.android.util.DDGControlVar; import com.duckduckgo.mobile.android.util.DDGUtils; import com.duckduckgo.mobile.android.util.SCREEN; import com.duckduckgo.mobile.android.util.SESSIONTYPE; import com.duckduckgo.mobile.android.views.DDGOverflowMenu; import com.duckduckgo.mobile.android.views.SlidingTabLayout; import com.duckduckgo.mobile.android.views.autocomplete.DDGAutoCompleteTextView; public final class DDGActionBarManager implements View.OnClickListener, View.OnLongClickListener { public static final String TAG = "ddg_actionbar_manager"; private Activity activity; private Context context; private KeyboardService keyboardService; private DDGAutoCompleteTextView searchField = null; private RelativeLayout searchFieldContainer = null; private TextView actionBarTitle; private ImageButton homeButton; private ImageButton bangButton; private ImageButton overflowButton; private ProgressBar progressBar; private ProgressBarAnimation progressBarAnimation = null; private int oldProgress = 0; private boolean isProgressVisible = false; private SlidingTabLayout slidingTabLayout; private boolean isTabAnimating = false; private DDGOverflowMenu overflowMenu = null; private Menu mainMenu; private MenuInflater inflater; private Toolbar toolbar; private String tag; private static final DDGActionBarManager DDG_ACTION_BAR_MANAGER = new DDGActionBarManager(); public static DDGActionBarManager getInstance() { return DDG_ACTION_BAR_MANAGER; } private DDGActionBarManager() { // No instances. } public void init(Activity activity, Context context, Toolbar toolbar) { this.activity = activity; this.context = context; this.toolbar = toolbar; this.inflater = activity.getMenuInflater(); searchFieldContainer = (RelativeLayout) toolbar.findViewById(R.id.search_container); actionBarTitle = (TextView) toolbar.findViewById(R.id.actionbar_title); Typeface typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto_Medium.ttf"); actionBarTitle.setTypeface(typeface); slidingTabLayout = (SlidingTabLayout) toolbar.findViewById(R.id.sliding_tabs); progressBar = (ProgressBar) toolbar.findViewById(R.id.progress_bar); searchField = (DDGAutoCompleteTextView) toolbar.findViewById(R.id.searchEditText); homeButton = (ImageButton) toolbar.findViewById(R.id.home); homeButton.setOnClickListener(this); homeButton.setOnLongClickListener(this); bangButton = (ImageButton) toolbar.findViewById(R.id.bang); bangButton.setOnClickListener(this); bangButton.setOnLongClickListener(this); overflowButton = (ImageButton) toolbar.findViewById(R.id.overflow); overflowButton.setOnClickListener(this); overflowButton.setOnLongClickListener(this); keyboardService = new KeyboardService(activity); mainMenu = new MenuBuilder(activity); inflater.inflate(R.menu.main, mainMenu); } public DDGAutoCompleteTextView getSearchField() { return this.searchField; } public SlidingTabLayout getSlidingTabLayout() { return this.slidingTabLayout; } public Toolbar getToolbar() { return this.toolbar; } @Override public void onClick(View v) { switch(v.getId()) { case R.id.home: stopProgress(); setProgressBarVisible(false); BusProvider.getInstance().post(new DisplayHomeScreenEvent()); break; case R.id.bang: stopProgress(); setProgressBarVisible(false); getSearchField().addBang(); break; case R.id.overflow: if(tag.equals(WebFragment.TAG)) { BusProvider.getInstance().post(new OverflowButtonClickEvent(toolbar)); } else { showMenu(tag); } default: break; } } @Override public boolean onLongClick(View v) { switch(v.getId()) { case R.id.home: Toast.makeText(context, "Home", Toast.LENGTH_SHORT).show(); return true; case R.id.bang: Toast.makeText(context, "Bang", Toast.LENGTH_SHORT).show(); return true; default: return false; } } public void updateActionBar(FragmentManager fragmentManager, String tag, boolean backPressed) { Log.d(TAG, "update actionbar: "+tag); this.tag = tag; SCREEN screen = DDGUtils.getScreenByTag(tag); boolean isStartingScreen = DDGControlVar.START_SCREEN==screen; if(!tag.equals(SearchFragment.TAG)) { Fragment searchFragment = fragmentManager.findFragmentByTag(SearchFragment.TAG); if(searchFragment==null || !searchFragment.isVisible()) { getSearchField().setFocusable(false); getSearchField().setFocusableInTouchMode(false); getSearchField().setFocusable(true); getSearchField().setFocusableInTouchMode(true); } } int standardMargin = (int) context.getResources().getDimension(R.dimen.actionbar_margin); int overflowVisibleRightMargin = 0; int actionButtonVisibleLeftMargin = (int) context.getResources().getDimension(R.dimen.actionbar_searchbar_left_margin_with_button); overflowVisibleRightMargin = actionButtonVisibleLeftMargin; int leftMargin , rightMargin; for(int i=0; i<mainMenu.size(); i++) { mainMenu.getItem(i).setEnabled(true); } switch(screen) { case SCR_STORIES: clearSearchBar(); showSearchField(); leftMargin = isStartingScreen ? standardMargin : actionButtonVisibleLeftMargin; rightMargin = overflowVisibleRightMargin; setActionBarMargins(leftMargin, standardMargin, rightMargin, standardMargin); setHomeButton(!isStartingScreen); setOverflowButton(true); setOverflowButtonMarginTop(false); setHomeButtonMarginTop(false); setTabLayout(false); setProgressBarVisible(false); MenuItem feedItem = mainMenu.findItem(R.id.action_stories); if(feedItem!=null) { feedItem.setEnabled(false); } break; case SCR_RECENTS: clearSearchBar(); showSearchField(); leftMargin = isStartingScreen ? standardMargin : actionButtonVisibleLeftMargin; rightMargin = overflowVisibleRightMargin; setActionBarMargins(leftMargin, standardMargin, rightMargin, standardMargin); setOverflowButton(true); setOverflowButtonMarginTop(false); setHomeButton(!isStartingScreen); setHomeButtonMarginTop(false); setProgressBarVisible(false); MenuItem recentItem = mainMenu.findItem(R.id.action_recents); if(recentItem!=null) { recentItem.setEnabled(false); } break; case SCR_FAVORITE: clearSearchBar(); showSearchField(); leftMargin = isStartingScreen ? standardMargin : actionButtonVisibleLeftMargin; rightMargin = overflowVisibleRightMargin; setActionBarMargins(leftMargin, standardMargin, rightMargin, standardMargin); setOverflowButton(true); setOverflowButtonMarginTop(false); setHomeButton(!isStartingScreen); setHomeButtonMarginTop(false); setProgressBarVisible(false); MenuItem favoriteItem = mainMenu.findItem(R.id.action_favorites); if(favoriteItem!=null) { favoriteItem.setEnabled(false); } break; case SCR_WEBVIEW: showSearchField(); setActionBarMargins(actionButtonVisibleLeftMargin, standardMargin, overflowVisibleRightMargin, standardMargin); setOverflowButton(true); setOverflowButtonMarginTop(false); setHomeButton(true); setHomeButtonMarginTop(false); setTabLayout(false); setProgressBarVisible(true); break; case SCR_SEARCH: case SCR_SEARCH_HOME_PAGE: showSearchField(); rightMargin = overflowVisibleRightMargin; setActionBarMargins(actionButtonVisibleLeftMargin, standardMargin, rightMargin, standardMargin); setHomeButtonMarginTop(false); setOverflowButton(true); setOverflowButtonMarginTop(false); setBangButton(); setTabLayout(false); setProgressBarVisible(false); break; case SCR_ABOUT: showTitle(tag, context.getResources().getString(R.string.about)); setOverflowButton(false); setOverflowButtonMarginTop(false); setHomeButton(true); setHomeButtonMarginTop(false); setTabLayout(false); setProgressBarVisible(false); break; case SCR_HELP: showTitle(tag, context.getResources().getString(R.string.help_feedback)); setOverflowButton(false); setOverflowButtonMarginTop(false); setHomeButton(true); setHomeButtonMarginTop(false); setTabLayout(false); setProgressBarVisible(false); break; case SCR_SETTINGS: showTitle(tag, context.getResources().getString(R.string.settings)); setOverflowButton(false); setOverflowButtonMarginTop(false); setHomeButton(true); setHomeButtonMarginTop(false); setTabLayout(false); setProgressBarVisible(false); break; case SCR_SOURCES: showTitle(tag, context.getResources().getString(R.string.change_sources)); setOverflowButton(false); setOverflowButtonMarginTop(false); setHomeButton(true); setHomeButtonMarginTop(false); setTabLayout(false); setProgressBarVisible(false); default: break; } if(backPressed || DDGControlVar.mDuckDuckGoContainer.prevFragmentTag.equals(SearchFragment.TAG) || DDGControlVar.mDuckDuckGoContainer.prevFragmentTag.equals(SearchFragment.TAG_HOME_PAGE)) { keyboardService.hideKeyboardDelayed(searchField); } else if((tag.equals(SearchFragment.TAG) || tag.equals(SearchFragment.TAG_HOME_PAGE))) { keyboardService.showKeyboard(searchField); } } public void clearSearchBar() { searchField.setText(""); searchField.setCompoundDrawables(null, null, null, null); } public void toggleProgressBarVisibility(boolean visible, boolean withAnimation) { View progressBarContainer = toolbar.findViewById(R.id.progress_container); if((!visible && progressBarContainer.getVisibility()==View.GONE) || (visible && progressBarContainer.getVisibility()==View.VISIBLE)) { return; } if(withAnimation) { int resId = visible ? R.anim.show_progressbar : R.anim.hide_progressbar; Animation animation = AnimationUtils.loadAnimation(context, resId); progressBarContainer.setAnimation(animation); } progressBarContainer.setVisibility(visible ? View.VISIBLE : View.GONE); } public void setProgressBarVisible(boolean visible) { isProgressVisible = visible; if(!visible) { toggleProgressBarVisibility(false, false); } else { toggleProgressBarVisibility(true, true); } } public void setProgress(int newProgress) { if(!isProgressVisible) { return; } if(newProgress<oldProgress) { return; } toggleProgressBarVisibility(true, true); progressBarAnimation = new ProgressBarAnimation(progressBar, oldProgress, newProgress); progressBarAnimation.setDuration(500); progressBar.startAnimation(progressBarAnimation); oldProgress = newProgress; if(oldProgress>=100) { oldProgress = 0; toggleProgressBarVisibility(false, true); } } public void stopProgress() { progressBar.clearAnimation(); progressBar.setProgress(0); oldProgress = 0; } private void showSearchField() { toggleActionBarView(true); } private void showTitle(String tag, String title) { toggleActionBarView(false); setTitle(tag, title); } private void setTitle(String tag, String title) { actionBarTitle.setText(title); } private void toggleActionBarView(boolean searchVisible) { searchFieldContainer.setVisibility(searchVisible ? View.VISIBLE : View.GONE); actionBarTitle.setVisibility(searchVisible ? View.GONE : View.VISIBLE); } private void setActionBarMargins(int newLeft, int newTop, int newRight, int newBottom) { final RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) searchFieldContainer.getLayoutParams(); if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB) { ValueAnimator leftValueAnimator = ValueAnimator.ofInt(params.leftMargin, newLeft); leftValueAnimator.setDuration(250); leftValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { params.leftMargin = (Integer) animation.getAnimatedValue(); searchFieldContainer.setLayoutParams(params); } }); ValueAnimator rightValueAnimator = ValueAnimator.ofInt(params.rightMargin, newRight); rightValueAnimator.setDuration(250); rightValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { params.rightMargin = (Integer) animation.getAnimatedValue(); searchFieldContainer.setLayoutParams(params); } }); ValueAnimator topValueAnimator = ValueAnimator.ofInt(params.topMargin, newTop); topValueAnimator.setDuration(250); topValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { params.topMargin = (Integer) animation.getAnimatedValue(); searchFieldContainer.setLayoutParams(params); } }); ValueAnimator bottomValueAnimator = ValueAnimator.ofInt(params.bottomMargin, newBottom); bottomValueAnimator.setDuration(250); bottomValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { params.bottomMargin = (Integer) animation.getAnimatedValue(); searchFieldContainer.setLayoutParams(params); } }); leftValueAnimator.start(); rightValueAnimator.start(); topValueAnimator.start(); bottomValueAnimator.start(); } else { params.setMargins(newLeft, newTop, newRight, newBottom); } } private void setHomeButton(boolean visible) { Animation fadeIn = AnimationUtils.loadAnimation(context, R.anim.actionbar_button_fade_in); Animation fadeOut = AnimationUtils.loadAnimation(context, R.anim.actionbar_button_fade_out); if (bangButton.getVisibility() == View.VISIBLE) { bangButton.setAnimation(fadeOut); bangButton.setVisibility(View.GONE); } if(visible) { if (homeButton.getVisibility() == View.GONE) { homeButton.setAnimation(fadeIn); homeButton.setVisibility(View.VISIBLE); } } else if(homeButton.getVisibility() == View.VISIBLE) { homeButton.setAnimation(fadeOut); homeButton.setVisibility(View.GONE); } } private void setHomeButtonMarginTop(boolean visible) { final RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) toolbar.findViewById(R.id.home).getLayoutParams(); int padding = visible ? (int) context.getResources().getDimension(R.dimen.actionbar_margin) : 0; params.topMargin = padding; } private void setBangButton() { Animation fadeIn = AnimationUtils.loadAnimation(context, R.anim.actionbar_button_fade_in); Animation fadeOut = AnimationUtils.loadAnimation(context, R.anim.actionbar_button_fade_out); if(homeButton.getVisibility()==View.VISIBLE) { homeButton.setAnimation(fadeOut); homeButton.setVisibility(View.GONE); } if(bangButton.getVisibility()==View.GONE) { bangButton.setAnimation(fadeIn); bangButton.setVisibility(View.VISIBLE); } } public void setOverflowButton(boolean visible) { Animation fadeIn = AnimationUtils.loadAnimation(context, R.anim.actionbar_button_fade_in); Animation fadeOut = AnimationUtils.loadAnimation(context, R.anim.actionbar_button_fade_out); if(visible) { if(overflowButton.getVisibility()==View.GONE) { overflowButton.setAnimation(fadeIn); overflowButton.setVisibility(View.VISIBLE); } } else { if(overflowButton.getVisibility()==View.VISIBLE) { overflowButton.setAnimation(fadeOut); overflowButton.setVisibility(View.GONE); } } } private void setOverflowButtonMarginTop(boolean visible) { final RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) toolbar.findViewById(R.id.overflow).getLayoutParams(); int padding = visible ? (int) context.getResources().getDimension(R.dimen.actionbar_margin) : 0; params.topMargin = padding; } public void showTabLayout() { setTabLayout(true); } private void setTabLayout(boolean visible) { boolean gone = slidingTabLayout.getVisibility()==View.GONE; if(visible) { if(slidingTabLayout.getVisibility()==View.GONE) { expandView(slidingTabLayout); } } else { if(slidingTabLayout.getVisibility()==View.VISIBLE) { collapseView(slidingTabLayout); } } } public boolean isTabAnimating() { return isTabAnimating; } public void tryToShowTab() { if(!isTabAnimating && slidingTabLayout.getVisibility()!=View.VISIBLE) { expandView(slidingTabLayout); } } public void tryToHideTab() { if(!isTabAnimating && slidingTabLayout.getVisibility()!=View.GONE) { collapseView(slidingTabLayout); } } public void expandView(final View view) { view.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); final int standardMargin = (int) context.getResources().getDimension(R.dimen.actionbar_height); final int tabHeight = (int) context.getResources().getDimension(R.dimen.actionbar_tab_height2); final int actualMargin = standardMargin - tabHeight; view.setVisibility(View.VISIBLE); Animation a = new Animation() { @Override protected void applyTransformation(float interpolatedTime, Transformation t) { ((FrameLayout.LayoutParams)view.getLayoutParams()).topMargin = interpolatedTime == 1 ? standardMargin : (int) (actualMargin + (tabHeight * interpolatedTime)); view.requestLayout(); } @Override public boolean willChangeBounds() { return true; } }; a.setDuration(250); a.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { isTabAnimating = true; } @Override public void onAnimationEnd(Animation animation) { isTabAnimating = false; } @Override public void onAnimationRepeat(Animation animation) { } }); view.startAnimation(a); } public void collapseView(final View view) { final int standardMargin = (int) context.getResources().getDimension(R.dimen.actionbar_height); final int tabHeight = (int) context.getResources().getDimension(R.dimen.actionbar_tab_height2); Animation a = new Animation() { @Override protected void applyTransformation(float interpolatedTime, Transformation t) { if(interpolatedTime == 1){ view.setVisibility(View.GONE); }else{ ((FrameLayout.LayoutParams)view.getLayoutParams()).topMargin = standardMargin -(int)(tabHeight * interpolatedTime); view.requestLayout(); } } @Override public boolean willChangeBounds() { return true; } }; a.setDuration(250); a.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { isTabAnimating = true; } @Override public void onAnimationEnd(Animation animation) { isTabAnimating = false; } @Override public void onAnimationRepeat(Animation animation) { } }); view.startAnimation(a); view.getParent().requestLayout(); } public void setSearchBarText(String text) { if(text==null) { text = ""; } /* Disabled because it interferes with ACTION_WEB_SEARCH intent if(DDGControlVar.homeScreenShowing) { DDGControlVar.mDuckDuckGoContainer.currentUrl = ""; return; } */ DDGControlVar.mDuckDuckGoContainer.currentUrl = text; searchField.setFocusable(false); searchField.setFocusableInTouchMode(false); searchField.setText(DDGUtils.getUrlToDisplay(text)); searchField.setFocusable(true); searchField.setFocusableInTouchMode(true); } public void resetScreenState() { clearSearchBar(); DDGControlVar.currentFeedObject = null; DDGControlVar.mDuckDuckGoContainer.sessionType = SESSIONTYPE.SESSION_BROWSE; } public void showMenu(String tag) { overflowMenu = new DDGOverflowMenu(activity); overflowMenu.setMenu(mainMenu); overflowMenu.show(overflowButton); } public void dismissMenu() { if(overflowMenu!=null && overflowMenu.isShowing()) { overflowMenu.dismiss(); } } public class ProgressBarAnimation extends Animation { private ProgressBar progressBar; private float from; private float to; public ProgressBarAnimation(ProgressBar progressBar, float from, float to) { super(); this.progressBar = progressBar; this.from = from; this.to = to; progressBar.setProgress(0); } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { super.applyTransformation(interpolatedTime, t); float value = from + (to - from) * interpolatedTime; progressBar.setProgress((int) value); } } }