Pregunta

necesito para poner en práctica mis propios atributos al igual que en com.android.R.attr

No se encontró nada en la documentación oficial, así que necesitan información sobre cómo definir estas attrs y cómo utilizarlos de mi código.

¿Fue útil?

Solución

En la actualidad la mejor documentación es la fuente. Puede echar un vistazo a lo aquí (attrs. xml) .

Se puede definir atributos en el elemento superior <resources> o en el interior de un elemento <declare-styleable>. Si voy a utilizar un attr en más de un lugar en el que puse en el elemento raíz. Nota, todos los atributos comparten el mismo espacio de nombres global. Eso significa que incluso si se crea un nuevo atributo en el interior de un elemento <declare-styleable> que pueden ser usados ??fuera de ella y no se puede crear otro atributo con el mismo nombre de un tipo diferente.

Un elemento <attr> tiene dos atributos XML name y format. name le permite llamar a algo y esto es como se llega a referirse a ella en el código, por ejemplo, R.attr.my_attribute. El atributo format puede tener diferentes valores dependiendo del 'tipo' de atributo que desea.

  • Referencia - Si se hace referencia a otra Identificación del recurso (por ejemplo, "@ Color / my_color", "@ diseño / my_layout")
  • Color
  • boolean
  • dimensión
  • flotador
  • entero
  • cadena
  • fracción
  • enumeración - normalmente definido implícitamente
  • bandera - normalmente definido implícitamente

Se puede configurar el formato de múltiples tipos utilizando |, por ejemplo, format="reference|color".

atributos enum pueden ser definidos como sigue:

<attr name="my_enum_attr">
  <enum name="value1" value="1" />
  <enum name="value2" value="2" />
</attr>

atributos flag son similares, excepto los valores deben ser definidas para que puedan ser poco ORED juntos:

<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 una vista personalizada puede utilizar. Esto se hace mediante la especificación de un elemento <attr>, si se ha definido previamente no se especifica el format. Si desea volver a utilizar una attr androide, por ejemplo, androide:. Gravedad, entonces usted puede hacer que 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 la vista personalizada que tiene que hacer algunas cosas. En primer lugar se debe declarar un espacio de nombres para encontrar sus atributos. Esto se hace en el elemento de diseño raíz. Normalmente sólo hay xmlns:android="http://schemas.android.com/apk/res/android". Ahora debe añadir también 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>

Por último, para el acceso atributo personalizado que normalmente lo hacen en el constructor de la 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 extremo. :)

Otros consejos

La respuesta de Qberticus es bueno, pero un detalle útil es que falta. Si va a implementar estos en una biblioteca reemplazar:

xmlns:whatever="http://schemas.android.com/apk/res/org.example.mypackage"

por:

xmlns:whatever="http://schemas.android.com/apk/res-auto"

De lo contrario la aplicación que utiliza la biblioteca tendrá errores de ejecución.

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

En primer lugar, si no hay estilos, entonces el método de firma (Context context, AttributeSet attrs) será utilizado para crear instancias de la preferencia. En este caso, sólo tiene que utilizar context.obtainStyledAttributes(attrs, R.styleable.MyCustomView) para obtener el TypedArray.

En segundo lugar, no cubre cómo tratar con los recursos plaurals (cadenas cantidad). Estos no pueden ser tratadas con el uso TypedArray. Aquí es un fragmento de código de mi SeekBarPreference que establece el resumen de la preferencia de formatear su valor de acuerdo con el valor de la preferencia. Si el código XML para los conjuntos de preferencias Android: Resumen de una cadena de texto o una cadena resouce el valor de la preferencia se da formato a la cadena (que debería tener% d en el mismo, para recoger el valor). Si androide:. Resumen se establece en un recurso plaurals, a continuación, que se utiliza 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 es sólo como ejemplo, sin embargo, si desea que se ven tentados a establecer el resumen en la pantalla de preferencias, entonces usted necesita llamar notifyChanged() en el método onDialogClosed de la preferencia.

El enfoque tradicional está llena de código repetitivo y manejo de recursos torpe. Es por eso que hice la Spyglass marco . Para demostrar cómo funciona, aquí está un ejemplo que muestra cómo hacer una vista personalizada que muestra un título de cadena.

. Paso 1: Crear una clase 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: Definir un atributo de cadena en el archivo de recursos values/attrs.xml:

<resources>
    <declare-styleable name="CustomView">
        <attr name="title" format="string"/>
    </declare-styleable>
</resources>

Paso 3:. Aplicar la anotación @StringHandler con el método setTitle para contar el marco Spyglass para enrutar el valor de atributo a este método cuando se infla la vista

@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 del catalejo lo detectará en tiempo de compilación y generar automáticamente la clase CustomView_SpyglassCompanion.

Paso 4: Usar la clase generada en el método init de 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 todo. Ahora bien, cuando se instancia la clase de XML, el compañero del catalejo interpreta los atributos y hace la llamada al método requerido. Por ejemplo, si inflamos la siguiente distribución setTitle entonces será llamada con "Hello, World!" como 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 está limitado a recursos de cadena tiene un montón de diferentes anotaciones para el manejo de otros tipos de recursos. También tiene anotaciones para definir los valores por defecto y para pasar en los valores de marcador de posición si sus métodos tienen varios parámetros.

Para consultar el repositorio Github para obtener más información y ejemplos.

Si se omite el atributo format del elemento attr, se puede utilizar para hacer referencia a una clase de diseños XML.

  • ejemplo de attrs.xml .
  • Android Estudio entiende que la clase está haciendo referencia a partir de XML
    • es decir.
      • Refactor > Rename funciona
      • Find Usages funciona
      • y así sucesivamente ...

no especifique un atributo format en ... / src / main / res / valores / attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="MyCustomView">
        ....
        <attr name="give_me_a_class"/>
        ....
    </declare-styleable>

</resources>

usarlo en algún archivo de diseño ... / src / main / res / layout / activity__main_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<SomeLayout
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <!-- make sure to use $ dollar signs for nested classes -->
    <MyCustomView
        app:give_me_a_class="class.type.name.Outer$Nested/>

    <MyCustomView
        app:give_me_a_class="class.type.name.AnotherClass/>

</SomeLayout>

analizar la clase en el código de inicialización vista ... / src / main / java /.../ MyCustomView.kt

class MyCustomView(
        context:Context,
        attrs:AttributeSet)
    :View(context,attrs)
{
    // parse XML attributes
    ....
    private val giveMeAClass:SomeCustomInterface
    init
    {
        context.theme.obtainStyledAttributes(attrs,R.styleable.ColorPreference,0,0).apply()
        {
            try
            {
                // very important to use the class loader from the passed-in context
                giveMeAClass = context::class.java.classLoader!!
                        .loadClass(getString(R.styleable.MyCustomView_give_me_a_class))
                        .newInstance() // instantiate using 0-args constructor
                        .let {it as SomeCustomInterface}
            }
            finally
            {
                recycle()
            }
        }
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top