Как использовать getStyledAttributes (int []) с внутренними темами Android

Итак, я осмотрел и узнал, что android.R.styleable больше не является частью SDK, хотя он все еще документирован здесь.

Это не было бы проблемой, если бы было четко зафиксировано, что такое альтернатива. Например, приложение AOSP Calendar по-прежнему использует android.R.styleable

// Get the dim amount from the theme   
TypedArray a = obtainStyledAttributes(com.android.internal.R.styleable.Theme);
lp.dimAmount = a.getFloat(android.R.styleable.Theme_backgroundDimAmount, 0.5f);
a.recycle();

Итак, как получить backgroundDimAmount без получения int[] от android.R.styleable.Theme?

Что мне нужно вставить в obtainStyledAttributes(int []), чтобы заставить его работать с SDK?

Ответ 1

В демонстрации CustomView API показано, как извлекать стилизованные атрибуты. Код для просмотра здесь:

https://github.com/android/platform_development/blob/master/samples/ApiDemos/src/com/example/android/apis/view/LabelView.java

Массивный массив, используемый для извлечения текста, цвета и размера, определен в разделе <declare-styleable> здесь:

https://github.com/android/platform_development/blob/master/samples/ApiDemos/res/values/attrs.xml#L24

Вы можете использовать <declare-styleable> для определения любого списка атрибутов, которые вы хотите получить в качестве группы, содержащих как собственные, так и определенные, определенные платформой.

Насколько эти вещи находятся в документации, есть много java-документов вокруг шаблонных массивов, что делает их полезными в документации, поэтому они остались там. Однако по мере изменения массивов, например добавления новых атрибутов, значения констант могут меняться, поэтому платформа не может быть в SDK (и, пожалуйста, не используйте никаких трюков, чтобы попытаться получить к ним доступ). В любом случае не должно быть необходимости использовать платформу, потому что каждый из них существует только для реализации частей фреймворка, и тривиально создавать свои собственные, как показано здесь.

Ответ 2

В этом примере они оставили ссылку на контекст "c":

public ImageAdapter(Context c) {
    TypedArray a = c.obtainStyledAttributes(R.styleable.GalleryPrototype);
    mGalleryItemBackground = a.getResourceId(
            R.styleable.GalleryPrototype_android_galleryItemBackground, 0);
    a.recycle();
    return mGalleryItemBackground;
}

Изменение getStyledAttributes на c.obtainStyledAttributes должно работать

Ответ 3

Пример вытаскивания стандартного атрибута (фона) в пользовательский вид, который имеет свой собственный стиль по умолчанию. В этом примере пользовательский вид PasswordGrid расширяет GridLayout. Я задал стиль для PasswordGrid, который устанавливает фоновое изображение, используя стандартный атрибут android android: background.

public class PasswordGrid extends GridLayout {

    public PasswordGrid(Context context) {
        super(context);
        init(context, null, 0);
    }

    public PasswordGrid(Context context, AttributeSet attrs) {
        super(context, attrs, R.attr.passwordGridStyle);
        init(context, attrs, 0);
    }

    public PasswordGrid(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context, attrs, defStyle);
    }

    private void init(Context context, AttributeSet attrs, int defStyle) {
        if (!isInEditMode()) {

            TypedArray stdAttrs = context.obtainStyledAttributes(attrs,
                    new int[] { android.R.attr.background },  // attribute[s] to access
                    defStyle, 
                    R.style.PasswordGridStyle);  // Style to access

           // or use any style available in the android.R.style file, such as
           //       android.R.style.Theme_Holo_Light

            if (stdAttrs != null) {
                Drawable bgDrawable = stdAttrs.getDrawable(0);
                if (bgDrawable != null)
                    this.setBackground(bgDrawable);
                stdAttrs.recycle();
            }
        }
    }

Вот часть моего файла styles.xml:

 <declare-styleable name="passwordGrid">
    <attr name="drawOn" format="color|reference" />
    <attr name="drawOff" format="color|reference" />
    <attr name="pathWidth" format="integer" />
    <attr name="pathAlpha" format="integer" />
    <attr name="pathColor" format="color" />
 </declare-styleable>



  <style name="PasswordGridStyle" parent="@android:style/Widget.GridView" >  
      <!--  Style custom attributes.  -->
      <item name="drawOff">@drawable/ic_more</item>
      <item name="drawOn">@drawable/ic_menu_cut</item>
      <item name="pathWidth">31</item>
      <item name="pathAlpha">129</item>
      <item name="pathColor">@color/green</item>

      <!-- Style standard attributes -->
      <item name="android:background">@drawable/pattern_bg</item>
</style>

Ответ 4

Это похоже на ошибку в SDK. Я подал на него issue, который вы, возможно, захотите показать, чтобы получать обновления на нем.

В качестве обходного пути вы можете использовать отражение для доступа к полю:

Class clazz=Class.forName("android.R$styleable");
int i=clazz.getField("Theme_backgroundDimAmount").getInt(clazz);