|
|
|
@ -23,7 +23,6 @@ import android.animation.AnimatorSet; |
|
|
|
|
import android.animation.ObjectAnimator; |
|
|
|
|
import android.animation.ValueAnimator; |
|
|
|
|
import android.content.Context; |
|
|
|
|
import android.content.res.Configuration; |
|
|
|
|
import android.graphics.drawable.Drawable; |
|
|
|
|
import android.os.Build; |
|
|
|
|
import android.text.Editable; |
|
|
|
@ -63,7 +62,7 @@ public class Toolbar extends LinearLayout implements View.OnClickListener, LoadV |
|
|
|
|
|
|
|
|
|
private ToolbarCallback callback; |
|
|
|
|
private NavigationItem navigationItem; |
|
|
|
|
private boolean search = false; |
|
|
|
|
private boolean openKeyboardAfterSearchViewCreated = false; |
|
|
|
|
|
|
|
|
|
public Toolbar(Context context) { |
|
|
|
|
super(context); |
|
|
|
@ -81,102 +80,20 @@ public class Toolbar extends LinearLayout implements View.OnClickListener, LoadV |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void updateNavigation() { |
|
|
|
|
closeSearchInternal(true); |
|
|
|
|
closeSearchInternal(); |
|
|
|
|
setNavigationItem(false, false, navigationItem); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public boolean showSearch() { |
|
|
|
|
if (!search) { |
|
|
|
|
search = true; |
|
|
|
|
|
|
|
|
|
LinearLayout searchViewWrapper = new LinearLayout(getContext()); |
|
|
|
|
final EditText searchView = new EditText(getContext()); |
|
|
|
|
searchView.setImeOptions(EditorInfo.IME_FLAG_NO_FULLSCREEN | EditorInfo.IME_ACTION_DONE); |
|
|
|
|
searchView.setHint(callback.getSearchHint()); |
|
|
|
|
searchView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); |
|
|
|
|
searchView.setHintTextColor(0x88ffffff); |
|
|
|
|
searchView.setTextColor(0xffffffff); |
|
|
|
|
searchView.setSingleLine(true); |
|
|
|
|
searchView.setBackgroundResource(0); |
|
|
|
|
searchView.setPadding(0, 0, 0, 0); |
|
|
|
|
final ImageView clearButton = new ImageView(getContext()); |
|
|
|
|
searchView.addTextChangedListener(new TextWatcher() { |
|
|
|
|
@Override |
|
|
|
|
public void onTextChanged(CharSequence s, int start, int before, int count) { |
|
|
|
|
callback.onSearchEntered(s.toString()); |
|
|
|
|
clearButton.setAlpha(s.length() == 0 ? 0.6f : 1.0f); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void afterTextChanged(Editable s) { |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
searchView.setOnEditorActionListener(new TextView.OnEditorActionListener() { |
|
|
|
|
@Override |
|
|
|
|
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { |
|
|
|
|
if (actionId == EditorInfo.IME_ACTION_DONE) { |
|
|
|
|
AndroidUtils.hideKeyboard(searchView); |
|
|
|
|
callback.onSearchEntered(searchView.getText().toString()); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
LinearLayout.LayoutParams searchViewParams = new LinearLayout.LayoutParams(0, dp(36), 1); |
|
|
|
|
searchViewParams.gravity = Gravity.CENTER_VERTICAL; |
|
|
|
|
searchViewWrapper.addView(searchView, searchViewParams); |
|
|
|
|
|
|
|
|
|
clearButton.setImageResource(R.drawable.ic_close_white_24dp); |
|
|
|
|
clearButton.setAlpha(0.6f); |
|
|
|
|
clearButton.setScaleType(ImageView.ScaleType.CENTER); |
|
|
|
|
clearButton.setOnClickListener(new OnClickListener() { |
|
|
|
|
@Override |
|
|
|
|
public void onClick(View v) { |
|
|
|
|
searchView.setText(""); |
|
|
|
|
AndroidUtils.requestKeyboardFocus(searchView); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
searchViewWrapper.addView(clearButton, dp(48), LayoutParams.MATCH_PARENT); |
|
|
|
|
searchViewWrapper.setPadding(dp(16), 0, 0, 0); |
|
|
|
|
|
|
|
|
|
searchView.post(new Runnable() { |
|
|
|
|
@Override |
|
|
|
|
public void run() { |
|
|
|
|
searchView.requestFocus(); |
|
|
|
|
AndroidUtils.requestKeyboardFocus(searchView); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
navigationItemContainer.setView(searchViewWrapper, true); |
|
|
|
|
animateArrow(true, 0); |
|
|
|
|
callback.onSearchVisibilityChanged(true); |
|
|
|
|
return true; |
|
|
|
|
} else { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
public boolean openSearch() { |
|
|
|
|
return openSearchInternal(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public boolean closeSearch() { |
|
|
|
|
return closeSearchInternal(false); |
|
|
|
|
return closeSearchInternal(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void setNavigationItem(final boolean animate, final boolean pushing, final NavigationItem item) { |
|
|
|
|
closeSearchInternal(true); |
|
|
|
|
if (item.menu != null) { |
|
|
|
|
AndroidUtils.waitForMeasure(this, new AndroidUtils.OnMeasuredCallback() { |
|
|
|
|
@Override |
|
|
|
|
public boolean onMeasured(View view) { |
|
|
|
|
setNavigationItemInternal(animate, pushing, false, item); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} else { |
|
|
|
|
setNavigationItemInternal(animate, pushing, false, item); |
|
|
|
|
} |
|
|
|
|
setNavigationItemInternal(animate, pushing, item); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void setCallback(ToolbarCallback callback) { |
|
|
|
@ -186,9 +103,7 @@ public class Toolbar extends LinearLayout implements View.OnClickListener, LoadV |
|
|
|
|
@Override |
|
|
|
|
public void onClick(View v) { |
|
|
|
|
if (v == arrowMenuView) { |
|
|
|
|
if (callback != null) { |
|
|
|
|
callback.onMenuOrBackClicked(arrowMenuDrawable.getProgress() == 1f); |
|
|
|
|
} |
|
|
|
|
callback.onMenuOrBackClicked(arrowMenuDrawable.getProgress() == 1f); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -196,9 +111,6 @@ public class Toolbar extends LinearLayout implements View.OnClickListener, LoadV |
|
|
|
|
arrowMenuDrawable.setProgress(progress); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void onConfigurationChanged(Configuration newConfig) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void onLoadViewRemoved(View view) { |
|
|
|
|
// TODO: this is kinda a hack
|
|
|
|
@ -207,6 +119,15 @@ public class Toolbar extends LinearLayout implements View.OnClickListener, LoadV |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void setTitle(NavigationItem navigationItem, String title) { |
|
|
|
|
if (navigationItem.view != null) { |
|
|
|
|
TextView titleView = (TextView) navigationItem.view.findViewById(R.id.title); |
|
|
|
|
if (titleView != null) { |
|
|
|
|
titleView.setText(title); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void init() { |
|
|
|
|
setOrientation(HORIZONTAL); |
|
|
|
|
|
|
|
|
@ -233,24 +154,47 @@ public class Toolbar extends LinearLayout implements View.OnClickListener, LoadV |
|
|
|
|
addView(navigationItemContainer, new LayoutParams(0, LayoutParams.MATCH_PARENT, 1f)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private boolean closeSearchInternal(boolean fromSetNavigation) { |
|
|
|
|
if (search) { |
|
|
|
|
search = false; |
|
|
|
|
setNavigationItemInternal(true, false, true, navigationItem); |
|
|
|
|
private boolean openSearchInternal() { |
|
|
|
|
if (!navigationItem.search) { |
|
|
|
|
navigationItem.search = true; |
|
|
|
|
openKeyboardAfterSearchViewCreated = true; |
|
|
|
|
setNavigationItem(true, true, navigationItem); |
|
|
|
|
setNavigationItemInternal(true, false, navigationItem); |
|
|
|
|
callback.onSearchVisibilityChanged(true); |
|
|
|
|
return true; |
|
|
|
|
} else { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private boolean closeSearchInternal() { |
|
|
|
|
if (navigationItem.search) { |
|
|
|
|
navigationItem.search = false; |
|
|
|
|
navigationItem.searchText = null; |
|
|
|
|
setNavigationItemInternal(true, false, navigationItem); |
|
|
|
|
AndroidUtils.hideKeyboard(navigationItemContainer); |
|
|
|
|
callback.onSearchVisibilityChanged(false); |
|
|
|
|
if (!fromSetNavigation) { |
|
|
|
|
animateArrow(navigationItem.hasBack, 0); |
|
|
|
|
} |
|
|
|
|
return true; |
|
|
|
|
} else { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void setNavigationItemInternal(boolean animate, boolean pushing, boolean fromSearch, NavigationItem toItem) { |
|
|
|
|
private void setNavigationItemInternal(boolean animate, boolean pushing, NavigationItem toItem) { |
|
|
|
|
final NavigationItem fromItem = navigationItem; |
|
|
|
|
|
|
|
|
|
boolean same = toItem == navigationItem; |
|
|
|
|
|
|
|
|
|
if (!toItem.search) { |
|
|
|
|
AndroidUtils.hideKeyboard(navigationItemContainer); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (fromItem != null) { |
|
|
|
|
fromItem.toolbar = null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
toItem.toolbar = this; |
|
|
|
|
|
|
|
|
|
if (!animate) { |
|
|
|
|
if (fromItem != null) { |
|
|
|
|
removeNavigationItem(fromItem); |
|
|
|
@ -261,7 +205,7 @@ public class Toolbar extends LinearLayout implements View.OnClickListener, LoadV |
|
|
|
|
toItem.view = createNavigationItemView(toItem); |
|
|
|
|
|
|
|
|
|
// use the LoadView animation when from a search
|
|
|
|
|
if (fromSearch) { |
|
|
|
|
if (same) { |
|
|
|
|
navigationItemContainer.setView(toItem.view, true); |
|
|
|
|
} else { |
|
|
|
|
navigationItemContainer.addView(toItem.view, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); |
|
|
|
@ -271,18 +215,16 @@ public class Toolbar extends LinearLayout implements View.OnClickListener, LoadV |
|
|
|
|
final int offset = dp(16); |
|
|
|
|
final int delay = pushing ? 0 : 100; |
|
|
|
|
|
|
|
|
|
if (animate) { |
|
|
|
|
animateArrow(toItem.hasBack || toItem.search, toItem.search ? 0 : delay); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Use the LoadView animation when from a search
|
|
|
|
|
if (animate && !fromSearch) { |
|
|
|
|
if (animate && !same) { |
|
|
|
|
toItem.view.setAlpha(0f); |
|
|
|
|
|
|
|
|
|
List<Animator> animations = new ArrayList<>(5); |
|
|
|
|
|
|
|
|
|
if (fromItem != null && fromItem.hasBack != toItem.hasBack) { |
|
|
|
|
animateArrow(toItem.hasBack, delay); |
|
|
|
|
} else { |
|
|
|
|
setArrowMenuProgress(toItem.hasBack ? 1f : 0f); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Animator toYAnimation = ObjectAnimator.ofFloat(toItem.view, View.TRANSLATION_Y, pushing ? offset : -offset, 0f); |
|
|
|
|
toYAnimation.setDuration(duration); |
|
|
|
|
toYAnimation.setInterpolator(new DecelerateInterpolator(2f)); |
|
|
|
@ -329,48 +271,121 @@ public class Toolbar extends LinearLayout implements View.OnClickListener, LoadV |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private LinearLayout createNavigationItemView(final NavigationItem item) { |
|
|
|
|
LinearLayout wrapper = (LinearLayout) LayoutInflater.from(getContext()).inflate(R.layout.toolbar_menu, null); |
|
|
|
|
wrapper.setGravity(Gravity.CENTER_VERTICAL); |
|
|
|
|
|
|
|
|
|
final TextView titleView = (TextView) wrapper.findViewById(R.id.title); |
|
|
|
|
titleView.setTypeface(AndroidUtils.ROBOTO_MEDIUM); |
|
|
|
|
titleView.setText(item.title); |
|
|
|
|
// black: titleView.setTextColor(Color.argb((int)(0.87 * 255.0), 0, 0, 0));
|
|
|
|
|
if (item.search) { |
|
|
|
|
LinearLayout searchViewWrapper = new LinearLayout(getContext()); |
|
|
|
|
final EditText searchView = new EditText(getContext()); |
|
|
|
|
searchView.setImeOptions(EditorInfo.IME_FLAG_NO_FULLSCREEN | EditorInfo.IME_ACTION_DONE); |
|
|
|
|
searchView.setHint(callback.getSearchHint()); |
|
|
|
|
if (item.searchText != null) { |
|
|
|
|
searchView.setText(item.searchText); |
|
|
|
|
} |
|
|
|
|
searchView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); |
|
|
|
|
searchView.setHintTextColor(0x88ffffff); |
|
|
|
|
searchView.setTextColor(0xffffffff); |
|
|
|
|
searchView.setSingleLine(true); |
|
|
|
|
searchView.setBackgroundResource(0); |
|
|
|
|
searchView.setPadding(0, 0, 0, 0); |
|
|
|
|
final ImageView clearButton = new ImageView(getContext()); |
|
|
|
|
searchView.addTextChangedListener(new TextWatcher() { |
|
|
|
|
@Override |
|
|
|
|
public void onTextChanged(CharSequence s, int start, int before, int count) { |
|
|
|
|
item.searchText = s.toString(); |
|
|
|
|
callback.onSearchEntered(s.toString()); |
|
|
|
|
clearButton.setAlpha(s.length() == 0 ? 0.6f : 1.0f); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (item.middleMenu != null) { |
|
|
|
|
item.middleMenu.setAnchor(titleView, Gravity.LEFT, dp(5), dp(5)); |
|
|
|
|
@Override |
|
|
|
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Drawable drawable = new DropdownArrowDrawable(); |
|
|
|
|
titleView.setCompoundDrawablesWithIntrinsicBounds(null, null, drawable, null); |
|
|
|
|
@Override |
|
|
|
|
public void afterTextChanged(Editable s) { |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
searchView.setOnEditorActionListener(new TextView.OnEditorActionListener() { |
|
|
|
|
@Override |
|
|
|
|
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { |
|
|
|
|
if (actionId == EditorInfo.IME_ACTION_DONE) { |
|
|
|
|
AndroidUtils.hideKeyboard(searchView); |
|
|
|
|
callback.onSearchEntered(searchView.getText().toString()); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
LinearLayout.LayoutParams searchViewParams = new LinearLayout.LayoutParams(0, dp(36), 1); |
|
|
|
|
searchViewParams.gravity = Gravity.CENTER_VERTICAL; |
|
|
|
|
searchViewWrapper.addView(searchView, searchViewParams); |
|
|
|
|
|
|
|
|
|
titleView.setOnClickListener(new OnClickListener() { |
|
|
|
|
clearButton.setImageResource(R.drawable.ic_close_white_24dp); |
|
|
|
|
clearButton.setAlpha(searchView.length() == 0 ? 0.6f : 1.0f); |
|
|
|
|
clearButton.setScaleType(ImageView.ScaleType.CENTER); |
|
|
|
|
clearButton.setOnClickListener(new OnClickListener() { |
|
|
|
|
@Override |
|
|
|
|
public void onClick(View v) { |
|
|
|
|
item.middleMenu.show(); |
|
|
|
|
searchView.setText(""); |
|
|
|
|
AndroidUtils.requestKeyboardFocus(searchView); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
searchViewWrapper.addView(clearButton, dp(48), LayoutParams.MATCH_PARENT); |
|
|
|
|
searchViewWrapper.setPadding(dp(16), 0, 0, 0); |
|
|
|
|
|
|
|
|
|
if (item.menu != null) { |
|
|
|
|
wrapper.addView(item.menu, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT)); |
|
|
|
|
} |
|
|
|
|
if (openKeyboardAfterSearchViewCreated) { |
|
|
|
|
openKeyboardAfterSearchViewCreated = false; |
|
|
|
|
searchView.post(new Runnable() { |
|
|
|
|
@Override |
|
|
|
|
public void run() { |
|
|
|
|
searchView.requestFocus(); |
|
|
|
|
AndroidUtils.requestKeyboardFocus(searchView); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (item.rightView != null) { |
|
|
|
|
item.rightView.setPadding(0, 0, dp(16), 0); |
|
|
|
|
wrapper.addView(item.rightView, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT)); |
|
|
|
|
} |
|
|
|
|
return searchViewWrapper; |
|
|
|
|
} else { |
|
|
|
|
LinearLayout menu = (LinearLayout) LayoutInflater.from(getContext()).inflate(R.layout.toolbar_menu, null); |
|
|
|
|
menu.setGravity(Gravity.CENTER_VERTICAL); |
|
|
|
|
|
|
|
|
|
AndroidUtils.waitForMeasure(titleView, new AndroidUtils.OnMeasuredCallback() { |
|
|
|
|
@Override |
|
|
|
|
public boolean onMeasured(View view) { |
|
|
|
|
if (item.middleMenu != null) { |
|
|
|
|
item.middleMenu.setPopupWidth(Math.max(dp(200), titleView.getWidth())); |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
final TextView titleView = (TextView) menu.findViewById(R.id.title); |
|
|
|
|
titleView.setTypeface(AndroidUtils.ROBOTO_MEDIUM); |
|
|
|
|
titleView.setText(item.title); |
|
|
|
|
// black: titleView.setTextColor(Color.argb((int)(0.87 * 255.0), 0, 0, 0));
|
|
|
|
|
|
|
|
|
|
if (item.middleMenu != null) { |
|
|
|
|
item.middleMenu.setAnchor(titleView, Gravity.LEFT, dp(5), dp(5)); |
|
|
|
|
|
|
|
|
|
Drawable drawable = new DropdownArrowDrawable(); |
|
|
|
|
titleView.setCompoundDrawablesWithIntrinsicBounds(null, null, drawable, null); |
|
|
|
|
|
|
|
|
|
titleView.setOnClickListener(new OnClickListener() { |
|
|
|
|
@Override |
|
|
|
|
public void onClick(View v) { |
|
|
|
|
item.middleMenu.show(); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (item.menu != null) { |
|
|
|
|
menu.addView(item.menu, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT)); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
return wrapper; |
|
|
|
|
if (item.rightView != null) { |
|
|
|
|
item.rightView.setPadding(0, 0, dp(16), 0); |
|
|
|
|
menu.addView(item.rightView, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
AndroidUtils.waitForMeasure(titleView, new AndroidUtils.OnMeasuredCallback() { |
|
|
|
|
@Override |
|
|
|
|
public boolean onMeasured(View view) { |
|
|
|
|
if (item.middleMenu != null) { |
|
|
|
|
item.middleMenu.setPopupWidth(Math.max(dp(200), titleView.getWidth())); |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
return menu; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void animateArrow(boolean toArrow, long delay) { |
|
|
|
|