java - studio - Acceso a los atributos en AttributeSet para componentes personalizados
taglib java (2)
La respuesta aceptada es un poco larga. Aquí hay una versión condensada que espero sea fácil de seguir. Para agregar un atributo de textSize
(o cualquier cosa que use dp
/ sp
) a su vista personalizada, siga los siguientes pasos.
1. Crea un atributo personalizado
Cree (o agregue la siguiente sección) a attrs.xml . Tenga en cuenta el formato de dimension
.
<resources>
<declare-styleable name="CustomView">
<attr name="textSize" format="dimension" />
</declare-styleable>
</resources>
2. Establezca el atributo en su diseño xml.
Tenga en cuenta el espacio de nombres de la app
personalizada.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.myproject.CustomView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:textSize="20sp" />
</RelativeLayout>
3. Obtenga el valor del atributo en su vista personalizada
Tenga en cuenta el uso de getDimensionPixelSize
. Dentro de su vista personalizada solo trabaje con píxeles. Vea esta respuesta si necesita convertir a una dimensión diferente.
public class CustomView extends View {
private float mTextSize; // pixels
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs, R.styleable.CustomView, 0, 0);
try {
mTextSize = a.getDimensionPixelSize(R.styleable.CustomView_textSize, 0);
} finally {
a.recycle();
}
}
/**
* @param size in SP units
*/
public void setTextSize(int size) {
mTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
size, getResources().getDisplayMetrics());
mTextPaint.setTextSize(mTextSize);
invalidate();
requestLayout();
}
// ...
}
Notas
Tengo un componente personalizado que contiene dos vistas de texto que tienen activado un método de configuración de tamaño personalizado (las dos vistas de texto son proporcionales en una proporción de 1: 2). Siendo que esta es una subclase de RelativeLayout, no tiene un atributo textSize, pero me pregunto si todavía es posible establecer el atributo android:textSize
en la android:textSize
instancias XML para este componente, y luego tomar el atributo textSize
el AttributeSet para usar con mi método setSize()
en el constructor.
He visto la técnica para hacer esto con atributos personalizados, pero ¿qué pasa si quiero capturar un atributo que ya está en el léxico de Android?
Sí, es posible;
Supongamos que su declaración RelativeLayout (en xml) tiene textSize definido con 14sp:
android:textSize="14sp"
En el constructor de su vista personalizada (la que incluye el AttributeSet), puede recuperar los atributos del espacio de nombres de Android como tal:
String xmlProvidedSize = attrs.getAttributeValue("http://schemas.android.com/apk/res/android", "textSize");
El valor de xmlProvidedSize será algo así como "14.0sp" y tal vez con un poco de edición de String solo puedes extraer los números.
Otra opción para declarar su propio conjunto de atributos sería un poco larga, pero también es posible.
Entonces, tienes tu vista personalizada y tus TextViews declararon algo así:
public class MyCustomView extends RelativeLayout{
private TextView myTextView1;
private TextView myTextView2;
// rest of your class here
genial...
Ahora también debe asegurarse de que su vista personalizada anule el constructor que toma el AttributeSet de esta manera:
public MyCustomView(Context context, AttributeSet attrs){
super(context, attrs);
init(attrs, context); //nice, clean method to instantiate your TextViews//
}
ok, veamos ese método init () ahora:
private void init(AttributeSet attrs, Context context){
// do your other View related stuff here //
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MyCustomView);
int xmlProvidedText1Size = a.int(R.styleable.MyCustomView_text1Size);
int xmlProvidedText2Size = a.int(R.styleable.MyCustomView_text2Size);
myTextView1.setTextSize(xmlProvidedText1Size);
myTextView2.setTextSize(xmlProvidedText2Size);
// and other stuff here //
}
Probablemente se esté preguntando de dónde viene R.styleable.MyCustomView, R.styleable.MyCustomView_text1Size y R.styleable.MyCustomView_text2Size provienen de; Permítanme elaborar sobre eso.
Debe declarar el (los) nombre (s) de los atributos en su archivo attrs.xml (en el directorio de valores) para que siempre que use su vista personalizada, los valores recopilados de estos atributos se entreguen en su constructor.
Así que veamos cómo declara estos atributos personalizados como ha pedido: Aquí está mi attrs.xml completo
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyCustomView">
<attr name="text1Size" format="integer"/>
<attr name="text2Size" format="integer"/>
</declare-styleable>
</resources>
Ahora puede configurar el tamaño de su TextViews en su XML, pero NO sin declarar el espacio de nombres en su diseño, aquí es cómo:
<com.my.app.package.MyCustomView
xmlns:josh="http://schemas.android.com/apk/res-auto"
android:id="@+id/my_custom_view_id"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
josh:text1Size="15"
josh:text2Size="30"
/>
Preste atención a cómo declaré el espacio de nombres como "josh" como la primera línea en el conjunto de atributos de su CustomView.
Espero que esto ayude a Josh,