android - tipos - para qué sirve el elemento data-* en html
Definiendo atributos personalizados (4)
Actualmente la mejor documentación es la fuente. Puedes echarle un vistazo aquí (attrs.xml) .
Puede definir atributos en el elemento superior <resources>
o dentro de un elemento <declare-styleable>
. Si voy a usar un atributo en más de un lugar, lo pongo en el elemento raíz. Tenga en cuenta que todos los atributos comparten el mismo espacio de nombres global. Eso significa que incluso si crea un nuevo atributo dentro de un elemento <declare-styleable>
, puede usarse fuera de él y no puede crear otro atributo con el mismo nombre de un tipo diferente.
Un elemento <attr>
tiene dos atributos xml name
y format
. name
permite llamarlo de alguna manera y así es como terminará refiriéndose a él en el código, por ejemplo, R.attr.my_attribute
. El atributo de format
puede tener diferentes valores dependiendo del ''tipo'' de atributo que desee.
- referencia - si hace referencia a otro ID de recurso (por ejemplo, "@ color / my_color", "@ layout / my_layout")
- color
- booleano
- dimensión
- flotador
- entero
- cuerda
- fracción
- enumeración - normalmente definida implícitamente
- bandera - normalmente definida implícitamente
Puede configurar el formato en varios tipos utilizando |
, por ejemplo, format="reference|color"
.
enum
atributos de enum
se pueden definir de la siguiente manera:
<attr name="my_enum_attr">
<enum name="value1" value="1" />
<enum name="value2" value="2" />
</attr>
flag
atributos de los flag
son similares, excepto que los valores deben definirse para que puedan unirse en bits:
<attr name="my_flag_attr">
<flag name="fuzzy" value="0x01" />
<flag name="cold" value="0x02" />
</attr>
Además de los atributos, está el elemento <declare-styleable>
. Esto le permite definir atributos que puede usar una vista personalizada. Para ello, especifique un elemento <attr>
, si se definió anteriormente, no especifica el format
. Si desea reutilizar un dispositivo androide, por ejemplo, android: gravity, puede hacerlo en el name
, de la siguiente manera.
Un ejemplo de una vista personalizada <declare-styleable>
:
<declare-styleable name="MyCustomView">
<attr name="my_custom_attribute" />
<attr name="android:gravity" />
</declare-styleable>
Al definir sus atributos personalizados en XML en su vista personalizada, necesita hacer algunas cosas. Primero debes declarar un espacio de nombres para encontrar tus atributos. Usted hace esto en el elemento de diseño raíz. Normalmente solo hay xmlns:android="http://schemas.android.com/apk/res/android"
. Ahora también debe agregar xmlns:whatever="http://schemas.android.com/apk/res-auto"
.
Ejemplo:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:whatever="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<org.example.mypackage.MyCustomView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
whatever:my_custom_attribute="Hello, world!" />
</LinearLayout>
Finalmente, para acceder a ese atributo personalizado, normalmente lo hace en el constructor de su vista personalizada de la siguiente manera.
public MyCustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView, defStyle, 0);
String str = a.getString(R.styleable.MyCustomView_my_custom_attribute);
//do something with str
a.recycle();
}
El fin. :)
Necesito implementar mis propios atributos como en com.android.R.attr
No encontré nada en la documentación oficial, así que necesito información sobre cómo definir estos atributos y cómo usarlos desde mi código.
El enfoque tradicional está lleno de código repetitivo y manejo de recursos torpe. Es por eso que hice el framework Spyglass . Para demostrar cómo funciona, aquí hay un ejemplo que muestra cómo hacer una vista personalizada que muestre un título de cadena.
Paso 1: Crea una clase de vista personalizada.
public class CustomView extends FrameLayout {
private TextView titleView;
public CustomView(Context context) {
super(context);
init(null, 0, 0);
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs, 0, 0);
}
public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs, defStyleAttr, 0);
}
@RequiresApi(21)
public CustomView(
Context context,
AttributeSet attrs,
int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(attrs, defStyleAttr, defStyleRes);
}
public void setTitle(String title) {
titleView.setText(title);
}
private void init(AttributeSet attrs, int defStyleAttr, int defStyleRes) {
inflate(getContext(), R.layout.custom_view, this);
titleView = findViewById(R.id.title_view);
}
}
Paso 2: defina un atributo de cadena en el archivo de recursos de values/attrs.xml
:
<resources>
<declare-styleable name="CustomView">
<attr name="title" format="string"/>
</declare-styleable>
</resources>
Paso 3: aplique la anotación setTitle
método setTitle
para indicar al marco de Spyglass que setTitle
el valor del atributo a este método cuando la vista está inflada.
@HandlesString(attributeId = R.styleable.CustomView_title)
public void setTitle(String title) {
titleView.setText(title);
}
Ahora que su clase tiene una anotación de Spyglass, el marco de Spyglass lo detectará en tiempo de compilación y generará automáticamente la clase CustomView_SpyglassCompanion
.
Paso 4: Use la clase generada en el método init
la vista personalizada:
private void init(AttributeSet attrs, int defStyleAttr, int defStyleRes) {
inflate(getContext(), R.layout.custom_view, this);
titleView = findViewById(R.id.title_view);
CustomView_SpyglassCompanion
.builder()
.withTarget(this)
.withContext(getContext())
.withAttributeSet(attrs)
.withDefaultStyleAttribute(defStyleAttr)
.withDefaultStyleResource(defStyleRes)
.build()
.callTargetMethodsNow();
}
Eso es. Ahora, cuando crea una instancia de la clase desde XML, el acompañante de Spyglass interpreta los atributos y realiza la llamada al método requerido. Por ejemplo, si setTitle
el siguiente diseño, setTitle
se llamará con "Hello, World!"
como el argumento.
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:width="match_parent"
android:height="match_parent">
<com.example.CustomView
android:width="match_parent"
android:height="match_parent"
app:title="Hello, World!"/>
</FrameLayout>
El marco no se limita a los recursos de cadena, tiene muchas anotaciones diferentes para manejar otros tipos de recursos. También tiene anotaciones para definir valores predeterminados y para pasar valores de marcador de posición si sus métodos tienen múltiples parámetros.
Echa un vistazo al repositorio de Github para obtener más información y ejemplos.
La respuesta anterior cubre todo con gran detalle, aparte de un par de cosas.
Primero, si no hay estilos, entonces se utilizará la firma del método (Context context, AttributeSet attrs)
para crear una instancia de la preferencia. En este caso, simplemente use context.obtainStyledAttributes(attrs, R.styleable.MyCustomView)
para obtener TypedArray.
En segundo lugar, no cubre cómo tratar con los recursos de las publicaciones (cadenas de cantidad). Estos no pueden ser tratados con TypedArray. Aquí hay un fragmento de código de mi SeekBarPreference que establece el resumen del formato de preferencia de su valor de acuerdo con el valor de la preferencia. Si el xml para la preferencia establece android: resumen en una cadena de texto o una cadena, el valor de la preferencia se formatea en la cadena (debe tener% d en ella para recoger el valor). Si android: summary se establece en un recurso de tipo de archivo, entonces se usa para formatear el resultado.
// Use your own name space if not using an android resource.
final static private String ANDROID_NS =
"http://schemas.android.com/apk/res/android";
private int pluralResource;
private Resources resources;
private String summary;
public SeekBarPreference(Context context, AttributeSet attrs) {
// ...
TypedArray attributes = context.obtainStyledAttributes(
attrs, R.styleable.SeekBarPreference);
pluralResource = attrs.getAttributeResourceValue(ANDROID_NS, "summary", 0);
if (pluralResource != 0) {
if (! resources.getResourceTypeName(pluralResource).equals("plurals")) {
pluralResource = 0;
}
}
if (pluralResource == 0) {
summary = attributes.getString(
R.styleable.SeekBarPreference_android_summary);
}
attributes.recycle();
}
@Override
public CharSequence getSummary() {
int value = getPersistedInt(defaultValue);
if (pluralResource != 0) {
return resources.getQuantityString(pluralResource, value, value);
}
return (summary == null) ? null : String.format(summary, value);
}
- Esto solo se proporciona como un ejemplo, sin embargo, si desea tener la tentación de establecer el resumen en la pantalla de preferencias, debe llamar a
notifyChanged()
en el métodoonDialogClosed
la preferencia.
La respuesta de Qberticus es buena, pero falta un detalle útil. Si está implementando estos en una biblioteca, reemplace:
xmlns:whatever="http://schemas.android.com/apk/res/org.example.mypackage"
con:
xmlns:whatever="http://schemas.android.com/apk/res-auto"
De lo contrario, la aplicación que utiliza la biblioteca tendrá errores de tiempo de ejecución.