CustomView в собственной библиотеке: Как изменить дэфолтные значения атрибутов?

Рейтинг: 1Ответов: 1Опубликовано: 12.07.2023

Есть отдельный модуль AndroidLibary
В нем создаю кастомную вьюшку
Создаю кастомные атрибуты и даю им дэфолтные значения

 <declare-styleable name="TestView">
        <attr name="_name_TestView" format="string" />
        <attr name="_info_TestView" format="string" />
    </declare-styleable>

    <style name="TestView">
        <item name="_name_TestView">test</item>
        <item name="_info_TestView">info</item>
    </style>

Получаю атрибуты в коде

context.theme.obtainStyledAttributes(
            attrs,
            R.styleable.TestView,
            0,
            0
        )

Подключаю модуль к проекту
Хочу изменить в теме проекта (не модуля), чтобы по умолчанию атрибут _name_TestView был customTest. Как это сделать?

Код вьюшки

class TestView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : FrameLayout(context, attrs, R.attr.TestViewAtr) {


    init {
        inflate(context, R.layout.test_view, this)
    }

    private val xml =
        context.theme.obtainStyledAttributes(
            attrs,
            R.styleable.TestView,
            0,
            0
        )

    val button by lazy { findViewById<Button>(R.id.testButton) }
    val textView by lazy { findViewById<TextView>(R.id.textView) }

    var text: String = xml.getStringOrThrow(R.styleable.TestView__name_TestView)
        .apply { text = this }
        set(value) {
            field = value
            button.setText(field)
        }

    var helpText: String = xml.getStringOrThrow(R.styleable.TestView__info_TestView)
        .apply { helpText = this }
        set(value) {
            field = value
            textView.text = field
        }


    private val closeXml = { xml.recycle() }.apply { this.invoke() }

}  

Ответы

▲ 0Принят

В модуле создаем 3 вещи:

  • TestView - для атрибутов, которые мы будем использовать. Имя должно совпадать с именем класса кастомной Вью. Тогда мы в режиме design сможем увидеть все кастомные параметры.
  • TestViewDefStyle - дэфолтный стиль для атрибутов
  • TestViewStyle - стиль-ссылка, чтобы можно было изменять атрибуты снаружи
<declare-styleable name="TestView">
   <attr name="_name_TestView" format="string" />
   <attr name="_info_TestView" format="string" />
</declare-styleable>
    
<style name="TestViewDefStyle">
    <item name="_name_TestView">test</item>
    <item name="_info_TestView">info</item>
</style>

<attr name="TestViewStyle" format="reference" />

В классе нашей кастомной вьюшки, у TypedArray, указываем все, что создали

context.theme.obtainStyledAttributes(
            attrs,
            R.styleable.TestView,
            R.attr.TestViewStyle,
            R.style.TestViewDefStyle
        )

Все работает. Изменять параметры для каждого элемента можно в разметке. То, что не указано в разметке будет подтягиваться из дэфолтного значения из МОДУЛЯ.

 <com.example.mylibrary.TestView
     android:id="@+id/ggg"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
      app:_name_TestView="wlad" />

Чтобы изменить дэфолтные значения для ПРИЛОЖЕНИЯ следует

  • сперва удалить из разметки app:_name_TestView="wlad" (а то будете мучаться как я 40 минут)
  • создать собственный стиль CustomTestView и отнаследоваться от дэфолтного стиля из модуля TestViewDefStyle
    тут переопределяем нужные атрибуты
  <style name="CustomTestView" parent="TestViewDefStyle">
        <item name="_name_TestView">uuuu</item>
    </style>
  • указать этот стиль в теме своего приложения
 <style name="YOUR_APP_THEME" parent="Theme.AppCompat.NoActionBar">
  ....
  <item name="TestViewStyle">@style/CustomTestView</item>
  ...
</style>