72 votes

Comment concaténer plusieurs chaînes dans XML android?

Problème
Je voudrais être capable de faire quelque chose comme ça dans Android code XML:

<string name="title">@string/app_name test</string>
<string name="title2">@string/app_name @string/version_name</string>

Concernant la première ligne de code du compilateur affiche cette erreur

Aucune ressource trouvée, qui correspond au nom donné ("titre" avec la valeur "@string/app_name test')

et au sujet de la deuxième ligne de code compilateur affiche cette erreur

Aucune ressource trouvée, qui correspond au nom donné (à 'titre2' avec la valeur '@string/app_name @string/version_name')

Question
Quelqu'un sait comment concaténer plusieurs chaînes dans Android XML?

Justification
C'est une mauvaise pratique de dupliquer les valeurs de la variable dans de nombreux endroits de code (dans ce cas, XML).

56voto

dbm Points 3814

J'ai essayé de faire un semblable manœuvre moi-même, mais on m'a dit que ce n'est pas faisable dans Android.

La chose intéressante est que vous obtenez un message d'erreur qui indique que c' est possible, mais en raison d'erreurs dans de jumelage des ressources, il n'est pas possible en ce moment. (Êtes-vous sûr que vous avez défini la "app_name" et "version_name" cordes avant de le "titre" et "titre2" cordes?)

Vous pouvez cependant faire quelque chose comme:

<string name="title">%1$s test</string>
<string name="title2">%1$s %2$s</string>

<string name="app_name">AppName</string>
<string name="version_name">1.2</string>

Et puis à partir du code Java faire quelque chose comme:

Resources res = getResources();
String appName = res.getString(R.string.app_name);
String versionName = res.getString(R.string.version_name);

String title = res.getString(R.string.title, appName);
String title2 = res.getString(R.string.title2, appName, versionName);

Plus sur le formatage de chaînes de caractères dans Android.

Espérons que cette aide.

1voto

schnatterer Points 730

Vous pouvez utiliser votre propre logique qui résout les chaînes imbriquées de manière récursive.

J'ai répondu à une question similaire ici . Pour votre commodité, voici comment j'ai résolu ce problème:

 /**
 * Regex that matches a resource string such as <code>@string/a-b_c1</code>.
 */
private static final String REGEX_RESOURCE_STRING = "@string/([A-Za-z0-9-_]*)";

/** Name of the resource type "string" as in <code>@string/...</code> */
private static final String DEF_TYPE_STRING = "string";

/**
 * Recursively replaces resources such as <code>@string/abc</code> with
 * their localized values from the app's resource strings (e.g.
 * <code>strings.xml</code>) within a <code>source</code> string.
 * 
 * Also works recursively, that is, when a resource contains another
 * resource that contains another resource, etc.
 * 
 * @param source
 * @return <code>source</code> with replaced resources (if they exist)
 */
public static String replaceResourceStrings(Context context, String source) {
    // Recursively resolve strings
    Pattern p = Pattern.compile(REGEX_RESOURCE_STRING);
    Matcher m = p.matcher(source);
    StringBuffer sb = new StringBuffer();
    while (m.find()) {
        String stringFromResources = getStringByName(context, m.group(1));
        if (stringFromResources == null) {
            Log.w(Constants.LOG,
                    "No String resource found for ID \"" + m.group(1)
                            + "\" while inserting resources");
            /*
             * No need to try to load from defaults, android is trying that
             * for us. If we're here, the resource does not exist. Just
             * return its ID.
             */
            stringFromResources = m.group(1);
        }
        m.appendReplacement(sb, // Recurse
                replaceResourceStrings(context, stringFromResources));
    }
    m.appendTail(sb);
    return sb.toString();
}

/**
 * Returns the string value of a string resource (e.g. defined in
 * <code>values.xml</code>).
 * 
 * @param name
 * @return the value of the string resource or <code>null</code> if no
 *         resource found for id
 */
public static String getStringByName(Context context, String name) {
    int resourceId = getResourceId(context, DEF_TYPE_STRING, name);
    if (resourceId != 0) {
        return context.getString(resourceId);
    } else {
        return null;
    }
}

/**
 * Finds the numeric id of a string resource (e.g. defined in
 * <code>values.xml</code>).
 * 
 * @param defType
 *            Optional default resource type to find, if "type/" is not
 *            included in the name. Can be null to require an explicit type.
 * 
 * @param name
 *            the name of the desired resource
 * @return the associated resource identifier. Returns 0 if no such resource
 *         was found. (0 is not a valid resource ID.)
 */
private static int getResourceId(Context context, String defType,
        String name) {
    return context.getResources().getIdentifier(name, defType,
            context.getPackageName());
}
 

D'un Activity , par exemple, appelez-le comme suit

 replaceResourceStrings(this, getString(R.string.title));
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X