Search code examples
javaandroidandroid-studiodialogdeclare-styleable

Custom declare-styleable not displaying text attribute


I have been working on a custom "Button" and it works just as I want it to so far. However, I am trying to add text to the button instead of a drawable (which is what I was doing before).

Currently I have used a declare-styleable in my attrs.xml file which looks like the following:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- Custom attributes for the button -->
    <declare-styleable name="StyledButton">
        <attr name="cornerRadius" format="dimension" />
        <attr name="borderWidth" format="dimension" />
        <attr name="startColor" format="color" />
        <attr name="centerColor" format="color" />
        <attr name="endColor" format="color" />
    </declare-styleable>
</resources>

Alongside this, I have the accompanying class StyledButton.java :

package com.example.test;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.graphics.Path;
import android.graphics.Paint;
import android.graphics.LinearGradient;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageButton;

public class StyledButton extends AppCompatImageButton {

    private float cornerRadius = 0f;
    private float borderWidth = 0f;
    private int startColor = 0;
    private int centerColor = 0;
    private int endColor = 0;

    private Path path = new Path();
    private Paint borderPaint = new Paint();

    {
        borderPaint.setStyle(Paint.Style.FILL);
    }

    public StyledButton(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs, 0);

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.StyledButton);

        try {
            cornerRadius = a.getDimension(R.styleable.StyledButton_cornerRadius, 10f);
            borderWidth = a.getDimension(R.styleable.StyledButton_borderWidth, 10f);
            startColor = a.getColor(R.styleable.StyledButton_startColor, getResources().getColor(R.color.colorPrimaryDark, context.getTheme()));
            centerColor = a.getColor(R.styleable.StyledButton_centerColor, getResources().getColor(R.color.colorAccent, context.getTheme()));
            endColor = a.getColor(R.styleable.StyledButton_endColor, Color.WHITE);
        }
        finally {
            a.recycle();
        }

    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        borderPaint.setShader(new LinearGradient(0f, 0f, 0f, (float) getHeight(), new int[] {startColor, centerColor, endColor}, null, Shader.TileMode.CLAMP));
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        path.rewind();
        path.addRoundRect(borderWidth, borderWidth, ((float) getWidth()) - borderWidth, ((float) getHeight()) - borderWidth, cornerRadius - borderWidth / 2, cornerRadius - borderWidth / 2, Path.Direction.CCW);
        canvas.clipOutPath(path);
        path.rewind();
        path.addRoundRect(0f, 0f, ((float) getWidth()), ((float) getHeight()), cornerRadius, cornerRadius, Path.Direction.CCW);
        canvas.drawPath(path, borderPaint);
    }
}

I am trying to use these in a custom dialog to get user input with the following code:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:elevation="5dp">

    <androidx.cardview.widget.CardView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:cardCornerRadius="20dp">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:background="@drawable/background_gradient"
            android:padding="10dp">

            <TextView
                android:layout_width="300dp"
                android:layout_height="wrap_content"
                android:scaleType="center"
                android:text="@string/app_name"
                android:textAlignment="center"
                android:fontFamily="@font/lato_bold"
                android:textSize="36sp"
                android:padding="10dp"
                android:textColor="@android:color/white" />

            <EditText
                android:id="@+id/player_name_dialog_name"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="16dp"
                android:layout_marginLeft="4dp"
                android:layout_marginRight="4dp"
                android:layout_marginBottom="4dp"
                android:hint="@string/player_name_hint"
                android:textAlignment="center"/>

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="40dp"
                android:orientation="horizontal"
                android:layout_gravity="center"
                android:layout_marginTop="10dp">

                <com.example.test.StyledButton
                    android:id="@+id/player_name_dialog_confirm_button"
                    android:layout_weight="1"
                    android:layout_height="match_parent"
                    android:layout_width="120dp"
                    android:scaleType="center"
                    android:layout_gravity="center"
                    app:startColor="@color/colorPrimaryDark"
                    app:centerColor="@color/colorPrimary"
                    app:endColor="@color/colorAccent"
                    app:borderWidth="2dp"
                    app:cornerRadius="20dp"
                    android:text="@string/cancel"
                    android:textColor="@android:color/white"
                    android:textSize="20sp"
                    android:fontFamily="@font/lato"
                    android:layout_marginHorizontal="10dp"
                    android:onClick="deletePlayerButtonClick"/>

                <com.example.test.StyledButton
                    android:id="@+id/add_players_activity_delete_button"
                    android:layout_weight="1"
                    android:layout_height="match_parent"
                    android:layout_width="120dp"
                    android:scaleType="center"
                    android:layout_gravity="center"
                    app:startColor="@color/colorPrimaryDark"
                    app:centerColor="@color/colorPrimary"
                    app:endColor="@color/colorAccent"
                    app:borderWidth="2dp"
                    app:cornerRadius="20dp"
                    android:layout_marginHorizontal="10dp"
                    android:onClick="deletePlayerButtonClick"/>

            </LinearLayout>
        </LinearLayout>
    </androidx.cardview.widget.CardView>
</RelativeLayout>

I have tried adding the android:text in the attrs.xml file but this doesn't show up and I don't understand why this may be.

Thanks in advance !


Solution

  • The text will not show as the custom view extends AppCompatImageButton. AppCompatImageButton only displays an image.

    public class StyledButton extends AppCompatImageButton {
    

    If you require a button that shows text consider having two custom views, one for image and the other for text.

    StyledImageButton:

    public class StyledImageButton extends AppCompatImageButton {
    

    StyledButton

    public class StyledButton extends AppCompatButton {
    

    The rest of the code can remain the same.

    NOTE: Android will not let you create duplicate attributes in attrs.xml. Create global attributes and reuse them. Like so:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <attr name="cornerRadius" format="dimension" />
        <attr name="borderWidth" format="dimension" />
        <attr name="startColor" format="color" />
        <attr name="centerColor" format="color" />
        <attr name="endColor" format="color" />
    
        <declare-styleable name="StyledButton">
            <attr name="cornerRadius" />
            <attr name="borderWidth" />
            <attr name="startColor" />
            <attr name="centerColor" />
            <attr name="endColor" />
        </declare-styleable>
    
        <declare-styleable name="StyledImageButton">
            <attr name="cornerRadius" />
            <attr name="borderWidth" />
            <attr name="startColor" />
            <attr name="centerColor" />
            <attr name="endColor" />
        </declare-styleable>
    </resources>