16

I am trying to change the default close button on the actionbar of the custom chrome tabs. I have tried to set using setCloseButtonIcon() However, the default close button still shows. I want to change the close to an arrow.

My code below:

public void openHomePage() {
    final CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
    builder.setToolbarColor(ContextCompat.getColor(getActivity(), R.color.primary));
    final Bitmap backButton = BitmapFactory.decodeResource(getResources(), R.drawable.ic_arrow_back_black_48dp);
    builder.setCloseButtonIcon(backButton);

    builder.setShowTitle(true);
    final CustomTabsIntent customTabsIntent = builder.build();

    customTabsIntent.launchUrl(getActivity(), Uri.parse(mTvHomepage.getText().toString()));
}
Zoe
  • 27,060
  • 21
  • 118
  • 148
ant2009
  • 27,094
  • 154
  • 411
  • 609
  • 1
    i just checked my code for this and it looks exactly the same. Have you tried another drawable (maybe a smaller one? could this be your problem that the 48dp arrow is to big?) – stamanuel Mar 11 '17 at 20:06
  • @stamanuel First I tried 24dp which didn't work. After some searching someone said use 48dp. However, the 48dp didn't work either. – ant2009 Mar 12 '17 at 02:39
  • Can you post a basic project? – azizbekian Mar 15 '17 at 15:51

7 Answers7

26

I have an observation. Last month, when searching through SO for various chrome custom tab issues, I found this answer suggesting to use 24dp size icon and also found this question saying that it is working fine with PNG.

I have checked your code with using back arrow icon from here.

When I used "ic_arrow_back_black_48dp", it didn't change the default close button to an arrow (see left image).

final Bitmap backButton = BitmapFactory.decodeResource(getResources(), R.drawable.ic_arrow_back_black_48dp);

But when I used "ic_arrow_back_black_24dp", it perfectly changed the default close button to an arrow (see right image).

final Bitmap backButton = BitmapFactory.decodeResource(getResources(), R.drawable.ic_arrow_back_black_24dp);

As it has worked perfectly for me, you should also try with "24dp" size back arrow icon from here instead of "48dp" size back arrow icon.

Screenshot : [ Device: ASUS_Z00UD; OS: 6.0.1 ]

The default close button has changed to an arrow when using 24dp size icon instead of 48dp size.

Community
  • 1
  • 1
mdrafiqulrabin
  • 1,657
  • 5
  • 28
  • 38
  • 3
    @FantasyPollock Its seems that you can only use the png icons. I was originally trying to use the svg icons. When I changed to png it started working. Not sure why the svg doesn't work. I used the same icon as you but selected the png. Did you test with the svg icons? Thanks. – ant2009 Mar 17 '17 at 02:03
  • @ant2009 Sorry that I forgot to mention about .png format. Yes, I always tested with png icon. Not sure why the svg icon doesn't work. – mdrafiqulrabin Mar 17 '17 at 04:02
  • 1
    +1 I second what everyone has been saying here. If you want to change the "close icon", it has to be a 24dp PNG drawable. Vectors or any other size don't work... – Leo Nov 19 '18 at 11:50
9

Presuming you are using the Google library and not on of the related ones the icons size should be 24dp as documented here.

This can be achieved with BitmapFactory Options:

BitmapFactory.Options options = new BitmapFactory.Options();
options.outWidth = 24;
options.outHeight = 24;
options.inScaled = true; //already default, just for illustration - ie scale to screen density (dp)
... = BitmapFactory.decodeResource(getResources(), R.drawable.ic_arrow_back_black_48dp, opts);
Nick Cardoso
  • 20,807
  • 14
  • 73
  • 124
5

You can directly get BitmapDrawable from Drawable but not from VectorDrawable as setCloseButtonIcon requires @NonNull Bitmap icon

You can also use svg as follows. Download the svg from here ic_arrow_back_black_24px

Below methods are self explanatory:

private static Bitmap getBitmapFromDrawable(Context context, int drawableId) {
Drawable drawable = ContextCompat.getDrawable(context, drawableId);
if (drawable instanceof BitmapDrawable) {
  return ((BitmapDrawable) drawable).getBitmap();
} else if (drawable instanceof VectorDrawable) {
  return getBitmapFromVectorDrawable((VectorDrawable) drawable);
} else {
  throw new IllegalArgumentException("Unable to convert to bitmap");
}
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static Bitmap getBitmapFromVectorDrawable(VectorDrawable vectorDrawable) {
Bitmap bitmap = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(),
    vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
vectorDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
vectorDrawable.draw(canvas);
return bitmap;
}

You can use the above as:

builder.setCloseButtonIcon(getBitmapFromDrawable(this, R.drawable.ic_arrow_back_black_24px)); 

Ref from SO

Community
  • 1
  • 1
Anurag Singh
  • 6,140
  • 2
  • 31
  • 47
3

why not you Add Image Asset and store in mipmap then it will be easier to use default icons inbuilt in android studio Assest Studio

After Uploading You can easily access icons and image from mipmap in xml file using src resource in ImageView for an instant

android:src="@mipmap/ic_launcher"
3

To make this work in Kotlin (using Android KTX) with any 24dp drawable resource:

AppCompatResources.getDrawable(activity, R.drawable.ic_arrow_back_white_24dp)?.let {
    builder.setCloseButtonIcon(it.toBitmap())
}

And if you need to do some tinting:

AppCompatResources.getDrawable(activity, R.drawable.ic_arrow_back_black_24dp)?.mutate()?.let {
    DrawableCompat.setTint(it, Color.WHITE)
    builder.setCloseButtonIcon(it.toBitmap())
}

If the drawable needs to be resized, then pass in the new width/height to the Drawable.toBitmap() function.

And if you are not using Kotlin then you can just use the equivalent of the Drawable.toBitmap() code:

fun Drawable.toBitmap(
    @Px width: Int = intrinsicWidth,
    @Px height: Int = intrinsicHeight,
    config: Config? = null
): Bitmap {
    if (this is BitmapDrawable) {
        if (config == null || bitmap.config == config) {
            // Fast-path to return original. Bitmap.createScaledBitmap will do this check, but it
            // involves allocation and two jumps into native code so we perform the check ourselves.
            if (width == intrinsicWidth && height == intrinsicHeight) {
                return bitmap
            }
            return Bitmap.createScaledBitmap(bitmap, width, height, true)
        }
    }

    val (oldLeft, oldTop, oldRight, oldBottom) = bounds

    val bitmap = Bitmap.createBitmap(width, height, config ?: Config.ARGB_8888)
    setBounds(0, 0, width, height)
    draw(Canvas(bitmap))

    setBounds(oldLeft, oldTop, oldRight, oldBottom)
    return bitmap
}

For more see this answer.

Mark
  • 7,446
  • 5
  • 55
  • 75
1

I too had to face the same problem

Solution :-

1) Take image(back arrow) in png format.
2) Keep the image size under 24dp .

Swati
  • 28,069
  • 4
  • 21
  • 41
INavin
  • 11
  • 1
1

Although this question has already been answered, since I had this problem too and none of the above suggestions solved my Problem I want to share the way I solved my problem. Hope it helps others.

Ref

  fun Context.openCustomTab(
    url: String,
    @ColorRes toolbarColor: Int,
    @ColorRes iconColor: Int,
    @DrawableRes drawable: Int
) {
    CustomTabsIntent.Builder().let { ctb ->
        AppCompatResources.getDrawable(this, drawable)?.let {
            DrawableCompat.setTint(it, resources.getColor(iconColor))
            ctb.setCloseButtonIcon(it.toBitmap())
        }
        ctb.setDefaultColorSchemeParams(
            CustomTabColorSchemeParams.Builder()
                .setToolbarColor(
                    ContextCompat.getColor(
                        this,
                        toolbarColor,
                    )
                ).build()
        )

        ctb.setShowTitle(true)
    }.build().launchUrl(this, Uri.parse(url))
}
moonkin
  • 353
  • 1
  • 10