From 82a9f2296eab23ba6487342ce15b217b043514de Mon Sep 17 00:00:00 2001 From: Aris Tetradis Date: Thu, 14 Sep 2017 18:29:50 +0300 Subject: [PATCH] Support ActionBarDrawerToggle with DrawerArrowDrawable. --- .../slidingrootnav/SlidingRootNav.java | 3 + .../slidingrootnav/SlidingRootNavBuilder.java | 4 +- .../slidingrootnav/SlidingRootNavLayout.java | 23 +++- .../util/BadgeDrawerArrowDrawable.java | 105 ++++++++++++++++++ .../util/BadgeDrawerToggle.java | 92 +++++++++++++++ .../slidingrootnav/sample/SampleActivity.java | 5 +- 6 files changed, 227 insertions(+), 5 deletions(-) create mode 100644 library/src/main/java/com/yarolegovich/slidingrootnav/util/BadgeDrawerArrowDrawable.java create mode 100644 library/src/main/java/com/yarolegovich/slidingrootnav/util/BadgeDrawerToggle.java diff --git a/library/src/main/java/com/yarolegovich/slidingrootnav/SlidingRootNav.java b/library/src/main/java/com/yarolegovich/slidingrootnav/SlidingRootNav.java index d6e46dd..ce458d8 100644 --- a/library/src/main/java/com/yarolegovich/slidingrootnav/SlidingRootNav.java +++ b/library/src/main/java/com/yarolegovich/slidingrootnav/SlidingRootNav.java @@ -1,5 +1,7 @@ package com.yarolegovich.slidingrootnav; +import com.yarolegovich.slidingrootnav.util.BadgeDrawerToggle; + /** * Created by yarolegovich on 25.03.2017. */ @@ -24,4 +26,5 @@ public interface SlidingRootNav { SlidingRootNavLayout getLayout(); + BadgeDrawerToggle getBadgeDrawerToggle(); } diff --git a/library/src/main/java/com/yarolegovich/slidingrootnav/SlidingRootNavBuilder.java b/library/src/main/java/com/yarolegovich/slidingrootnav/SlidingRootNavBuilder.java index a734be3..5401fa5 100644 --- a/library/src/main/java/com/yarolegovich/slidingrootnav/SlidingRootNavBuilder.java +++ b/library/src/main/java/com/yarolegovich/slidingrootnav/SlidingRootNavBuilder.java @@ -19,6 +19,7 @@ import com.yarolegovich.slidingrootnav.transform.ScaleTransformation; import com.yarolegovich.slidingrootnav.transform.YTranslationTransformation; import com.yarolegovich.slidingrootnav.util.ActionBarToggleAdapter; +import com.yarolegovich.slidingrootnav.util.BadgeDrawerToggle; import com.yarolegovich.slidingrootnav.util.DrawerListenerAdapter; import com.yarolegovich.slidingrootnav.util.HiddenMenuClickConsumer; @@ -248,9 +249,10 @@ protected void initToolbarMenuVisibilityToggle(final SlidingRootNavLayout sideNa if (toolbar != null) { ActionBarToggleAdapter dlAdapter = new ActionBarToggleAdapter(activity); dlAdapter.setAdaptee(sideNav); - ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(activity, dlAdapter, toolbar, + BadgeDrawerToggle toggle = new BadgeDrawerToggle(activity, dlAdapter, toolbar, R.string.srn_drawer_open, R.string.srn_drawer_close); + sideNav.setActionBarDrawerToggle(toggle); toggle.syncState(); DrawerListenerAdapter listenerAdapter = new DrawerListenerAdapter(toggle, drawer); sideNav.addDragListener(listenerAdapter); diff --git a/library/src/main/java/com/yarolegovich/slidingrootnav/SlidingRootNavLayout.java b/library/src/main/java/com/yarolegovich/slidingrootnav/SlidingRootNavLayout.java index 8bb31bd..ba3062c 100644 --- a/library/src/main/java/com/yarolegovich/slidingrootnav/SlidingRootNavLayout.java +++ b/library/src/main/java/com/yarolegovich/slidingrootnav/SlidingRootNavLayout.java @@ -6,6 +6,7 @@ import android.os.Parcelable; import android.support.v4.view.ViewCompat; import android.support.v4.widget.ViewDragHelper; +import android.support.v7.app.ActionBarDrawerToggle; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; @@ -14,6 +15,7 @@ import com.yarolegovich.slidingrootnav.callback.DragListener; import com.yarolegovich.slidingrootnav.callback.DragStateListener; import com.yarolegovich.slidingrootnav.transform.RootTransformation; +import com.yarolegovich.slidingrootnav.util.BadgeDrawerToggle; import java.util.ArrayList; import java.util.List; @@ -47,6 +49,7 @@ public class SlidingRootNavLayout extends FrameLayout implements SlidingRootNav private List dragListeners; private List dragStateListeners; + private ActionBarDrawerToggle actionBarDrawerToggle; public SlidingRootNavLayout(Context context) { super(context); @@ -64,8 +67,8 @@ public SlidingRootNavLayout(Context context) { @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return (!isMenuLocked - && dragHelper.shouldInterceptTouchEvent(ev)) - || shouldBlockClick(ev); + && dragHelper.shouldInterceptTouchEvent(ev)) + || shouldBlockClick(ev); } @Override @@ -113,7 +116,8 @@ public boolean isMenuClosed() { return isMenuHidden; } - @Override public boolean isMenuOpened() { + @Override + public boolean isMenuOpened() { return !isMenuHidden; } @@ -122,6 +126,15 @@ public SlidingRootNavLayout getLayout() { return this; } + @Override + public BadgeDrawerToggle getBadgeDrawerToggle() { + if (actionBarDrawerToggle instanceof BadgeDrawerToggle) { + return (BadgeDrawerToggle) actionBarDrawerToggle; + } else { + return null; + } + } + @Override public boolean isMenuLocked() { return isMenuLocked; @@ -246,6 +259,10 @@ private boolean calculateIsMenuHidden() { return dragProgress == 0f; } + public void setActionBarDrawerToggle(BadgeDrawerToggle actionBarDrawerToggle) { + this.actionBarDrawerToggle = actionBarDrawerToggle; + } + private class ViewDragCallback extends ViewDragHelper.Callback { private boolean edgeTouched; diff --git a/library/src/main/java/com/yarolegovich/slidingrootnav/util/BadgeDrawerArrowDrawable.java b/library/src/main/java/com/yarolegovich/slidingrootnav/util/BadgeDrawerArrowDrawable.java new file mode 100644 index 0000000..b7f4e69 --- /dev/null +++ b/library/src/main/java/com/yarolegovich/slidingrootnav/util/BadgeDrawerArrowDrawable.java @@ -0,0 +1,105 @@ +package com.yarolegovich.slidingrootnav.util; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.Typeface; +import android.support.v7.graphics.drawable.DrawerArrowDrawable; + +/** + * Original source: https://stackoverflow.com/a/43886113 + */ +public class BadgeDrawerArrowDrawable extends DrawerArrowDrawable { + + // Fraction of the drawable's intrinsic size we want the badge to be. + private static final float SIZE_FACTOR = .3f; + private static final float HALF_SIZE_FACTOR = SIZE_FACTOR / 2; + + private Paint backgroundPaint; + private Paint textPaint; + private String text; + private boolean enabled = true; + + public BadgeDrawerArrowDrawable(Context context) { + super(context); + + backgroundPaint = new Paint(); + backgroundPaint.setColor(Color.RED); + backgroundPaint.setAntiAlias(true); + + textPaint = new Paint(); + textPaint.setColor(Color.WHITE); + textPaint.setAntiAlias(true); + textPaint.setTypeface(Typeface.DEFAULT_BOLD); + textPaint.setTextAlign(Paint.Align.CENTER); + textPaint.setTextSize(SIZE_FACTOR * getIntrinsicHeight()); + } + + @Override + public void draw(Canvas canvas) { + super.draw(canvas); + + if (!enabled) { + return; + } + + final Rect bounds = getBounds(); + final float x = (1 - HALF_SIZE_FACTOR) * bounds.width(); + final float y = HALF_SIZE_FACTOR * bounds.height(); + canvas.drawCircle(x, y, SIZE_FACTOR * bounds.width(), backgroundPaint); + + if (text == null || text.length() == 0) { + return; + } + + final Rect textBounds = new Rect(); + textPaint.getTextBounds(text, 0, text.length(), textBounds); + canvas.drawText(text, x, y + textBounds.height() / 2, textPaint); + } + + public void setEnabled(boolean enabled) { + if (this.enabled != enabled) { + this.enabled = enabled; + invalidateSelf(); + } + } + + public boolean isEnabled() { + return enabled; + } + + public void setText(String text) { + if (this.text == null || !this.text.equals(text)) { + this.text = text; + invalidateSelf(); + } + } + + public String getText() { + return text; + } + + public void setBackgroundColor(int color) { + if (backgroundPaint.getColor() != color) { + backgroundPaint.setColor(color); + invalidateSelf(); + } + } + + public int getBackgroundColor() { + return backgroundPaint.getColor(); + } + + public void setTextColor(int color) { + if (textPaint.getColor() != color) { + textPaint.setColor(color); + invalidateSelf(); + } + } + + public int getTextColor() { + return textPaint.getColor(); + } +} \ No newline at end of file diff --git a/library/src/main/java/com/yarolegovich/slidingrootnav/util/BadgeDrawerToggle.java b/library/src/main/java/com/yarolegovich/slidingrootnav/util/BadgeDrawerToggle.java new file mode 100644 index 0000000..3bb1ded --- /dev/null +++ b/library/src/main/java/com/yarolegovich/slidingrootnav/util/BadgeDrawerToggle.java @@ -0,0 +1,92 @@ +package com.yarolegovich.slidingrootnav.util; + +import android.app.Activity; +import android.content.Context; +import android.support.v4.widget.DrawerLayout; +import android.support.v7.app.ActionBarDrawerToggle; +import android.support.v7.widget.Toolbar; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +/** + * Original source: https://stackoverflow.com/a/43886113 + */ +public class BadgeDrawerToggle extends ActionBarDrawerToggle { + + private BadgeDrawerArrowDrawable badgeDrawable; + + public BadgeDrawerToggle(Activity activity, DrawerLayout drawerLayout, + int openDrawerContentDescRes, + int closeDrawerContentDescRes) { + super(activity, drawerLayout, openDrawerContentDescRes, + closeDrawerContentDescRes); + init(activity); + } + + public BadgeDrawerToggle(Activity activity, DrawerLayout drawerLayout, + Toolbar toolbar, int openDrawerContentDescRes, + int closeDrawerContentDescRes) { + super(activity, drawerLayout, toolbar, openDrawerContentDescRes, + closeDrawerContentDescRes); + init(activity); + } + + private void init(Activity activity) { + Context c = getThemedContext(); + if (c == null) { + c = activity; + } + badgeDrawable = new BadgeDrawerArrowDrawable(c); + setDrawerArrowDrawable(badgeDrawable); + } + + public void setBadgeEnabled(boolean enabled) { + badgeDrawable.setEnabled(enabled); + } + + public boolean isBadgeEnabled() { + return badgeDrawable.isEnabled(); + } + + public void setBadgeText(String text) { + badgeDrawable.setText(text); + } + + public String getBadgeText() { + return badgeDrawable.getText(); + } + + public void setBadgeColor(int color) { + badgeDrawable.setBackgroundColor(color); + } + + public int getBadgeColor() { + return badgeDrawable.getBackgroundColor(); + } + + public void setBadgeTextColor(int color) { + badgeDrawable.setTextColor(color); + } + + public int getBadgeTextColor() { + return badgeDrawable.getTextColor(); + } + + private Context getThemedContext() { + // Don't freak about the reflection. ActionBarDrawerToggle + // itself is already using reflection internally. + try { + Field mActivityImplField = ActionBarDrawerToggle.class + .getDeclaredField("mActivityImpl"); + mActivityImplField.setAccessible(true); + Object mActivityImpl = mActivityImplField.get(this); + Method getActionBarThemedContextMethod = mActivityImpl.getClass() + .getDeclaredMethod("getActionBarThemedContext"); + return (Context) getActionBarThemedContextMethod.invoke(mActivityImpl); + } + catch (Exception e) { + return null; + } + } +} \ No newline at end of file diff --git a/sample/src/main/java/com/yarolegovich/slidingrootnav/sample/SampleActivity.java b/sample/src/main/java/com/yarolegovich/slidingrootnav/sample/SampleActivity.java index 1c88f6b..0e8c4b3 100644 --- a/sample/src/main/java/com/yarolegovich/slidingrootnav/sample/SampleActivity.java +++ b/sample/src/main/java/com/yarolegovich/slidingrootnav/sample/SampleActivity.java @@ -15,11 +15,11 @@ import com.yarolegovich.slidingrootnav.SlidingRootNav; import com.yarolegovich.slidingrootnav.SlidingRootNavBuilder; +import com.yarolegovich.slidingrootnav.sample.fragment.CenteredTextFragment; import com.yarolegovich.slidingrootnav.sample.menu.DrawerAdapter; import com.yarolegovich.slidingrootnav.sample.menu.DrawerItem; import com.yarolegovich.slidingrootnav.sample.menu.SimpleItem; import com.yarolegovich.slidingrootnav.sample.menu.SpaceItem; -import com.yarolegovich.slidingrootnav.sample.fragment.CenteredTextFragment; import java.util.Arrays; @@ -84,6 +84,9 @@ public void onItemSelected(int position) { slidingRootNav.closeMenu(); Fragment selectedScreen = CenteredTextFragment.createFor(screenTitles[position]); showFragment(selectedScreen); + + slidingRootNav.getBadgeDrawerToggle().setBadgeEnabled(position != POS_DASHBOARD); + slidingRootNav.getBadgeDrawerToggle().setBadgeText(String.valueOf(position)); } private void showFragment(Fragment fragment) {