下面列出了怎么用androidx.appcompat.widget.ActionMenuView的API类实例代码及写法,或者点击链接到github查看源代码。
public void showOverflowPrompt(View view)
{
final MaterialTapTargetPrompt.Builder tapTargetPromptBuilder = new MaterialTapTargetPrompt.Builder(this)
.setPrimaryText(R.string.overflow_prompt_title)
.setSecondaryText(R.string.overflow_prompt_description)
.setAnimationInterpolator(new FastOutSlowInInterpolator())
.setMaxTextWidth(R.dimen.tap_target_menu_max_width)
.setIcon(R.drawable.ic_more_vert);
final Toolbar tb = this.findViewById(R.id.toolbar);
final View child = tb.getChildAt(2);
if (child instanceof ActionMenuView)
{
final ActionMenuView actionMenuView = ((ActionMenuView) child);
tapTargetPromptBuilder.setTarget(actionMenuView.getChildAt(actionMenuView.getChildCount() - 1));
}
else
{
Toast.makeText(this, R.string.overflow_unavailable, Toast.LENGTH_SHORT).show();
}
tapTargetPromptBuilder.show();
}
public void showStylePrompt(View view)
{
final MaterialTapTargetPrompt.Builder builder = new MaterialTapTargetPrompt.Builder(this, R.style.MaterialTapTargetPromptTheme_FabTarget);
final Toolbar tb = this.findViewById(R.id.toolbar);
final View child = tb.getChildAt(2);
if (child instanceof ActionMenuView)
{
final ActionMenuView actionMenuView = ((ActionMenuView) child);
builder.setTarget(actionMenuView.getChildAt(actionMenuView.getChildCount() - 1));
}
else
{
Toast.makeText(this, R.string.overflow_unavailable, Toast.LENGTH_SHORT).show();
}
builder.setIcon(R.drawable.ic_more_vert)
.show();
}
public void showOverflowPrompt(View view)
{
final MaterialTapTargetPrompt.Builder tapTargetPromptBuilder = new MaterialTapTargetPrompt.Builder(this)
.setPrimaryText(R.string.overflow_prompt_title)
.setSecondaryText(R.string.overflow_prompt_description)
.setAnimationInterpolator(new FastOutSlowInInterpolator())
.setMaxTextWidth(R.dimen.max_prompt_width)
.setIcon(R.drawable.ic_more_vert)
.setClipToView(findViewById(R.id.dialog_view));
final Toolbar tb = this.findViewById(R.id.toolbar);
final View child = tb.getChildAt(2);
if (child instanceof ActionMenuView)
{
final ActionMenuView actionMenuView = ((ActionMenuView) child);
tapTargetPromptBuilder.setTarget(actionMenuView.getChildAt(actionMenuView.getChildCount() - 1));
}
else
{
Toast.makeText(this, R.string.overflow_unavailable, Toast.LENGTH_SHORT).show();
}
tapTargetPromptBuilder.show();
}
private void onGlobalLayout() {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
mToolbar.getViewTreeObserver().removeOnGlobalLayoutListener(mOnGlobalLayoutListener);
else
mToolbar.getViewTreeObserver().removeGlobalOnLayoutListener(mOnGlobalLayoutListener);
ActionMenuView menuView = getMenuView();
for(int i = 0, count = menuView == null ? 0 : menuView.getChildCount(); i < count; i++){
View child = menuView.getChildAt(i);
if(mRippleStyle != 0){
if(child.getBackground() == null || !(child.getBackground() instanceof ToolbarRippleDrawable))
ViewUtil.setBackground(child, getBackground());
}
}
if(mGroupChanged){
animateIn();
mGroupChanged = false;
}
}
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
super.addView(child, index, params);
if (child instanceof AppCompatImageButton) {
mThemeComponent.addColorProperty(R.attr.actionBarTextColorPrimary, (c) ->
ImageViewCompat.setImageTintList((ImageView) child, ColorStateList.valueOf(c)));
} else if (child instanceof ActionMenuView) {
mThemeComponent.addColorProperty(R.attr.actionBarTextColorPrimary, (c) -> {
ActionMenuView ch = (ActionMenuView) child;
Drawable d = DrawableCompat.wrap(ch.getOverflowIcon()).mutate();
DrawableCompat.setTint(d, c);
ch.setOverflowIcon(d);
});
}
}
public void setOverflowButtonColor(int color) {
ActionMenuView actionMenuView = ViewUtils.findChildByClass(this, ActionMenuView.class);
if (actionMenuView != null) {
Drawable overflowIcon = actionMenuView.getOverflowIcon();
if (overflowIcon != null) {
overflowIcon.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN));
}
}
}
@Test
public void applyOptions_appliesColorOnButtonTextView() {
MenuItem menuItem = buttonController.createAndAddButtonToTitleBar(titleBar, 0);
uut.applyOptions(titleBar, menuItem, buttonController::getView);
ShadowLooper.idleMainLooper();
List<TextView> textualButtons = ViewUtils.findChildrenByClass(
requireNonNull(ViewUtils.findChildByClass(titleBar, ActionMenuView.class)),
TextView.class,
child -> true
);
assertThat(textualButtons.get(0).getCurrentTextColor()).isEqualTo(Color.RED);
}
private TopBar mockTopBar() {
TopBar topBar = mock(TopBar.class);
Toolbar toolbar = new Toolbar(activity);
toolbar.addView(new ActionMenuView(activity));
when(topBar.getTitleBar()).then(invocation -> toolbar);
when(topBar.getContext()).then(invocation -> activity);
when(topBar.dispatchApplyWindowInsets(any())).then(invocation -> invocation.getArguments()[0]);
when(topBar.getLayoutParams()).thenReturn(new CoordinatorLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
return topBar;
}
@Test
public void setLayoutDirection_directionIsExplicitlyAppliedToButtonsContainer() {
ActionMenuView buttonsContainer = findChildByClass(uut, ActionMenuView.class);
assertNotNull(buttonsContainer);
ActionMenuView spy = TestUtils.spyOn(buttonsContainer);
uut.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
verify(spy).setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
}
public void setUpMenu(final ActionMenuView actionMenu, final DrawerLayout drawerLayout, final View bookmarksPanel) {
this.drawerLayout = drawerLayout;
this.bookmarksPanel = bookmarksPanel;
this.actionMenu = actionMenu;
actionMenu.setOnMenuItemClickListener(this);
// Enable special buttons
Menu menu = actionMenu.getMenu();
PackageManager pm = context.getPackageManager();
menu.findItem(R.id.action_backgroundPlay).setChecked(sp.getBoolean(BackgroundPlayHelper.PREF_BACKGROUND_PLAY_ENABLED, true));
menu.findItem(R.id.action_accept_cookies).setChecked(sp.getBoolean(PREF_COOKIES_ENABLED, true));
// Tor button
if (OrbotHelper.isOrbotInstalled(context.getApplicationContext())) {
menu.findItem(R.id.action_tor)
.setEnabled(true)
.setChecked(sp.getBoolean(TorHelper.PREF_TOR_ENABLED, false));
}
// Add Kodi button
try {
pm.getPackageInfo("org.xbmc.kore", PackageManager.GET_ACTIVITIES);
menu.findItem(R.id.action_cast_to_kodi).setEnabled(true);
} catch (PackageManager.NameNotFoundException e) {
/* Kodi is not installed */
}
}
@Nullable
private ActionMenuView getActionMenuView() {
for (int i = 0; i < getChildCount(); i++) {
View view = getChildAt(i);
if (view instanceof ActionMenuView) {
return (ActionMenuView) view;
}
}
return null;
}
/**
* Returns the X translation to position the {@link ActionMenuView}. When {@code fabAlignmentMode}
* is equal to {@link #FAB_ALIGNMENT_MODE_END} and {@code fabAttached} is true, the {@link
* ActionMenuView} will be aligned to the end of the navigation icon, otherwise the {@link
* ActionMenuView} is not moved.
*/
protected int getActionMenuViewTranslationX(
@NonNull ActionMenuView actionMenuView,
@FabAlignmentMode int fabAlignmentMode,
boolean fabAttached) {
if (fabAlignmentMode != FAB_ALIGNMENT_MODE_END || !fabAttached) {
return 0;
}
boolean isRtl = ViewUtils.isLayoutRtl(this);
int toolbarLeftContentEnd = isRtl ? getMeasuredWidth() : 0;
// Calculate the inner side of the Toolbar's Gravity.START contents.
for (int i = 0; i < getChildCount(); i++) {
View view = getChildAt(i);
boolean isAlignedToStart =
view.getLayoutParams() instanceof Toolbar.LayoutParams
&& (((Toolbar.LayoutParams) view.getLayoutParams()).gravity
& Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK)
== Gravity.START;
if (isAlignedToStart) {
toolbarLeftContentEnd =
isRtl
? Math.min(toolbarLeftContentEnd, view.getLeft())
: Math.max(toolbarLeftContentEnd, view.getRight());
}
}
int actionMenuViewStart = isRtl ? actionMenuView.getRight() : actionMenuView.getLeft();
int systemStartInset = isRtl ? rightInset : -leftInset;
int end = actionMenuViewStart + systemStartInset;
return toolbarLeftContentEnd - end;
}
private void setActionMenuViewPosition() {
ActionMenuView actionMenuView = getActionMenuView();
// If the menu is null there is no need to translate it. If the menu is currently being
// animated, the menuAnimator will take care of re-positioning the menu if necessary.
if (actionMenuView != null && menuAnimator == null) {
actionMenuView.setAlpha(1.0f);
if (!isFabVisibleOrWillBeShown()) {
translateActionMenuView(actionMenuView, FAB_ALIGNMENT_MODE_CENTER, false);
} else {
translateActionMenuView(actionMenuView, fabAlignmentMode, fabAttached);
}
}
}
public void setUpMenu(final ActionMenuView actionMenu, final DrawerLayout drawerLayout, final View bookmarksPanel) {
this.drawerLayout = drawerLayout;
this.bookmarksPanel = bookmarksPanel;
this.actionMenu = actionMenu;
actionMenu.setOnMenuItemClickListener(this);
// Enable special buttons
Menu menu = actionMenu.getMenu();
PackageManager pm = context.getPackageManager();
menu.findItem(R.id.action_backgroundPlay).setChecked(sp.getBoolean(BackgroundPlayHelper.PREF_BACKGROUND_PLAY_ENABLED, true));
menu.findItem(R.id.action_accept_cookies).setChecked(sp.getBoolean(PREF_COOKIES_ENABLED, true));
// Tor button
if (OrbotHelper.isOrbotInstalled(context.getApplicationContext())) {
menu.findItem(R.id.action_tor)
.setEnabled(true)
.setChecked(sp.getBoolean(TorHelper.PREF_TOR_ENABLED, false));
}
// Add Kodi button
try {
pm.getPackageInfo("org.xbmc.kore", PackageManager.GET_ACTIVITIES);
menu.findItem(R.id.action_cast_to_kodi).setEnabled(true);
} catch (PackageManager.NameNotFoundException e) {
/* Kodi is not installed */
}
}
private void animateIn(){
ActionMenuView menuView = getMenuView();
for(int i = 0, count = menuView == null ? 0 : menuView.getChildCount(); i < count; i++){
View child = menuView.getChildAt(i);
Animation anim = mAnimator.getInAnimation(child, i);
if(anim != null)
child.startAnimation(anim);
}
}
private void animateNavigationIn(long time){
mAnimTime = time;
cancelAllAnimations();
mToolbar.setNavigationIcon(null);
doOnPreDraw(mToolbar, new AnimRunnable(time) {
@Override
void doWork() {
final ViewData viewData = new ViewData(mToolbar);
mToolbar.setNavigationIcon(mNavigationIcon);
doOnPreDraw(mToolbar, new AnimRunnable(mTime) {
@Override
void doWork() {
for (int i = 0, count = mToolbar.getChildCount(); i < count; i++) {
View child = mToolbar.getChildAt(i);
if (!(child instanceof ActionMenuView)) {
int prevLeft = viewData.getLeft(child);
if (prevLeft < 0)
prevLeft = -child.getLeft() - child.getWidth();
animateViewIn(child, prevLeft);
}
}
}
});
}
});
}
public ViewData(Toolbar toolbar){
int count = toolbar.getChildCount();
views = new ArrayList<>(count);
lefts = new ArrayList<>(count);
for(int i = 0; i < count; i++){
View child = toolbar.getChildAt(i);
if(!(child instanceof ActionMenuView)) {
views.add(child);
lefts.add(child.getLeft());
}
}
}
/**
* Use this method to colorize toolbar icons to the desired target color
*
* @param toolbarView toolbar view being colored
* @param toolbarIconsColor the target color of toolbar icons
* @param activity reference to activity needed to register observers
*/
public static void colorizeToolbar(@NonNull Toolbar toolbarView, int toolbarIconsColor, @NonNull Activity activity) {
final PorterDuffColorFilter colorFilter = new PorterDuffColorFilter(toolbarIconsColor, PorterDuff.Mode.MULTIPLY);
for (int i = 0; i < toolbarView.getChildCount(); i++) {
final View v = toolbarView.getChildAt(i);
//Step 1 : Changing the color of back button (or open drawer button).
if (v instanceof ImageButton) {
//Action Bar back button
((ImageButton) v).getDrawable().setColorFilter(colorFilter);
}
if (v instanceof ActionMenuView) {
for (int j = 0; j < ((ActionMenuView) v).getChildCount(); j++) {
//Step 2: Changing the color of any ActionMenuViews - icons that are not back button, nor text, nor overflow menu icon.
//Colorize the ActionViews -> all icons that are NOT: back button | overflow menu
final View innerView = ((ActionMenuView) v).getChildAt(j);
if (innerView instanceof ActionMenuItemView) {
for (int k = 0; k < ((ActionMenuItemView) innerView).getCompoundDrawables().length; k++) {
if (((ActionMenuItemView) innerView).getCompoundDrawables()[k] != null) {
final int finalK = k;
//Important to set the color filter in seperate thread, by adding it to the message queue
//Won't work otherwise.
innerView.post(new Runnable() {
@Override
public void run() {
Drawable drawable = ((ActionMenuItemView) innerView).getCompoundDrawables()[finalK];
if (drawable != null) {
drawable.setColorFilter(colorFilter);
}
}
});
}
}
}
}
}
//Step 3: Changing the color of title and subtitle.
toolbarView.setTitleTextColor(toolbarIconsColor);
toolbarView.setSubtitleTextColor(toolbarIconsColor);
}
}
@Override
public void setLayoutDirection(int layoutDirection) {
super.setLayoutDirection(layoutDirection);
perform(findChildByClass(this, ActionMenuView.class), buttonsContainer -> buttonsContainer.setLayoutDirection(layoutDirection));
}
private void enableOverflowForReactButtonViews(View child) {
if (child instanceof ActionMenuView) {
((ViewGroup) child).setClipChildren(false);
}
}
@Test
public void addView_overflowIsEnabledForButtonsContainer() {
ActionMenuView buttonsContainer = mock(ActionMenuView.class);
uut.addView(buttonsContainer);
verify(buttonsContainer).setClipChildren(false);
}
private void animateNavigationOut(long time){
mAnimTime = time;
cancelAllAnimations();
mToolbar.setNavigationIcon(null);
doOnPreDraw(mToolbar, new AnimRunnable(time) {
@Override
void doWork() {
final ViewData viewData = new ViewData(mToolbar);
mToolbar.setNavigationIcon(mNavigationIcon);
doOnPreDraw(mToolbar, new AnimRunnable(mTime) {
@Override
void doWork() {
boolean first = true;
for (int i = 0, count = mToolbar.getChildCount(); i < count; i++) {
View child = mToolbar.getChildAt(i);
if (!(child instanceof ActionMenuView)) {
int nextLeft = viewData.getLeft(child);
if (nextLeft < 0)
nextLeft = -child.getLeft() - child.getWidth();
if (first) {
animateViewOut(child, nextLeft, new Runnable() {
@Override
public void run() {
mToolbar.setNavigationIcon(null);
mNavigationIcon.cancel();
}
});
first = false;
} else
animateViewOut(child, nextLeft, null);
}
}
if (first)
mToolbar.setNavigationIcon(null);
}
});
}
});
}
/**
* Translates the ActionMenuView so that it is aligned correctly depending on the fabAlignmentMode
* and if the fab is attached. The view will be translated to the left when the fab is attached
* and on the end. Otherwise it will be in its normal position.
*
* @param actionMenuView the ActionMenuView to translate
* @param fabAlignmentMode the fabAlignmentMode used to determine the position of the
* ActionMenuView
* @param fabAttached whether the ActionMenuView should be moved
*/
private void translateActionMenuView(
@NonNull ActionMenuView actionMenuView,
@FabAlignmentMode int fabAlignmentMode,
boolean fabAttached) {
actionMenuView.setTranslationX(
getActionMenuViewTranslationX(actionMenuView, fabAlignmentMode, fabAttached));
}