[F/OS] ๐Ÿ”˜ Button Icon Extension - Android, Material and Custom Icons

:computer: Introduction

I was testing a couple of extensions and I realized that the Button Addon extension by Andres Cotes needs some updates, including the color of the icons, the sizes and some more. So I cooked up this extension to help you insert icons to your buttons. No assets for Android and Material, just download it, import it and you're good.

image image image image

This extension offers four types of icons.

Icon Type Description Icons Available
Default Android's default icons that you can use, available in a helper block. 67
Material Google's Material Icons, available here. 2,500 +
Custom Your custom icons that you can add to your app! Unlimited
Font Icon fonts in your assets or ASD. Unlimited

The default icons that Android provides in the R.drawable class are kind of old, so I recommend you to use them only if you are making apps intending for old Android devices, or apps with the Classic theme, although you can technically use any icon for any theme. Material Icons are icons provided by Google using material design, and if you want to build an app with professional UI, this should be for you.

:chart_with_upwards_trend: Stats

:hammer_and_wrench: Built with: AppInventor Extensions Template

:clock1: Version: 2

:blue_book: Documentation

SetAndroidButtonIcons

image

Sets the icon of the specified button, using the default Android drawable icons. Use 0 if you do not want an icon to appear.

Parameters: component = component, leftIcon = Icon/number(int), topIcon = Icon/number(int), rightIcon = Icon/number(int), bottomIcon = Icon/number(int)

SetCustomButtonIcons

Sets the icon of the specified button. Use an empty text block if you do not want an icon to appear. Please use absolute paths or full paths in this instance.

Parameters: component = component, leftIcon = text, topIcon = text, rightIcon = text, bottomIcon = text

SetFontButtonIcons

image

Sets the button's icons from the given icon font. Please use absolute or full paths in this instance. If you do not want an icon, use an empty text block.

Parameters: component = component, fontPath = text, leftIcon = text, topIcon = text, rightIcon = text, bottomIcon = text, color = color, size = number (int)

SetIconPadding

image

Sets the size of the padding between the icon and the text, in pixels.

Parameters: component = component, padding = number (int)

SetMaterialButtonIcons

image

Sets the material icon of the specified button. Use an empty text block if you do not want an icon to appear. The size of the icons should be in pixels.

Parameters: component = component, leftIcon = text, topIcon = text, rightIcon = text, bottomIcon = text, color = color, size = number (int)

:inbox_tray: Downloads

AIX (V2):
com.gordonlu.buttonicons.aix (190.2 KB)

AIA (V2):
ButtonIcons.aia (235.1 KB)

:books: FAQ

Q1: Does this extension support GIFs?

A1: No, unfortunately it does not. Try using a JPG or PNG image instead.

Q2: Is this extension open source?

A2: Yes of course! You can modify the code here in GitHub, but please give me a credit by linking to this topic and mentioning the author.

:+1: Credits

Thanks to @Kumaraswamy for helping me creating this extension and for his guidance, shout-out to him.

Also, thanks to @shreyash for his guide on creating extensions, I'm using Extensions Template for the first time and this is only possible because of his guide.

Please click the beautiful :heart: Like button if you like the extension, it took a lot of effort and time to make it.

As I have exams from the 3rd to 13th next month, I definitely need a break from the builders. I'll be back in 2 weeks. Please, if you have questions in those two weeks, drop a reply in this post and I'll answer your questions after my exams. Goodbye.

Gute Rutsch! Happy New Year! ๆ–ฐๅนดๅฟซๆจ‚๏ผ

27 Likes

Could the material icons be made to show in companion if one used a ttf font file, as with @Anke 's extension?

Do you add text to a button using the standard button text property?

No, there is a function in TextView that allows you to assign a Drawable to a button. You can take a look at the source code.

I do not see in your extension blocks where one would add the text?

Try it in the built app.

1 Like

What does that mean? (The assets are in the ASD with Companion).

The extension assets are not sent over to the Companion, but it is compiled with the built app. (this is with extensions template)

Still not answered my question about button text...

You don't need to add the text, because the extension only changes the drawable of the button, not the text. Those are two different properties of a Button.

And yes, you add the text using the Text property. It's in the AIA file.

Thank you :blush:

1 Like

one suggestion:
for this block:
https://community.appinventor.mit.edu/uploads/default/original/3X/c/0/c09bb463f7f9368ff2d5d91d799da3913e53765d.png
you can add a line to avoid use the replace block by users.

public Drawable createDrawable(String path) {
      if(path.startsWith("file://")) {
			path = path.replace("file://", "");
		}
        if (path == "") {
            return null;
        } else {
3 Likes

Reworked (using RUSH) with a bit of extra code to make a temp file of the ttf, and now works in companion and when compiled:

JAVA
package uk.co.metricrat.buttonmaticon;


import android.graphics.Canvas;
import com.google.appinventor.components.annotations.SimpleFunction;
import com.google.appinventor.components.runtime.AndroidNonvisibleComponent;
import com.google.appinventor.components.runtime.AndroidViewComponent;
import com.google.appinventor.components.runtime.ComponentContainer;
import android.widget.Button;
import android.graphics.Paint;
import java.io.*;
import java.io.File;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.util.DisplayMetrics;


public class ButtonMatIcon extends AndroidNonvisibleComponent {
  String filePath;
  String newFilePath;
  public ButtonMatIcon(ComponentContainer container) {
    super(container.$form());
  }


  public String GetFont() throws IOException {

    File file = File.createTempFile("temp", ".ttf");
    filePath = file.getAbsolutePath();
    try {
      InputStream in = form.openAssetForExtension(this, "material-icons.ttf");
      int size = in.available();
      byte[] buffer = new byte[size];
      in.read(buffer);
      in.close();
      FileOutputStream out = new FileOutputStream(filePath);
      out.write(buffer);
      out.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return filePath;
  }


  public Drawable createMaterialIcon(String icon, int color, int size) throws IOException {
    if (icon == "") {
      return null;
    } else {
      newFilePath = GetFont();
      Typeface typeface = Typeface.createFromFile(newFilePath);
      Paint paint = new Paint();
      paint.setTypeface(typeface);
      paint.setColor(color);
      paint.setTextSize((float)size);
      paint.setTextAlign(Paint.Align.CENTER);
      Bitmap bit = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
      Canvas canvas = new Canvas(bit);
      canvas.drawText(icon, (float) (canvas.getWidth() / 2),   (((float) (canvas.getHeight() / 2)) - ((paint.descent() + paint.ascent()) / 2)), paint);
      return new BitmapDrawable(form.getResources(), bit);
    }
  }

  @SimpleFunction(description = "Sets the material icon of the specified button. Use an empty text block if you do not want an icon to appear. The size of the icons should be in pixels.")
  public void SetMaterialButtonIcons(AndroidViewComponent component, String leftIcon, String topIcon, String rightIcon, String bottomIcon, int color, int size) throws IOException {
    Button button = (Button) component.getView();
    int pixels = size * getDensity();
    button.setCompoundDrawablesWithIntrinsicBounds(createMaterialIcon(leftIcon, color, pixels), createMaterialIcon(topIcon, color, pixels),
            createMaterialIcon(rightIcon, color, pixels), createMaterialIcon(bottomIcon, color, pixels));
  }

  @SimpleFunction(description = "Sets the size of the padding between the icon and the text.")
  public void SetIconPadding(AndroidViewComponent component, int padding) {
    Button button = (Button) component.getView();
    button.setCompoundDrawablePadding(padding);
  }

  public int getDensity(){
    DisplayMetrics metrics = form.getResources().getDisplayMetrics();
    return (int) metrics.density;
  }

}

uk.co.metricrat.buttonmaticon.aix (192.5 KB)

image

image

8 Likes

Thank you for all of your suggestions. I made version 2 of this extension that works in the Companion, accepts full paths, and even accepts custom icon fonts. I also renamed SetButtonIcons to SetAndroidButtonIcons because the former sounded too generic.

image

Icon font from: Journal Dingbats 2 Font ยท 1001 Fonts

Credits: @TIMAI2, @Kevinkun Thank you both!

4 Likes

below code can get Typeface no mater the font file at assets or asd, then no need to copy font file from asset to asd.

Typeface tf = Typeface.DEFAULT;
		if (fontName.startsWith("//")) {
			fontName = fontName.substring(2);
			if (isReplForm) {
				String realpath;
				String files = this.context.getExternalFilesDir(null).getPath();
				if (Build.VERSION.SDK_INT >= 29) {
					realpath = files + "/assets/" + fontName;
				} else {
					realpath = files + "/AppInventor/assets/" + fontName;
				}
				tf = Typeface.createFromFile(realpath);
			} else {
				tf = Typeface.createFromAsset(this.context.getAssets(), fontName);
			}
		} else {
			if (fontName.toLowerCase().startsWith("file://")) {
				fontName = fontName.substring(7);
			}
			tf = Typeface.createFromFile(fontName);
		}
5 Likes

Thanks @gordonlu310 for such a long awaited and useful feature!

1 Like

Hello, I'm trying to add my custom icon to the button I created. I followed the blocks displayed above when putting custom buttons, but it didn't work. What did I do wrong?


I want to put the icon on the left side of the button with the text "Restaurants Near Me."

I would appreciate your help. Thank you!

For this version, you will have to also copy the image to ASD before you set the custom button icons. Look at the sample project.

Do You plan to implement Materia Symbols?

Material icons are already implemented. I can add Material Symbols Rounded if you want to.