Работа со стилем

Я хотел сделать вид, содержащий вид прогресса и кнопку. Через xml представления я хотел добавить поля, которые определяют стиль кнопки и porgress.

Что я сделал до сих пор, но это не работает:

   <io.**.**.view.ButtonLoading android:id="@+id/b_recover_password"
                                       android:layout_width="wrap_content"
                                       android:gravity="center"
                                       app:styleButton="@style/ButtonGrey"
                                       app:styleProgress="@style/ProgressBar"
                                       app:textButton="@string/recover_password"
                                       android:layout_height="wrap_content"/>

Код:

   a = context.getTheme().obtainStyledAttributes(
            attrs,
            R.styleable.ButtonLoading,
            0, 0);

    int buttonId = 0;// R.style.Widget_AppCompat_Button;
    try {
        buttonId = a.getResourceId(R.styleable.ButtonLoading_styleButton, 0);
    } catch (Exception e) {
    }

    button = new Button(getContext(), attrs, buttonId);

    LayoutParams lpButton = createLayoutParams();
    button.setLayoutParams(lpButton);
    color = button.getCurrentTextColor();

    int progressId = 0;// R.style.Widget_AppCompat_ProgressBar;
    try {
        progressId = a.getResourceId(R.styleable.ButtonLoading_styleProgress, 0);
    } catch (Exception e) {
    }

    progressBar = new ProgressBar(getContext(), attrs, progressId);
    LayoutParams lpProgressBar = createLayoutParams();
    lpProgressBar.addRule(RelativeLayout.CENTER_IN_PARENT);
    progressBar.setLayoutParams(lpProgressBar);

    LayoutParams lpRelativeLayout = createLayoutParams();
    setLayoutParams(lpRelativeLayout);

    addView(button);
    addView(progressBar);

    try {
        String value = a.getString(R.styleable.ButtonLoading_textButton);
        button.setText(value);
    } catch (Exception e) {
    }
    a.recycle();

Styleable:

   <declare-styleable name="ButtonLoading">
    <attr name="styleButton" format="reference" />
    <attr name="styleProgress" format="reference" />
    <attr name="textButton" format="string" />
</declare-styleable>

Кто-нибудь Помогите мне? Спасибо

2 ответа

Решение

Проблема в ваших конструкторах для Button а также ProgressBar, Давайте рассмотрим два из конструкторов. (Акцент мой.) ( Документация)

Представление (Контекст контекста, атрибуты AttributeSet, int defStyleAttr) [Подходит для API ниже 21]

Выполните инфляцию из XML и примените специфичный для класса базовый стиль из атрибута темы. Этот конструктор View позволяет подклассам использовать их собственный базовый стиль, когда они надуваются. Например, конструктор класса Button вызовет эту версию конструктора суперкласса и предоставит R.attr.buttonStyle для defStyleAttr; это позволяет стилю кнопки темы изменять все атрибуты базового представления (в частности, его фон), а также атрибуты класса Button.

Представление (Контекст контекста, атрибуты AttributeSet, int defStyleAttr, int defStyleRes) [Подходит для API 21+]

Выполните инфляцию из XML и примените специфичный для класса базовый стиль из атрибута темы или ресурса стиля. Этот конструктор View позволяет подклассам использовать их собственный базовый стиль, когда они надуваются.

Сосредоточив внимание на двух последних аргументах.

defStyleAttr int: Атрибут в текущей теме, содержащий ссылку на ресурс стиля, который предоставляет значения по умолчанию для представления. Может быть 0, чтобы не искать значения по умолчанию.

defStyleRes int: Идентификатор ресурса ресурса стиля, который предоставляет значения по умолчанию для представления, используется только в том случае, если defStyleAttr равен 0 или не может быть найден в теме. Может быть 0, чтобы не искать значения по умолчанию.

Это сбивает с толку, потому что есть идентификаторы ресурсов, указывающие на идентификаторы ресурсов, но потерпите меня.

Что вы определили для buttonId а также progressId идентификатор ресурса, который указывает на стиль (<style...). Этот идентификатор ресурса стиля подходит для defStyleRes атрибут Button а также ProgressBar конструкторы, как отмечено выше. Вы пытаетесь использовать каждое из этих значений ресурса в качестве идентификатора, который указывает на атрибут в текущей теме. Другими словами, вы говорите, что R.attr.styleButton (styleButton) - это атрибут в текущей теме, который не соответствует текущему. Чтобы это исправить, измените стиль темы следующим образом:

styles.xml

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="styleButton">@style/ButtonGrey</item>
    ...
</style>        

Для работы с API 21+ вы можете оставить файлы стилей и макетов такими, как они есть, и изменить код пользовательского представления на что-то вроде следующего. (Я только показываю код для кнопки, но индикатор выполнения будет аналогичным.) Возможно, вы захотите создать отдельный файл стиля для API 21+ (styles-v21.xml).

public CustomViewGroup(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    TypedArray a = context.getTheme().obtainStyledAttributes(
            attrs,
            R.styleable.ButtonLoading,
            0, 0);
    int defStyleRes = 0;
    try {
        defStyleRes = a.getResourceId(R.styleable.ButtonLoading_styleButton, 0);
    } catch (Exception e) {
      // do something
    }
    Button button;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        // defStyleRes is only used if defStyleAttr == 0 
        // or can't be found in the current theme.
        button = new Button(getContext(), attrs, defStyleAttr, defStyleRes);
    } else {
        button = new Button(getContext(), attrs, 
                     (defStyleAttr != 0) ? defStyleAttr : R.attr.styleButton);
    }
    try {
        String value = a.getString(R.styleable.ButtonLoading_textButton);
        button.setText(value);
    } catch (Exception e) {
      // do something
    }
    addView(button);
    a.recycle();
}

Установка текста кнопки продолжается, как вы закодировали. Стили сложнее. Делатьapp:styleButton="@style/ButtonGrey" работать так, как вы рассчитывали для всех API, я думаю, что вам придется сделать что-то вроде этого.

Надеюсь, это поможет.

Мои стили это:

    <!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="android:buttonStyle">@style/ButtonAppTheme</item>
    <item name="android:progressBarStyle">@style/ProgressBarBase</item>
</style>

<style name="ProgressBarBase" parent="android:Widget.Holo.Light.ProgressBar">
    <item name="android:textColorTertiary">@color/color_grey</item>
</style>

<style name="ProgressBar" parent="android:Widget.Holo.Light.ProgressBar">
    <item name="android:textColorTertiary">@color/color_black</item>
</style>

Проблема в том, что у вас всегда есть стиль "ProgressBarBase". То есть это не переопределение.

Другие вопросы по тегам