2016-08-08 2 views
2

Я пытаюсь найти способ переопределить непубличный атрибут стиля андроида, более конкретно атрибут atttribute с именем itemColor стиля Widget.FragmentBreadCrumbs. Этот стиль влияет на цвет текста корневой папки в PreferenceActivity, когда фрагмент предпочтений отображается на правой панели для больших экранов. Он используется классом FragmentBreadCrumbs.Как переопределить частный атрибут стиля Android

Мое приложение использует настраиваемую тему, которая расширяет Theme.Holo.Light, и тема разрывается на API 23, поэтому я пытаюсь найти обходной путь.

Вышеупомянутый стиль устанавливает значение по умолчанию itemColor из @null, которое не переопределено в теме Голо, в то время как, например, оно установлено в допустимое значение для темы Материал. В результате заголовок пачки не видно (см. screenshot for API 19 и screenshot for API 23)

Я предполагаю, что я пытаюсь найти способ, который может изменить личное значение темы, аналогичной тому, как отражение может быть используется для изменения значения частного поля для класса. Альтернативно, ContextThemeWrapper представляется многообещающим, но я просто не понимаю, как его использовать или даже если он применим в моей ситуации.

Что мне нужно, что после FragmentBreadCrumbs класса выполняет его конструктор ниже атрибута mTextColor не быть @null (который я предполагаю, что это 0), как установлено в конфигурации Android тему, но иметь действительное значение цвета.

Считаете ли вы, что это возможно?

public FragmentBreadCrumbs(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 
    super(context, attrs, defStyleAttr, defStyleRes); 

    final TypedArray a = context.obtainStyledAttributes(attrs, 
      com.android.internal.R.styleable.FragmentBreadCrumbs, defStyleAttr, defStyleRes); 

    mGravity = a.getInt(com.android.internal.R.styleable.FragmentBreadCrumbs_gravity, 
      DEFAULT_GRAVITY); 

    mLayoutResId = a.getResourceId(
      com.android.internal.R.styleable.FragmentBreadCrumbs_itemLayout, 
      com.android.internal.R.layout.fragment_bread_crumb_item); 

    /* This is the value needed to be overridden */ 
    mTextColor = a.getColor(
      com.android.internal.R.styleable.FragmentBreadCrumbs_itemColor, 
      0); 

    a.recycle(); 
} 
+1

У вас есть FragmentBreadCrumbs объект в вашем коде? (Можете ли вы получить экземпляр?) @ C.s. –

+0

@NirDuan Нет. Я не знаю, как его получить. Этот класс создается экземпляром '' в файле макета xml, используемом 'PreferenceActivity' –

ответ

1

К сожалению, набора инструментов сообщит об ошибке, если вы пытаетесь использовать android:itemColor, потому что это не соответствует имени публичного атрибута, так что вы не можете даже сделать стиль с этим атрибутом.

Единственное, что я могу придумать, это изменить цвет текста через отражение сразу после того, как были построены виды (завышены). Вы хотели бы сделать это как можно раньше, прежде чем первый раз updateCrumbs() будет запущен внутри FragmentBreadCrumbs. Может быть, вы можете переопределить onCreate() из PreferenceActivity или onCreateView() из PreferenceFragment (в зависимости от того применимо здесь), и сделать что-то вроде этого:

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    FragmentBreadCrumbs fbc = (FragmentBreadCrumbs) findViewById(...); 
    int color = ...; 
    FragmentBreadCrumbsUtils.setTextColor(fbc, color); 
} 


public class FragmentBreadCrumbsUtils { 

    private static final Field FRAGMENT_BREAD_CRUMBS_TEXT_COLOR = findField(); 
    private static Field findField() { 
     try { 
      Field f = FragmentBreadCrumbs.class.getDeclaredField("mTextColor"); 
      f.setAccessible(true); 
      return f; 
     } catch (Throwable t) { 
      // don't fail for any reason, just log it 
      Log.e("FragmentBreadCrumbsUtils", 
       "Couldn't find mTextColor field in FragmentBreadCrumbs", 
       t); 
     } 
     return null; 
    } 

    public static void setTextColor(FragmentBreadCrumbs fbc, int color) { 
     if (FRAGMENT_BREAD_CRUMBS_TEXT_COLOR == null) { 
      return; // can't do anything, we don't have the field 
     } 

     try { 
      FRAGMENT_BREAD_CRUMBS_TEXT_COLOR.set(fbc, color); 
     } catch (Throwable t) { 
      // don't fail for any reason, just log it 
      Log.e("FragmentBreadCrumbsUtils", 
       "Couldn't set mTextColor field in FragmentBreadCrumbs", 
       t); 
     } 
    } 
} 
+0

К сожалению,' onCreate() 'уже слишком поздно. Однако ваш пост и начальный комментарий помогли мне найти ответ. Я могу переопределить 'findViewById()', чтобы найти экземпляр, прежде чем он будет использоваться 'PreferenceActivity'. Если вы не возражаете добавить это к своему ответу, я соглашусь с ним, иначе я отвечу на свой вопрос. Спасибо за помощь –

+1

@ c.s. Переопределение 'findViewbyId()' чувствует себя неудобно на мой вкус (но опять же, так же как и обман фокуса). Независимо от того, какие работы я предполагаю, это как раз то, как Android иногда. – Karakuri

+0

Я полностью согласен. Отражения не было даже в моем списке, пока я не задал вопрос. Я упомянул об этом в тексте только как пример того, что я пытаюсь сделать, чтобы переопределить частный атрибут стиля. Однако перед тем, как задать вопрос, я уже исчерпал любые другие варианты (честно говоря, я не ожидал ответа на этот вопрос). Но, как вы сказали, это то, как Android иногда –