web-dev-qa-db-fra.com

Modifier par programme la valeur d'une ressource de couleur obtenue à partir de la réponse de l'API

Disons que sur mon appel API, j'ai un paramètre appelé color. Est-il possible d'éditer ou de modifier un R.colors.color pour assigner la couleur du résultat de l'API?

Par exemple:

J'appelle mon API et renvoie green, maintenant je veux charger mon application avec ie (vert Toolbar, vert TextView couleur, etc.), est-ce que possible?

Ma première pensée fut:

Créer un élément sur colors.xml appelé demo puis lui assigne une couleur par défaut, puis utilise cette couleur demo où je le souhaite (Button, TextView, etc.) il pourrait être possible de changer cette valeur par programme avec le résultat de l'API afin que je n'aie pas besoin de créer un SharedPreferences ou quelque chose comme ça et pour éviter plus de code.

Comme @ Y.S. m'a dit

Malheureusement, vous devrez définir la couleur du texte ou la voir manuellement partout ... :(

J'aimerais savoir s'il existe un autre moyen de le faire, car je ne sais pas combien Activities mon projet contiendra, donc s'il y a un autre moyen de le faire, je suis heureux d'entendre d'autres suppositions.

MODIFIER

J'essaie la réponse @Jared Rummler et peut-être que je fais quelque chose de mal ... J'ai créé un simple Json et je mets mes actifs. J'analyse le Json et je le mets sur un GlobalConstant puis j'ai fait une "application simple".

Tout d’abord, j’ai un TextView et un Button qui contient le "color_special_special", et le retour de celui-ci j’ai mis le GlobalConstant int comme suit :

case "your_special_color":                
            return GlobalConstant.color; 

Ensuite, ce que j’ai essayé, c’est mon premier Activity a 1 TextView et 1 Button comme je l’ai dit précédemment et ils ont la couleur "your_special_color" que je ne veux pas changer. MAIS j’ai un Intent sur mon Button pour ouvrir l’autre Activity qui contient le même, mais avec le GlobalConstant.color et ça ne change pas.

J'ai essayé de faire ceci (ma deuxième activité):

public class Main2Activity extends AppCompatActivity {
private Res res;
@Override public Resources getResources() {
    if (res == null) {
        res = new Res(super.getResources());
    }
    return res;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main2);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
}

Ai-je oublié quelque chose?

Oh .. Je l'ai compris, je suppose que c'est ce qui se passe sur mon MainActivity2?

 Button btn = (Button)findViewById(R.id.button2);
 btn.setBackgroundColor(res.getColor(R.color.your_special_color));
71
Skizo-ozᴉʞS

Si vous jetez un coup d'œil au document Accès aux ressources , son contenu est que ...

Une fois que vous avez fourni une ressource dans votre application, vous pouvez l'appliquer en référençant son ID de ressource. Tous les identifiants de ressources sont définis dans la classe R de votre projet, que l'outil aapt génère automatiquement.

En outre,

Lorsque votre application est compilée, aapt génère la classe R, qui contient les identifiants de ressources pour toutes les ressources de votre répertoire res/. Pour chaque type de ressource, il existe une sous-classe R (par exemple, R.drawable Pour toutes les ressources pouvant être dessinées), et pour chaque ressource de ce type, un entier statique (par exemple, R.drawable.icon). Cet entier est l'ID de ressource que vous pouvez utiliser pour récupérer votre ressource.

Ce que cela indique, en gros, est que pratiquement tout ce qui est considéré comme une ressource dans le répertoire res/ Est compilé et référencé comme une constante non modifiable. C’est pour cette raison que les valeurs des éléments de ressource ne peuvent pas être modifiées par programmation/au moment de l’exécution, car elles sont compilées . Contrairement aux variables locales/globales & SharedPreferences, les éléments de ressource sont représentés dans la mémoire de programme sous la forme d'objets fixes et non modifiables. Ils sont conservés dans une région spéciale en mémoire seule du programme. À cet égard, voir aussi Modification de la valeur de R.String par programme .

Ce que vous pouvez faites, pour éviter d’utiliser le même code à mille endroits dans votre projet, créez une fonction commune qui modifie la valeur de la couleur dans le SharedPreferences et utilisez cette méthode partout. Je suis sûr que vous le saviez déjà, bien sûr.

Pour réduire la quantité de code que vous devez ajouter au projet, il existe une alternative. J'ai déjà utilisé la bibliothèque de calligraphie qui m'a permis de corriger le style et la couleur de la police dans l'application. Cela peut vous être utile, jetez-y un coup d'œil ...

26
Y.S

Vous pouvez créer une classe qui étend Resources et redéfinir les méthodes getColor(int) et getColor(int, Theme).

Exemple:

colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="your_special_color">#FF0099CC</color>
</resources>

Res.Java

public class Res extends Resources {

    public Res(Resources original) {
        super(original.getAssets(), original.getDisplayMetrics(), original.getConfiguration());
    }

    @Override public int getColor(int id) throws NotFoundException {
        return getColor(id, null);
    }

    @Override public int getColor(int id, Theme theme) throws NotFoundException {
        switch (getResourceEntryName(id)) {
            case "your_special_color":
                // You can change the return value to an instance field that loads from SharedPreferences.
                return Color.RED; // used as an example. Change as needed.
            default:
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    return super.getColor(id, theme);
                }
                return super.getColor(id);
        }
    }
}

BaseActivity.Java

public class BaseActivity extends AppCompatActivity {

    ...

    private Res res;

    @Override public Resources getResources() {
        if (res == null) {
            res = new Res(super.getResources());
        }
        return res;
    }

    ...

}

C’est l’approche que j’ai utilisée dans l’une de mes applications, vérification de la racine . Si vous remplacez getResources dans vos activités et dans votre classe d'application principale, vous pouvez modifier le thème par programme (même si les thèmes sont immuables). Si vous le souhaitez, téléchargez l'application et voyez comment définir les couleurs primaire, d'accent et d'arrière-plan à partir des préférences.

58
Jared Rummler

R La classe n'est pas censée être modifiée. Il ne contient que des références à vos ressources.

Vous devrez le configurer manuellement. Cependant, pour réduire la charge de configuration manuelle, vous pouvez essayer d'utiliser des bibliothèques spéciales pour enregistrer les préférences, par exemple:

(liste complète des bibliothèques similaires https://Android-arsenal.com/tag/75 )


Vous pouvez également envisager une autre façon d'appliquer des styles et de transmettre des paramètres - si vous souhaitez ajouter d'autres paramètres tels que la hauteur, la largeur, etc. Pour cela, vous pouvez définir un attribut personnalisé dans themes.xml/styles.xml:

<attr name="demoColor" format="reference|color" />

puis définissez les styles:

<style name="BaseActivity">
</style>
<style name="GreenActivity" parent="@style/BaseActivity">
    <item name="demoColor">#00cd00</item>
</style>
<style name="RedActivity" parent="@style/BaseActivity">
    <item name="demoColor">#ff0000</item>
</style>

utilisez ensuite cette couleur dans votre XML comme ceci:

... Android:background="?demoColor" ...

et basculer entre les styles GreenActivity et RedActivity dans Activity.onCreate:

setTheme(isGreenStyle() ? R.style.GreenActivity : R.style.RedActivity)
setContentView(...)

Avec l'approche ci-dessus, vous serez en mesure de configurer facilement vos styles au format xml. Cela devrait être moins de code et plus facile à refactoriser à l'avenir. (Vous aurez toujours besoin d'avoir une variable de préférence pour enregistrer si vous avez le style vert ou rouge)


Si vous souhaitez afficher des démonstrations de votre application avec différentes couleurs, vous pouvez également utiliser des variantes/saveurs de construction pour charger votre application avec des couleurs et des styles différents (c'est pour le moment de la création - et non pour l'exécution):

app/src/main/res/colors.xml

<resources>
    <color name="demoColor">#00cd00</color>
</resources>

app/src/buildVariant/res/colors.xml

<resources>
    <color name="demoColor">#ff0000</color>
</resources>

Vous pouvez maintenant basculer rapidement entre "main" et "buildVariant" dans le menu Variantes de construction et lancer votre application avec différentes couleurs de "démo". De la même manière, vous pouvez personnaliser beaucoup d'autres attributs.

Recherchez "Variantes de construction" ici http://developer.Android.com/tools/building/configuring-gradle.html

10
GregoryK

Vous ne pouvez pas modifier les ressources d'une application, ce sont toutes des constantes. Au lieu de cela, vous pouvez enregistrer votre couleur dans SharedPrefences et l'utiliser à partir de là.

Voir Comment utiliser SharedPreferences dans Android pour stocker, extraire et modifier des valeurs .

Si votre application a déjà un R.color.green défini et que vous souhaitez simplement y accéder en fonction de l'API renvoyée, vous utilisez:

int resourceID = getResources().getIdentifier("green", "color", getPackageName());
10
Sourabh

stockez les codes de couleur hexadécimaux dans les préférences partagées, puis utilisez la fonction parsecolor; stockez tous vos codes hexadécimaux de couleurs dans les sessions sous forme de chaîne.
par ex.
session.setString("white","#FFFFFF"); String colorname=session.getString("white");yourtextview.setBackgroundColor(Color.parseColor(colorname);

3
Mayuresh Gawande