Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to refer to app theme attributes from within a library project?

I'm building a library and would like to keep it as generic as possible.

So I'd like to set the textColor attribute of a TextView to whatever the app that's using my library has specified as its primaryColor.

Using android:textColor="?colorPrimary" seems to give me a random color and not the one that's specified in my test application. That's probably because it's trying to lookup that resource ID in the library's R.java file instead of asking the application?

So is it possible at all to refer to colors outside of the library scope? I know I can solve this by introducing a custom attribute, but I'd like to avoid that solution since it requires the user of the library to update their app theme and it wouldn't work out of the box.

like image 277
jenzz Avatar asked Oct 19 '22 18:10

jenzz


1 Answers

For future reference:

I couldn't find an XML-based solution, but what you can do is read out the theme attributes programmatically at runtime and apply them from Java.

So here's what I did for the Android-MaterialPreference library which in addition to reading out the application's colorAccent attribute also looks for an optional, custom mp_colorAccent attribute which can override the default color. Comments should give enough clarity.

package com.jenzz.materialpreference;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;

import static android.graphics.Color.parseColor;
import static android.os.Build.VERSION.SDK_INT;
import static android.os.Build.VERSION_CODES.LOLLIPOP;

final class ThemeUtils {

  // material_deep_teal_500
  static final int FALLBACK_COLOR = parseColor("#009688");

  private ThemeUtils() {
    // no instances
  }

  static boolean isAtLeastL() {
    return SDK_INT >= LOLLIPOP;
  }

  @TargetApi(LOLLIPOP)
  static int resolveAccentColor(Context context) {
    Theme theme = context.getTheme();

    // on Lollipop, grab system colorAccent attribute
    // pre-Lollipop, grab AppCompat colorAccent attribute
    // finally, check for custom mp_colorAccent attribute
    int attr = isAtLeastL() ? android.R.attr.colorAccent : R.attr.colorAccent;
    TypedArray typedArray = theme.obtainStyledAttributes(new int[] { attr, R.attr.mp_colorAccent });

    int accentColor = typedArray.getColor(0, FALLBACK_COLOR);
    accentColor = typedArray.getColor(1, accentColor);
    typedArray.recycle();

    return accentColor;
  }

}
like image 115
jenzz Avatar answered Oct 22 '22 09:10

jenzz