Definición de atributos personalizados

Necesito implementar mis propios atributos como en com.android.R.attr

No se 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.

Actualmente, la mejor documentación es la fuente. Puedes echarle un vistazo aquí (attrs.xml) .

Puede definir atributos en el elemento superior o dentro de un elemento . Si voy a usar un atributo en más de un lugar, lo coloco en el elemento raíz. Tenga en cuenta que todos los atributos comparten el mismo espacio de nombres global. Esto significa que incluso si crea un nuevo atributo dentro de un elemento puede usarse fuera de él y no puede crear otro atributo con el mismo nombre de un tipo diferente.

Un elemento tiene dos atributos xml name y format . name permite llamarlo de alguna manera y así es como termina refiriéndose a él en el código, por ejemplo, R.attr.my_attribute . El atributo de format puede tener diferentes valores según el ‘tipo’ de atributo que desee.

  • referencia: si hace referencia a otra identificación de recurso (p. ej., “@ color / my_color”, “@ layout / my_layout”)
  • color
  • booleano
  • dimensión
  • flotador
  • entero
  • cuerda
  • fracción
  • enum – normalmente implícitamente definido
  • bandera – normalmente implícitamente definida

Puede establecer el formato en varios tipos utilizando | , por ejemplo, format="reference|color" .

enum atributos enum se pueden definir de la siguiente manera:

     

flag atributos de flag son similares, excepto que los valores deben definirse para que puedan combinarse juntos:

     

Además de los atributos, está el elemento . Esto le permite definir los atributos que una vista personalizada puede usar. Para ello, especifica un elemento ; si se definió previamente, no se especifica el format . Si desea reutilizar un attr de Android, por ejemplo, android: gravity, puede hacerlo en el name , de la siguiente manera.

Un ejemplo de una vista personalizada :

     

Al definir sus atributos personalizados en XML en su vista personalizada, debe hacer algunas cosas. Primero debe declarar un espacio de nombres para encontrar sus 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:

     

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. 🙂

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 usa la biblioteca tendrá errores de tiempo de ejecución.

La respuesta anterior cubre todo con gran detalle, aparte de un par de cosas.

Primero, si no hay estilos, se (Context context, AttributeSet attrs) firma del método (Context context, AttributeSet attrs) para crear una instancia de la preferencia. En este caso, solo use context.obtainStyledAttributes(attrs, R.styleable.MyCustomView) para obtener TypedArray.

En segundo lugar, no cubre cómo tratar los recursos plaurales (cadenas de cantidad). No pueden tratarse con TypedArray. Aquí hay un fragmento de código de mi SeekBarPreference que establece el resumen de la preferencia formateando su valor de acuerdo con el valor de la preferencia. Si el xml de la preferencia establece android: resumen en una cadena de texto o en un recurso de cadena, el valor de la preferencia se formatea en la cadena (debe tener% d en ella para seleccionar el valor). Si android: summary se establece en un recurso plaural, 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 da como ejemplo, sin embargo, si desea tener la tentación de establecer el resumen en la pantalla de preferencias, entonces necesita llamar a notifyChanged() en el método onDialogClosed la preferencia.

El enfoque tradicional está lleno de código repetitivo y manejo torpe de recursos. Es por eso que hice el marco de Spyglass . Para demostrar cómo funciona, aquí hay un ejemplo que muestra cómo crear una vista personalizada que muestra 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 values/attrs.xml :

      

Paso 3: aplique la anotación setTitle método setTitle para indicarle a la infraestructura 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, la estructura de Spyglass lo detectará en tiempo de comstackción y generará automáticamente la clase CustomView_SpyglassCompanion .

Paso 4: utilice 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 instancia la clase desde XML, el compañero de Spyglass interpreta los atributos y realiza la llamada al método requerido. Por ejemplo, si inflan el siguiente diseño, se setTitle a setTitle con "Hello, World!" como el argumento

    

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 en los valores de marcador de posición si sus métodos tienen múltiples parámetros.

Echa un vistazo al repository de Github para obtener más información y ejemplos.