1

I created a custom style:

<style name="Static">
    <item name="android:layout_width">wrap_content</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:layout_marginEnd">5dp</item>
</style>

Then I extended anko with a static function:

inline fun ViewManager.static(theme: Int = R.style.Static, init: TextView.() -> Unit) = ankoView(::TextView, theme, init)

When I use this in my layout:

static { text = resources.getString(R.string.name) }

The marginEnd value is ignored.

If I add a margin manually in anko:

static { text = resources.getString(R.string.name) }.lparams { marginEnd = dip(5) }

The margin is fine.

Do you guys know what is happening that anko is ignoring my margin value or any other way to define a predefined margin for a extended view anko function?

jonathanrz
  • 4,206
  • 6
  • 35
  • 58

2 Answers2

3

This is not Anko problem, this is how Android works:

If you are specifying layout_margin in a custom style, this style must be explicitly applied to each individual view that you wish to have the specified margin (as seen in the code sample below). Including this style in a theme and applying it to your application or an activity will not work.

This is because attributes which begin with layout_ are LayoutParams, or as in this example its MarginLayoutParams. Each ViewGroup have it's own LayoutParams implementation. And so layout_margin is not just general attribute that can be applied anywhere. It must be applied within the context of a ViewGroup that specifically defines it as a valid argument.

Look here for more.

Community
  • 1
  • 1
John
  • 1,304
  • 1
  • 9
  • 17
1

As @John pointed in his answer, using a style is not an option to define layout params.

So, I developed a function to use in the applyRecursively that iterates over the views and apply the layouts that I want to apply.

The solution:

I wanted to define matchParent for width and height and a margin of 16dp for a TableView, so I created a new class that extends TableLayout

class TableViewFrame(context: Context) : TableLayout(context)

and then in the function when the view is a TableViewFrame I apply my layouts

fun applyTemplateViewLayouts(view: View) {
    when(view) {
        is TableViewFrame -> {
            when(view.layoutParams) {
                is LinearLayout.LayoutParams -> {
                    view.layoutParams.height = matchParent
                    view.layoutParams.width = matchParent
                    (view.layoutParams as LinearLayout.LayoutParams).margin = view.dip(16)
                }
            }
        }
    }
}

To use the function, in the view definition, I just pass it in the applyRecursively:

verticalLayout {
        tableViewFrame {
            tableRow {
                ...
            }
        }
    }
}.applyRecursively { view -> applyTemplateViewLayouts(view) }

I wrote an article at medium with a more detailed explanation: https://medium.com/@jonathanrafaelzanella/using-android-styles-with-anko-e3d5341dd5b4

jonathanrz
  • 4,206
  • 6
  • 35
  • 58