web-dev-qa-db-fra.com

Notification de badge sur la bascule du tiroir dans la barre d'outils - Android

Je souhaite informer l'utilisateur du nouveau message non lu dans l'application, accessible via le tiroir de navigation. Je pensais au badge de notification quelque chose de similaire à Apple mais avec un tiroir dans la barre d’outils.

C'est ce que j'ai maintenant:  This is what I have now

C'est ce que je veux:  This is what I want

Comment puis-je y arriver?

16
Soriyyx

 enter image description here

 enter image description here

J'ai trouvé cette classe BadgeDrawable vraiment cool sur Internet et vous pouvez ajouter un nombre de badges à n'importe quel tirage utilisant cette classe. Veuillez suivre les étapes ci-dessous.

Étape 1: ajoutez d'abord la classe ci-dessous à votre projet.

import Android.content.Context;
import Android.content.res.Resources;
import Android.graphics.Canvas;
import Android.graphics.Color;
import Android.graphics.ColorFilter;
import Android.graphics.Paint;
import Android.graphics.PixelFormat;
import Android.graphics.Rect;
import Android.graphics.Typeface;
import Android.graphics.drawable.Drawable;
import Android.util.TypedValue;


/**
 * Created by Admin on 2/25/2016.
 */
public class BadgeDrawable extends Drawable {

    private float mTextSize;
    private Paint mBadgePaint;
    private Paint mBadgePaint1;
    private Paint mTextPaint;
    private Rect mTxtRect = new Rect();

    private String mCount = "";
    private boolean mWillDraw = false;


    public BadgeDrawable(Context context) {
        mTextSize = dpToPx(context, 8); //text size
        mBadgePaint = new Paint();
        mBadgePaint.setColor(Color.RED);
        mBadgePaint.setAntiAlias(true);
        mBadgePaint.setStyle(Paint.Style.FILL);
        mBadgePaint1 = new Paint();
        mBadgePaint1.setColor(Color.parseColor("#EEEEEE"));
        mBadgePaint1.setAntiAlias(true);
        mBadgePaint1.setStyle(Paint.Style.FILL);

        mTextPaint = new Paint();
        mTextPaint.setColor(Color.WHITE);
        mTextPaint.setTypeface(Typeface.DEFAULT);
        mTextPaint.setTextSize(mTextSize);
        mTextPaint.setAntiAlias(true);
        mTextPaint.setTextAlign(Paint.Align.CENTER);
    }

    private float dpToPx(Context context, float value) {
        Resources r = context.getResources();
        float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, r.getDisplayMetrics());
        return px;
    }


    @Override
    public void draw(Canvas canvas) {
        if (!mWillDraw) {
            return;
        }
        Rect bounds = getBounds();
        float width = bounds.right - bounds.left;
        float height = bounds.bottom - bounds.top;
        // Position the badge in the top-right quadrant of the icon.

  /*Using Math.max rather than Math.min */
//        float radius = ((Math.max(width, height) / 2)) / 2;
        float radius = width * 0.15f;
        float centerX = (width - radius - 1) +10;
        float centerY = radius -5;
        if(mCount.length() <= 2){
            // Draw badge circle.
            canvas.drawCircle(centerX, centerY, radius+9, mBadgePaint1);
            canvas.drawCircle(centerX, centerY, radius+7, mBadgePaint);
        }
        else{
            canvas.drawCircle(centerX, centerY, radius+10, mBadgePaint1);
            canvas.drawCircle(centerX, centerY, radius+8, mBadgePaint);
        }
        // Draw badge count text inside the circle.
        mTextPaint.getTextBounds(mCount, 0, mCount.length(), mTxtRect);
        float textHeight = mTxtRect.bottom - mTxtRect.top;
        float textY = centerY + (textHeight / 2f);
        if(mCount.length() > 2)
        canvas.drawText("99+", centerX, textY, mTextPaint);
        else
        canvas.drawText(mCount, centerX, textY, mTextPaint);
    }

    /*
     Sets the count (i.e notifications) to display.
      */
    public void setCount(String count) {
        mCount = count;
        // Only draw a badge if there are notifications.
        mWillDraw = !count.equalsIgnoreCase("0");
        invalidateSelf();
    }

    @Override
    public void setAlpha(int alpha) {
        // do nothing
    }

    @Override
    public void setColorFilter(ColorFilter cf) {
        // do nothing
    }

    @Override
    public int getOpacity() {
        return PixelFormat.UNKNOWN;
    }
}

Étape 2: Créez maintenant un dessin (dans mon cas, il s'agit de ic_badge_drawable.xml). Ensuite, copiez et collez ci-dessous le texte XML.

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:Android="http://schemas.Android.com/apk/res/Android">

    <item Android:id="@+id/ic_main_icon"
        Android:drawable="@drawable/ic_burger"
        Android:gravity="center" />


    <!-- set a place holder Drawable so Android:drawable isn't null -->
    <item Android:id="@+id/ic_badge"
        Android:drawable="@drawable/ic_burger" />
</layer-list>

ici, vous pouvez passer n'importe quel tirage pour le moment, plus tard, nous pouvons passer le tirage à ceux-ci. Ce sont juste comme des détenteurs de place.

Étape 3: Nous avons déjà tout configuré. Vous pouvez maintenant utiliser la méthode ci-dessous pour définir le nombre de badges pour tous les tirables.

 private Drawable setBadgeCount(Context context, int res, int badgeCount){
        LayerDrawable icon = (LayerDrawable) ContextCompat.getDrawable(context, R.drawable.ic_badge_drawable);
        Drawable mainIcon = ContextCompat.getDrawable(context, res);
        BadgeDrawable badge = new BadgeDrawable(context);
        badge.setCount(String.valueOf(badgeCount));
        icon.mutate();
        icon.setDrawableByLayerId(R.id.ic_badge, badge);
        icon.setDrawableByLayerId(R.id.ic_main_icon, mainIcon);

        return icon;
    }

Étape 4: Je l’ai utilisé comme ci-dessous pour changer l’icône de mon hamburger par défaut.

setSupportActionBar(toolbar);
getSupportActionBar().setHomeAsUpIndicator(setBadgeCount(this,R.drawable.ic_burger, 3));
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowCustomEnabled(true);   // enable overriding the default toolbar layout
getSupportActionBar().setDisplayShowTitleEnabled(false);// disable the default title element here (for centered title)
14
TdSoft

 enter image description here

J'ai utilisé TextView simple dans Android.support.design.widget.AppBarLayout, veuillez vérifier le code complet ci-dessous.

MainActivity.Java

import Android.os.Bundle;
import Android.support.v4.view.GravityCompat;
import Android.support.v4.widget.DrawerLayout;
import Android.support.v7.app.ActionBar;
import Android.support.v7.app.AppCompatActivity;
import Android.support.v7.widget.Toolbar;
import Android.view.Menu;
import Android.widget.TextView;

public class MainActivity extends AppCompatActivity {

     private DrawerLayout mDrawerLayout;

     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
         initViews();
     }

     private void initViews() {
         mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
         setUpToolbar();
     }

     private void setUpToolbar() {
         Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
         setSupportActionBar(toolbar);
         final ActionBar ab = getSupportActionBar();
         ab.setHomeAsUpIndicator(R.drawable.navigation_drawericon);
         ab.setDisplayHomeAsUpEnabled(true);
     }

     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         getMenuInflater().inflate(R.menu.home_menu, menu);
         return true;
     }

     @Override
     public boolean onOptionsItemSelected(Android.view.MenuItem item) {
         switch (item.getItemId()) {
             case Android.R.id.home:
                 mDrawerLayout.openDrawer(GravityCompat.START);
                 return true;
         }
         return super.onOptionsItemSelected(item);
     }

     private void updateCounter(int count) {
         ((TextView) findViewById(R.id.tv_nav_drawer_count)).setText(count + "");
     }

     public void closeDrawer() {
         mDrawerLayout.closeDrawers();
     }
  }

activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <Android.support.v4.widget.DrawerLayout
        xmlns:Android="http://schemas.Android.com/apk/res/Android"
        Android:id="@+id/drawer_layout"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:background="@Android:color/white"
        Android:fitsSystemWindows="true">

        <include layout="@layout/container_layout"/>

        <Android.support.design.widget.NavigationView
            Android:id="@+id/navigation_view"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:layout_gravity="start"
            Android:fitsSystemWindows="true">

        </Android.support.design.widget.NavigationView>


    </Android.support.v4.widget.DrawerLayout>

conteneur_layout.xml

<Android.support.design.widget.CoordinatorLayout
            xmlns:Android="http://schemas.Android.com/apk/res/Android"
            xmlns:app="http://schemas.Android.com/apk/res-auto"
            Android:id="@+id/main_content"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent">

            <Android.support.design.widget.AppBarLayout
                Android:id="@+id/appbar"
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content"
                Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

                <Android.support.v7.widget.Toolbar
                    Android:id="@+id/toolbar"
                    Android:layout_width="match_parent"
                    Android:layout_height="?attr/actionBarSize"
                    Android:background="?attr/colorPrimary"
                    app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>


                <TextView
                    Android:id="@+id/tv_nav_drawer_count"
                    Android:layout_width="15dp"
                    Android:layout_height="15dp"
                    Android:layout_marginLeft="30dp"
                    Android:layout_marginTop="-45dp"
                    Android:background="@drawable/menu_text_bg"
                    Android:gravity="center"
                    Android:text="10"
                    Android:textColor="@Android:color/white"
                    Android:textSize="8dp"/>


            </Android.support.design.widget.AppBarLayout>

            <FrameLayout
                Android:id="@+id/home_frame_container"
                Android:layout_width="match_parent"
                Android:layout_height="match_parent"
                Android:layout_marginTop="?actionBarSize"/>


        </Android.support.design.widget.CoordinatorLayout>

home_menu.xml

     <?xml version="1.0" encoding="utf-8"?>
        <menu xmlns:Android="http://schemas.Android.com/apk/res/Android"
              xmlns:app="http://schemas.Android.com/apk/res-auto">

            <item
                Android:id="@+id/menu_search"
                Android:icon="@Android:drawable/ic_menu_search"
                Android:orderInCategory="101"
                Android:title="Search"
                app:showAsAction="always"/>
        </menu>

menu_text_bg.xml

<vector xmlns:Android="http://schemas.Android.com/apk/res/Android"
        Android:width="24dp"
        Android:height="24dp"
        Android:viewportHeight="24.0"
        Android:viewportWidth="24.0">
    <path
        Android:fillColor="@Android:color/holo_red_dark"
        Android:pathData="M12,12m-10,0a10,10 0,1 1,20 0a10,10 0,1 1,-20 0"/>
</vector>
8
jaffar

Je sais qu'il est tard mais quand même. si vous utilisez le menu de navigation latéral Android comme démarreur, il y aura un nom de fichier app_bar_main.xml dans ce fichier, vous verrez du code comme ci-dessous, à l'exception du TextView this TextView est responsable de l'affichage du badge, il suffit de l'initialiser dans MainActivity où vous initialisez votre barre d'outils et de changer sa visibilité en fonction de vos besoins (visible lorsque le décompte est positif) dès que vous le pouvez voir sa visibilité est parti

<?xml version="1.0" encoding="utf-8"?>
<Android.support.design.widget.CoordinatorLayout 
xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
xmlns:tools="http://schemas.Android.com/tools"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
tools:context="com.thumbsol.beakns.activities.MainActivity">

<Android.support.design.widget.AppBarLayout
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:theme="@style/AppTheme.AppBarOverlay">

    <Android.support.v7.widget.Toolbar
        Android:id="@+id/toolbar"
        Android:layout_width="match_parent"
        Android:layout_height="?attr/actionBarSize"
        Android:background="?attr/colorPrimary"
        app:popupTheme="@style/AppTheme.PopupOverlay"></Android.support.v7.widget.Toolbar>

    <TextView
        Android:id="@+id/hamburger_count"
        Android:layout_width="25dp"
        Android:layout_height="25dp"
        Android:layout_marginLeft="30dp"
        Android:layout_marginTop="-45dp"
        Android:background="@drawable/red_circle_bacground"
        Android:gravity="center"
        Android:text="10"
        Android:textColor="@Android:color/white"
        Android:visibility="gone" />

    </Android.support.design.widget.AppBarLayout>

  <include layout="@layout/content_main" />

et voici le code de red_circle_bacground.xml mettez-le en drawable

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:Android="http://schemas.Android.com/apk/res/Android">
<solid Android:color="#f00" />
<corners
    Android:bottomLeftRadius="30dp"
    Android:bottomRightRadius="30dp"
    Android:topLeftRadius="30dp"
    Android:topRightRadius="30dp" />

  <size
    Android:height="25dp"
    Android:width="25dp"/>
</shape>
3
Zed

En vous basant sur la réponse de TDSoft, vous pouvez raccourcir davantage la procédure en étendant DrawerArrowDrawable.

Étape 1: (sauf DrawerArrowDrable, essentiellement identique à la classe Badge de TDSoft).

public class BadgeNavigationDrawable extends DrawerArrowDrawable{

private float mTextSize;
private Paint mBadgePaint;
private Paint mBadgePaint1;
private Paint mTextPaint;
private Rect mTxtRect = new Rect();

private String mCount = "";
private boolean mWillDraw = false;



/**
 * @param context used to get the configuration for the drawable from
 */
public BadgeNavigationDrawable(Context context) {
    super(context);

    setColor(context.getResources().getColor(R.color.accent));

    mTextSize = dpToPx(context, 8); //text size
    mBadgePaint = new Paint();
    mBadgePaint.setColor(Color.RED);
    mBadgePaint.setAntiAlias(true);
    mBadgePaint.setStyle(Paint.Style.FILL);
    mBadgePaint1 = new Paint();
    mBadgePaint1.setColor(Color.parseColor("#EEEEEE"));
    mBadgePaint1.setAntiAlias(true);
    mBadgePaint1.setStyle(Paint.Style.FILL);

    mTextPaint = new Paint();
    mTextPaint.setColor(Color.WHITE);
    mTextPaint.setTypeface(Typeface.DEFAULT);
    mTextPaint.setTextSize(mTextSize);
    mTextPaint.setAntiAlias(true);
    mTextPaint.setTextAlign(Paint.Align.CENTER);

}

@Override
public void draw(Canvas canvas) {
    super.draw(canvas);

    if (!mWillDraw) {
        return;
    }
    Rect bounds = getBounds();
    float width = bounds.right - bounds.left;
    float height = bounds.bottom - bounds.top;
    // Position the badge in the top-right quadrant of the icon.
/*Using Math.max rather than Math.min */
//  float radius = ((Math.max(width, height) / 2)) / 2;
    float radius = width * 0.15f;
    float centerX = (width - radius - 1) +10;
    float centerY = radius -5;
    if(mCount.length() <= 2){
        // Draw badge circle.
        canvas.drawCircle(centerX, centerY, radius+9, mBadgePaint1);
        canvas.drawCircle(centerX, centerY, radius+7, mBadgePaint);
    }
    else{
        canvas.drawCircle(centerX, centerY, radius+10, mBadgePaint1);
        canvas.drawCircle(centerX, centerY, radius+8, mBadgePaint);
    }
    // Draw badge count text inside the circle.
    mTextPaint.getTextBounds(mCount, 0, mCount.length(), mTxtRect);
    float textHeight = mTxtRect.bottom - mTxtRect.top;
    float textY = centerY + (textHeight / 2f);
    if(mCount.length() > 2)
        canvas.drawText("99+", centerX, textY, mTextPaint);
    else
        canvas.drawText(mCount, centerX, textY, mTextPaint);
}

/*
 Sets the count (i.e notifications) to display.
  */
public void setCount(String count) {
    mCount = count;
    // Only draw a badge if there are notifications.
    mWillDraw = !count.equalsIgnoreCase("0");
    invalidateSelf();
}

@Override
public void setAlpha(int alpha) {
    // do nothing
}

@Override
public void setColorFilter(ColorFilter cf) {
    // do nothing
}

@Override
public int getOpacity() {
    return PixelFormat.UNKNOWN;
}
private float dpToPx(Context context, float value) {
    Resources r = context.getResources();
    float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, r.getDisplayMetrics());
    return px;
}

}

Étape 2: C’est tout ce dont vous avez besoin. Si vous devez mettre à jour votre icône de tiroir de navigation, appelez - Vos événements sont tous conservés.

BadgeNavigationDrawable drawerIcon = new BadgeNavigationDrawable(MainActivity.this);
drawerIcon.setCount(String.valueOf(count));

mDrawerToggle.setDrawerArrowDrawable(drawerIcon);
                    mDrawerToggle.syncState();
1
kunmi