首页 > 解决方案 > 以编程方式创建三个具有样式和约束布局链接的 MaterialButton

问题描述

所以我最初的布局是这样的:

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/white"
            android:orientation="horizontal"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent">

            <androidx.constraintlayout.widget.ConstraintLayout
                android:id="@+id/holder"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="@dimen/margin_padding_size_small">

                <com.google.android.material.button.MaterialButton
                    android:id="@+id/btn_cod"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:paddingStart="@dimen/margin_padding_size_small"
                    android:paddingEnd="@dimen/margin_padding_size_small"
                    android:text="@string/cash_on_delivery_label"
                    app:cornerRadius="@dimen/card_corner_radius_medium"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintEnd_toStartOf="@+id/btn_card"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="parent"
                    tools:text="@string/cash_on_delivery_label" />

                <com.google.android.material.button.MaterialButton
                    android:id="@+id/btn_card"
                    style="@style/Widget.MaterialComponents.Button.OutlinedButton"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:paddingStart="@dimen/margin_padding_size_small"
                    android:paddingEnd="@dimen/margin_padding_size_small"
                    android:text="@string/card_label"
                    app:cornerRadius="@dimen/card_corner_radius_medium"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintEnd_toStartOf="@+id/btn_qr_scan"
                    app:layout_constraintStart_toEndOf="@+id/btn_cod"
                    app:strokeColor="@color/colorAccent"
                    tools:text="@string/card_label" />

                <com.google.android.material.button.MaterialButton
                    android:id="@+id/btn_qr_scan"
                    style="@style/Widget.MaterialComponents.Button.OutlinedButton"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:paddingStart="@dimen/margin_padding_size_small"
                    android:paddingEnd="@dimen/margin_padding_size_small"
                    android:text="@string/qr_scan_label"
                    app:cornerRadius="@dimen/card_corner_radius_medium"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toEndOf="@+id/btn_card"
                    app:strokeColor="@color/colorAccent"
                    tools:text="@string/qr_scan_label" />


            </androidx.constraintlayout.widget.ConstraintLayout>


        </LinearLayout>

我很早就做了一个假设,我将style根据从服务器收到的响应设置按钮的属性。但是 Android 框架没有setStyle()方法。

所以我必须找到其他方法来做到这一点。我搜索并找到了确实允许我们设置样式的Paris库,但它目前不适用于 MaterialComponents。

我尝试使用 MaterialButtonToggleGroup 但包含依赖项会完全弄乱 DataBinding 并在应用程序的其他模块中显示错误。

我目前的方法是动态创建所有三个按钮并将它们填充到 ConstraintLayout 中,这将是我的根布局。

我将如何以编程方式使用约束和链填充这三个按钮。

我已经试了:

        val constraintSet = ConstraintSet()
//        constraintSet.clone(holder) // do I need this? 
        //holder is the id of the constraint layout from xml

        val codButton = MaterialButton(this, null, R.attr.materialButtonStyle)
        codButton.text = resources.getString(R.string.cash_on_delivery_label)
        codButton.id = generateViewId()
        codButton.setCornerRadiusResource(R.dimen.card_corner_radius_medium)
        holder.addView(codButton)

        val cardButton = MaterialButton(this, null, R.attr.borderlessButtonStyle)
        cardButton.text = resources.getString(R.string.card_label)
        cardButton.id = generateViewId()
        cardButton.setCornerRadiusResource(R.dimen.card_corner_radius_medium)
        cardButton.setStrokeColorResource(R.color.colorAccent)
        holder.addView(cardButton)

        val qrButton = MaterialButton(this, null, R.attr.borderlessButtonStyle)
        qrButton.text = resources.getString(R.string.qr_scan_label)
        qrButton.id = generateViewId()
        qrButton.setCornerRadiusResource(R.dimen.card_corner_radius_medium)
        qrButton.setStrokeColorResource(R.color.colorAccent)
        holder.addView(qrButton)

        //constraintSet.connect() calls?

        constraintSet.applyTo(holder)

请告诉我实现这一目标的最佳方法。要求是对于来自服务器的任何响应,三个按钮中的两个应设置为来自材料组件的轮廓按钮,一个为来自材料组件的常规按钮。

另一个问题是:我无法使用R.attr.materialButtonOutlinedStyle(unResolved symbol) 但我可以使用R.attr.materialButtonStyle; 这是为什么?

标签: androidmaterial-designandroid-constraintlayout

解决方案


我最终做的是:

  1. 创建样式:
<!-- Outline Button Style -->
    <style name="ThemeOverlay.MyApp.OutlinedButton" parent="">
        <item name="materialButtonStyle">@style/Widget.MaterialComponents.Button.OutlinedButton</item>
    </style>
  1. 动态生成三个 Button 集。用于ContextThemeWrapper将上述样式应用于 Button。并设置约束以水平链接它们。
        val constraintSet = ConstraintSet()

        //construct COD button
        val codButton = MaterialButton(this, null, R.attr.materialButtonStyle)
        codButton.text = resources.getString(R.string.cash_on_delivery_label)
        codButton.id = generateViewId()
        codButton.setCornerRadiusResource(R.dimen.card_corner_radius_medium)
        holder.addView(codButton)

        //construct card button
        val cardButton =
            MaterialButton(ContextThemeWrapper(this, R.style.ThemeOverlay_MyApp_OutlinedButton))
        cardButton.text = resources.getString(R.string.card_label)
        cardButton.id = generateViewId()
        cardButton.isClickable = false
        cardButton.setCornerRadiusResource(R.dimen.card_corner_radius_medium)
        cardButton.setStrokeColorResource(R.color.colorAccent)
        holder.addView(cardButton)


        //construct qr button
        val qrButton =
            MaterialButton(ContextThemeWrapper(this, R.style.ThemeOverlay_MyApp_OutlinedButton))
        qrButton.text = resources.getString(R.string.qr_scan_label)
        qrButton.id = generateViewId()
        qrButton.isClickable = false
        qrButton.setCornerRadiusResource(R.dimen.card_corner_radius_medium)
        qrButton.setStrokeColorResource(R.color.colorAccent)
        holder.addView(qrButton)

        constraintSet.clone(holder)

        // constraints for the cod button
        constraintSet.connect(
            codButton.id,
            ConstraintSet.START,
            ConstraintSet.PARENT_ID,
            ConstraintSet.START
        )
        constraintSet.connect(codButton.id, ConstraintSet.END, cardButton.id, ConstraintSet.START)

        // constraints for the card button
        constraintSet.connect(cardButton.id, ConstraintSet.START, codButton.id, ConstraintSet.END)
        constraintSet.connect(cardButton.id, ConstraintSet.END, qrButton.id, ConstraintSet.START)

        // constraints for the qr scan
        constraintSet.connect(qrButton.id, ConstraintSet.START, cardButton.id, ConstraintSet.END)
        constraintSet.connect(
            qrButton.id,
            ConstraintSet.END,
            ConstraintSet.PARENT_ID,
            ConstraintSet.END
        )

        constraintSet.applyTo(holder)

推荐阅读