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 !
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>