android notificaciones - El icono de cuenta de notificación de barra de acciones(insignia)como Google tiene




cambiar iconos (8)

¿Hay una insignia estándar de Android o un método para mostrar el icono de notificación de la barra de acciones con un conteo como en los ejemplos de Google?

Si no, ¿cuál es la mejor manera de hacerlo?
Soy nuevo en Android, por favor ayuda.


Answers

En lugar de administrar formas personalizadas y dibujables, ¿por qué no usar el mecanismo Android incorporado? Puede usar el estilo de insignia en TextView y usar un estilo personalizado según su tema.

Aclamaciones. :)

        <TextView
                android:id="@+id/fabCounter"
                style="@style/Widget.Design.FloatingActionButton"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentEnd="true"
                android:layout_centerVertical="true"
                android:layout_marginEnd="10dp"
                android:padding="5dp"
                android:text="10"
                android:textColor="@android:color/black"
                android:textSize="14sp" />


Intente ver las respuestas a estas preguntas, particularmente la segunda que tiene código de muestra:

Cómo implementar valores dinámicos en el elemento del menú en Android

¿Cómo obtener texto en un icono de ActionBar?

Por lo que veo, necesitarás crear tu propia implementación personalizada de ActionView . Una alternativa podría ser un Drawable personalizado. Tenga en cuenta que no parece haber una implementación nativa de un recuento de notificaciones para la barra de acciones.

EDITAR: la respuesta que estaba buscando, con código: vista de notificación personalizada con implementación de muestra


Solo compartiré mi código en caso de que alguien quiera algo como esto:

  • diseño / menú / menu_actionbar.xml

    <?xml version="1.0" encoding="utf-8"?>
    
    <menu xmlns:android="http://schemas.android.com/apk/res/android">
        ...
        <item android:id="@+id/menu_hotlist"
            android:actionLayout="@layout/action_bar_notifitcation_icon"
            android:showAsAction="always"
            android:icon="@drawable/ic_bell"
            android:title="@string/hotlist" />
        ...
    </menu>
    
  • layout / action_bar_notifitcation_icon.xml

    Estilo de nota y android: propiedades clicables . estos hacen que el diseño tenga el tamaño de un botón y que el fondo sea gris al tocarlo.

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:orientation="vertical"
        android:gravity="center"
        android:layout_gravity="center"
        android:clickable="true"
        style="@android:style/Widget.ActionButton">
    
        <ImageView
            android:id="@+id/hotlist_bell"
            android:src="@drawable/ic_bell"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:layout_margin="0dp"
            android:contentDescription="bell"
            />
    
        <TextView xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/hotlist_hot"
            android:layout_width="wrap_content"
            android:minWidth="17sp"
            android:textSize="12sp"
            android:textColor="#ffffffff"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="@null"
            android:layout_alignTop="@id/hotlist_bell"
            android:layout_alignRight="@id/hotlist_bell"
            android:layout_marginRight="0dp"
            android:layout_marginTop="3dp"
            android:paddingBottom="1dp"
            android:paddingRight="4dp"
            android:paddingLeft="4dp"
            android:background="@drawable/rounded_square"/>
    </RelativeLayout>
    
  • drawable-xhdpi / ic_bell.png

    Una imagen de 64x64 píxeles con almohadillas de 10 píxeles de ancho desde todos los lados. Se supone que tienes almohadillas de 8 píxeles de ancho, pero la mayoría de los elementos predeterminados son ligeramente más pequeños que eso. Por supuesto, querrás usar diferentes tamaños para diferentes densidades.

  • drawable / rounded_square.xml

    Aquí, # ff222222 (color # 222222 con alfa #ff (completamente visible)) es el color de fondo de mi barra de acciones.

    <?xml version="1.0" encoding="utf-8"?>
    
    <shape
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle">
        <corners android:radius="2dp" />
        <solid android:color="#ffff0000" />
        <stroke android:color="#ff222222" android:width="2dp"/>
    </shape>
    
  • com / ubergeek42 / WeechatAndroid / WeechatActivity.java

    ¡Aquí lo hacemos clicable y actualizable! Creé un oyente abstracto que proporciona la creación de Toast en onLongClick, el código fue tomado de las fuentes de ActionBarSherlock .

    private int hot_number = 0;
    private TextView ui_hot = null;
    
    @Override public boolean onCreateOptionsMenu(final Menu menu) {
        MenuInflater menuInflater = getSupportMenuInflater();
        menuInflater.inflate(R.menu.menu_actionbar, menu);
        final View menu_hotlist = menu.findItem(R.id.menu_hotlist).getActionView();
        ui_hot = (TextView) menu_hotlist.findViewById(R.id.hotlist_hot);
        updateHotCount(hot_number);
        new MyMenuItemStuffListener(menu_hotlist, "Show hot message") {
            @Override
            public void onClick(View v) {
                onHotlistSelected();
            }
        };
        return super.onCreateOptionsMenu(menu);
    }
    
    // call the updating code on the main thread,
    // so we can call this asynchronously
    public void updateHotCount(final int new_hot_number) {
        hot_number = new_hot_number;
        if (ui_hot == null) return;
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (new_hot_number == 0)
                    ui_hot.setVisibility(View.INVISIBLE);
                else {
                    ui_hot.setVisibility(View.VISIBLE);
                    ui_hot.setText(Integer.toString(new_hot_number));
                }
            }
        });
    }
    
    static abstract class MyMenuItemStuffListener implements View.OnClickListener, View.OnLongClickListener {
        private String hint;
        private View view;
    
        MyMenuItemStuffListener(View view, String hint) {
            this.view = view;
            this.hint = hint;
            view.setOnClickListener(this);
            view.setOnLongClickListener(this);
        }
    
        @Override abstract public void onClick(View v);
    
        @Override public boolean onLongClick(View v) {
            final int[] screenPos = new int[2];
            final Rect displayFrame = new Rect();
            view.getLocationOnScreen(screenPos);
            view.getWindowVisibleDisplayFrame(displayFrame);
            final Context context = view.getContext();
            final int width = view.getWidth();
            final int height = view.getHeight();
            final int midy = screenPos[1] + height / 2;
            final int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
            Toast cheatSheet = Toast.makeText(context, hint, Toast.LENGTH_SHORT);
            if (midy < displayFrame.height()) {
                cheatSheet.setGravity(Gravity.TOP | Gravity.RIGHT,
                        screenWidth - screenPos[0] - width / 2, height);
            } else {
                cheatSheet.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, height);
            }
            cheatSheet.show();
            return true;
        }
    }
    

Ok, para que la solución @AndrewS funcione con la biblioteca v7 appCompat :

<menu 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:someNamespace="http://schemas.android.com/apk/res-auto" >

    <item
        android:id="@+id/saved_badge"
        someNamespace:showAsAction="always"
        android:icon="@drawable/shape_notification" />

</menu>

.

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
    menu.clear();
    inflater.inflate(R.menu.main, menu);

    MenuItem item = menu.findItem(R.id.saved_badge);
    MenuItemCompat.setActionView(item, R.layout.feed_update_count);
    View view = MenuItemCompat.getActionView(item);
    notifCount = (Button)view.findViewById(R.id.notif_count);
    notifCount.setText(String.valueOf(mNotifCount));
}

private void setNotifCount(int count){
    mNotifCount = count;
    supportInvalidateOptionsMenu();
}

El resto del código es el mismo.


No me gustan las ActionView basadas en ActionView , mi idea es:

  1. crear un diseño con TextView , que TextView se completará con la aplicación
  2. cuando necesitas dibujar un elemento de MenuItem :

    2.1. inflar el diseño

    2.2. call measure() y layout() (de lo contrario, view será 0px x 0px, es demasiado pequeño para la mayoría de los casos de uso)

    2.3. establecer el texto de TextView

    2.4. hacer "captura de pantalla" de la vista

    2.6. establece el ícono de MenuItem basado en el mapa de bits creado en 2.4

  3. ¡lucro!

Entonces, el resultado debería ser algo así como

  1. crear diseño aquí es un ejemplo simple
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/counterPanel"
    android:layout_width="32dp"
    android:layout_height="32dp"
    android:background="@drawable/ic_menu_gallery">
    <RelativeLayout
        android:id="@+id/counterValuePanel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" >

        <ImageView
            android:id="@+id/counterBackground"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/unread_background" />

        <TextView
            android:id="@+id/count"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="1"
            android:textSize="8sp"
            android:layout_centerInParent="true"
            android:textColor="#FFFFFF" />
    </RelativeLayout>
</FrameLayout>

@drawable/unread_background es que el TextView verde de TextView , @drawable/ic_menu_gallery no es realmente necesario aquí, es solo una vista previa del resultado del diseño en IDE.

  1. agregar código en onCreateOptionsMenu / onPrepareOptionsMenu

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
    
        MenuItem menuItem = menu.findItem(R.id.testAction);
        menuItem.setIcon(buildCounterDrawable(count, R.drawable.ic_menu_gallery));
    
        return true;
    }
    
  2. Implementar el método build-the-icon:

    private Drawable buildCounterDrawable(int count, int backgroundImageId) {
        LayoutInflater inflater = LayoutInflater.from(this);
        View view = inflater.inflate(R.layout.counter_menuitem_layout, null);
        view.setBackgroundResource(backgroundImageId);
    
        if (count == 0) {
            View counterTextPanel = view.findViewById(R.id.counterValuePanel);
            counterTextPanel.setVisibility(View.GONE);
        } else {
            TextView textView = (TextView) view.findViewById(R.id.count);
            textView.setText("" + count);
        }
    
        view.measure(
                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
        view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
    
        view.setDrawingCacheEnabled(true);
        view.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
        Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());
        view.setDrawingCacheEnabled(false);
    
        return new BitmapDrawable(getResources(), bitmap);
    }
    

El código completo está aquí: https://github.com/cvoronin/ActionBarMenuItemCounter


Cuando usas la barra de herramientas:

....
private void InitToolbar() {
    toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar);
    toolbartitle = (TextView) findViewById(R.id.titletool);
    toolbar.inflateMenu(R.menu.show_post);
    toolbar.setOnMenuItemClickListener(this);
    Menu menu = toolbar.getMenu();
    MenuItem menu_comments = menu.findItem(R.id.action_comments);
    MenuItemCompat
            .setActionView(menu_comments, R.layout.menu_commentscount);
    View v = MenuItemCompat.getActionView(menu_comments);
    v.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View arg0) {
            // Your Action
        }
    });
    comment_count = (TextView) v.findViewById(R.id.count);
}

y en su datos de carga, llame a refreshMenu ():

private void refreshMenu() {
    comment_count.setVisibility(View.VISIBLE);
    comment_count.setText("" + post_data.getComment_count());
}

No estoy seguro de si esta es la mejor solución o no, pero es lo que necesito.

Por favor dígame si sabe lo que se necesita cambiar para un mejor rendimiento o calidad. En mi caso, tengo un botón.

Artículo personalizado en mi menú - main.xml

<item
    android:id="@+id/badge"
    android:actionLayout="@layout/feed_update_count"
    android:icon="@drawable/shape_notification"
    android:showAsAction="always">
</item>

Forma personalizada dibujable (cuadrado de fondo) - shape_notification.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
   android:shape="rectangle">
    <stroke android:color="#22000000" android:width="2dp"/>
    <corners android:radius="5dp" />
    <solid android:color="#CC0001"/>
</shape>

Diseño para mi vista - feed_update_count.xml

<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/notif_count"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:minWidth="32dp"
     android:minHeight="32dp"
     android:background="@drawable/shape_notification"
     android:text="0"
     android:textSize="16sp"
     android:textColor="@android:color/white"
     android:gravity="center"
     android:padding="2dp"
     android:singleLine="true">    
</Button>

MainActivity: configuración y actualización de mi vista

static Button notifCount;
static int mNotifCount = 0;    

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getSupportMenuInflater();
    inflater.inflate(R.menu.main, menu);

    View count = menu.findItem(R.id.badge).getActionView();
    notifCount = (Button) count.findViewById(R.id.notif_count);
    notifCount.setText(String.valueOf(mNotifCount));
    return super.onCreateOptionsMenu(menu);
}

private void setNotifCount(int count){
    mNotifCount = count;
    invalidateOptionsMenu();
}

Almaceno texto principal y palabras seleccionables en diferentes recursos.

Las cadenas en los recursos no existen para algunas configuraciones.

    String[] links = new String[3];

    links[0] = cntx.getString(cntx.getResources().getIdentifier("footerLink1", "string", cntx.getPackageName()));
    links[1] = cntx.getString(cntx.getResources().getIdentifier("footerLink2", "string", cntx.getPackageName()));
    links[2] = cntx.getString(cntx.getResources().getIdentifier("footerLink3", "string", cntx.getPackageName()));
    String text = String.format(cntx.getString(cntx.getResources().getIdentifier("footerDisclaimer", "string", cntx.getPackageName())), links[0], links[1], links[2]);
    SpannableString ss = new SpannableString(text);
    setSpanOnLink(ss, links[0], new ClickableSpan() {
        @Override
        public void onClick(View textView) {
            Log.i("Disclaimer Footer", "1 click");
            //TODO run item 
        }
    });
    setSpanOnLink(ss, links[1], new ClickableSpan() {
        @Override
        public void onClick(View textView) {
            Log.i("Disclaimer Footer", "2 click");
            //TODO run item 
        }
    });
    setSpanOnLink(ss, links[2], new ClickableSpan() {
        @Override
        public void onClick(View textView) {
            Log.i("Disclaimer Footer", "3click");
            //TODO run item 
        }
    });

    TextView t1 = new TextView(cntx);
    t1.setTextSize(TypedValue.COMPLEX_UNIT_SP, 8);
    t1.setText(ss);
    t1.setMovementMethod(LinkMovementMethod.getInstance());

private void setSpanOnLink(SpannableString ss, String link, ClickableSpan cs) {
        String text = ss.toString();
        int start = text.indexOf(link);
        int end = start + link.length();
        ss.setSpan(cs, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    }




android notifications icons android-actionbar actionbarsherlock