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

Я хотел создать представление, содержащее представление прогресса и кнопку. Через 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();

Стили:

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

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


person Pedro Simões    schedule 10.08.2017    source источник
comment
Когда вы говорите, что это не работает, что именно это означает?   -  person Cheticamp    schedule 10.08.2017
comment
Не работает набор стилей на кнопке и прогрессбаре. Придерживайтесь стиля по умолчанию.   -  person Pedro Simões    schedule 10.08.2017
comment
Этот код находится в пользовательском представлении. Какой метод находится в этом представлении. Что такое базовый (расширяющий) вид. Можете ли вы опубликовать свои стили для индикатора выполнения и кнопки?   -  person Cheticamp    schedule 10.08.2017


Ответы (2)


Проблема в ваших конструкторах для Button и ProgressBar. Рассмотрим два конструктора. (Выделено мной.) (Документация)

View(Context context, AttributeSet attrs, int defStyleAttr) [Подходит для API 21 ниже]

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

View(Context context, AttributeSet attrs, 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, я думаю, вам нужно сделать что-то вроде этого.

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

person Cheticamp    schedule 11.08.2017

Мои стили:

    <!-- 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". То есть это не переопределение.

person Pedro Simões    schedule 11.08.2017