Is it possible if my theme values are downloadable from server then my mobile theme will change according to what I specify from it?
Example if I have columns [colorPrimary] and [colorAccent] from server then after downloading values, my app theme colors will change accordingly.
This is my current theme.
<style name="Base.Theme.Design" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">#013034</item>
<item name="colorPrimaryDark">#013034</item>
<item name="colorAccent">#1490a0</item>
<item name="android:textColorHint">#9e9e9e</item>
</style>
Note: For all downvotes, please leave comment for improvement of this post. Thanks.
You can use Firebase remote config to apply that, for example if you have multiple theme options for your app like "Base.Theme.Design_A" and "Base.Theme.Design_B" which are already built-in your app. You can switch between and apply one of these themes by checking a remote property in Firebase remote config. Also you can change old value and fetch the remote values and activate them (not with style file)
<defaultsMap>
<entry>
<!-- color entries -->
<entry>
<key>colorPrimary</key>
<value>#013034</value>
</entry>
<entry>
<key>colorPrimaryDark</key>
<value>#013034</value>
</entry>
To change your app's colour dynamically, for elaborate implementations refer to this
There is a way to change your App's theme dynamically.
You need put two the themes in your styles.xml in advance, like this:
<style name="AppThemeA" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">#aba424</item>
<item name="colorPrimaryDark">#9f2020</item>
<item name="colorAccent">#2a6c29</item>
</style>
<style name="AppThemeB" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">#706464</item>
<item name="colorPrimaryDark">#831444</item>
<item name="colorAccent">#183150</item>
</style>
And use one of them in your codes.
For example, there is button in your MainActivity, if you click it, your theme will change to AppThemeA, so you need do this in your MainActivity's OnCreate:
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
if ("A".Equals(Intent.GetStringExtra("Theme")))
{
SetTheme(Resource.Style.AppThemeA);
}
else if("B".Equals(Intent.GetStringExtra("Theme"))) {
SetTheme(Resource.Style.AppThemeB);
}
SetContentView(Resource.Layout.Main);
Button button = FindViewById<Button>(Resource.Id.bt);
button.Click += (sender, e) => {
Intent intent= new Intent(this, typeof(MainActivity));
intent.PutExtra("Theme","A");
StartActivity(intent);
Finish();
};
}
Related
I have some problem about apply colors to my app.
I want to achieve to get some json from the web, like this:
{
"colorPrimary": "#45a02c",
"colorAccent": "#a02c2c",
"backgroundColor": "#FFFFFF"
}
and store it in a object like ThemeColor, i created. Parsing the json to object is no problem, but now i want to create a method in my ThemeColor class, that will apply the colors of the object to my app, so that my toolbar will colored in this primary color or i can use it with ?attr/colorPrimary .
Is that possible?
And what would be a good way to achieve this?
Define your custom theme inside style.xml and use that inside your activity
style.xml
<style name="CustomTheme" parent="Theme.AppCompat.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/your_custom_color</item>
<item name="colorPrimaryDark">#color/your_custom_color_2</item>
<item name="android:navigationBarColor">#color/your_custom_colot_3</item>
</style>
And use that theme inside your activity
public void onCreate(Bundle savedInstanceState) {
setTheme(android.R.style.CustomTheme); //here your custom theme
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
}
In my Xamarin Forms Android app, I would like to change the color of the splash screen based on a theme that the user has selected at run time. This change should impact the next run of the app.
I have tried using the built in splash_screen.xml and using a Splash.axml file, but I cannot figure out how (if possible) to set the background color of the splash screen to a color defined in a theme.
Is this possible?
I have tried using the built in splash_screen.xml and using a Splash.axml file, but I cannot figure out how (if possible) to set the background color of the splash screen to a color defined in a theme.
You can define themes for your splashScreen and then set android:windowBackground to a specific color:
styles.xml:
<resources>
<style name="AppTheme">
<item name="android:windowBackground">#color/colorPrimary</item>
<item name="android:windowNoTitle">true</item>
</style>
<style name="AppTheme2">
<item name="android:windowBackground">#color/colorAccent</item>
<item name="android:windowNoTitle">true</item>
</style>
...
</resources>
SplashScreen.cs( don't forget to set SplashScreen activity to be mainlauncher):
[Activity(Label = "SplashActivity",MainLauncher =true)]
public class SplashActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
ISharedPreferences preferences=GetSharedPreferences("SplashThemeId", FileCreationMode.Private);
var themeName=preferences.GetString("themeName","AppTheme");
int themeId = Resource.Style.AppTheme ;
switch (themeName)
{
case "AppTheme":
themeId = Resource.Style.AppTheme;
break;
case "AppTheme2":
themeId = Resource.Style.AppTheme2;
break;
}
SetTheme(themeId);
base.OnCreate(savedInstanceState);
...
As you noticed, I use SharedPreference to store the user selected Theme in Runtime. You can also use Android Settings for the same purpose.
Here is the complete demo. It's native android project, but it's the same for forms project.
After all of the research I've done and the things I've tried in code, I am concluding that it is not possible to dynamically set the color of the initial activity. I am going with a neutral color for the splash.
I'm currently implementing Stripe into my application.
And using the example code from their documentation, I'm starting their PaymentMethodsActivity like this.
private fun startPaymentSelectActivity() {
val intent = PaymentMethodsActivity.newIntent(this#PaymentActivity)
startActivityForResult(intent, REQUEST_CODE_SELECT_SOURCE)
}
However, the created PaymentMethodsActivity's theme does not follow my app's theme, it's using their blue Toolbar. Like this
How do I apply a Theme to this Activity?
ScreenShot attached here
1.Download Stripe from here
"https://github.com/stripe/stripe-android"
2.import stripe module in your project and Update UI as you want from it's res folder
You can add this into your styles.xml and customize the colors
<style name="StripeDefaultTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">#0091ea</item>
<item name="colorAccent">#color/accent_color_default</item>
<item name="colorControlNormal">#color/control_normal_color_default</item>
<item name="titleTextColor">#android:color/white</item>
<item name="android:textColorSecondary">#android:color/secondary_text_light</item>
</style>
Be careful to keep the style name ( name="StripeDefaultTheme" )
I'm using 'com.stripe:stripe-android:6.1.2' and that's work fine.
Source: https://github.com/stripe/stripe-android/issues/414
I have made a few apps that support multiple themes, but I always had to restart the app when user switches theme, because setTheme() needs to be called before setContentView().
I was okay with it, until I discovered this app. It can seamlessly switch between two themes, and with transitions/animations too!
Please give me some hints on how this was implemented (and animations too). Thanks!
#Alexander Hanssen's answer basically has answered this...
Don't know why it was not accepted... Maybe because of the finish()/startActivity().
I voted for it and I tried to comment but cannot...
Anyway, I would do exactly what he described in terms of styles.
<style name="AppThemeLight" parent="Theme.AppCompat.Light">
<!-- Customize your theme here. -->
<item name="android:windowAnimationStyle">#style/WindowAnimationTransition</item>
</style>
<style name="AppThemeDark" parent="Theme.AppCompat">
<!-- Customize your theme here. -->
<item name="android:windowAnimationStyle">#style/WindowAnimationTransition</item>
</style>
<!-- This will set the fade in animation on all your activities by default -->
<style name="WindowAnimationTransition">
<item name="android:windowEnterAnimation">#android:anim/fade_in</item>
<item name="android:windowExitAnimation">#android:anim/fade_out</item>
</style>
But instead of finish/start with new intent:
Intent intent = new Intent(this, <yourclass>.class);
startActivity(intent);
finish();
I would do:
#Override
protected void onCreate(Bundle savedInstanceState) {
// MUST do this before super call or setContentView(...)
// pick which theme DAY or NIGHT from settings
setTheme(someSettings.get(PREFFERED_THEME) ? R.style.AppThemeLight : R.style.AppThemeDark);
super.onCreate(savedInstanceState);
}
// Somewhere in your activity where the button switches the theme
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// decide which theme to use DAY or NIGHT and save it
someSettings.save(PREFFERED_THEME, isDay());
Activity.this.recreate();
}
});
The effect is as shown in the video...
The transition/animation makes the theme change seamless when you restart the activity, and this can be done by adding the items "android:windowanimationStyle" to your themes, and then referencing a style where you specifiy how the Activity should animate when it enters and exits.
Note that this makes the animation apply on all activities with that theme.
<style name="AppThemeLight" parent="Theme.AppCompat.Light">
<!-- Customize your theme here. -->
<item name="android:windowAnimationStyle">#style/WindowAnimationTransition</item>
</style>
<style name="AppThemeDark" parent="Theme.AppCompat">
<!-- Customize your theme here. -->
<item name="android:windowAnimationStyle">#style/WindowAnimationTransition</item>
</style>
<!-- This will set the fade in animation on all your activities by default -->
<style name="WindowAnimationTransition">
<item name="android:windowEnterAnimation">#android:anim/fade_in</item>
<item name="android:windowExitAnimation">#android:anim/fade_out</item>
</style>
Then, when you want to change theme you could do this when clicking a button:
AppSettings settings = AppSettings.getInstance(this);
settings.set(AppSettings.Key.USE_DARK_THEME,
!settings.getBoolean(AppSettings.Key.USE_DARK_THEME));
Intent intent = new Intent(this, <yourclass>.class);
startActivity(intent);
finish();
Then in your onCreate method, use the setTheme() to apply the theme that is currently set in AppSettings like this:
AppSettings settings = AppSettings.getInstance(this);
setTheme(settings.getBoolean(AppSettings.Key.USE_DARK_THEME) ? R.style.AppThemeDark : R.style.AppThemeLight);
super.onCreate(savedInstanceState);
setContentView(<yourlayouthere>);
Check out this gist for reference: https://gist.github.com/alphamu/f2469c28e17b24114fe5
for those who are trying to find solution for android version 10 or updated.
to set dark/light mode use this:
AppCompatDelegate.setDefaultNightMode(state) //state can be AppCompatDelegate.MODE_NIGHT_YES or AppCompatDelegate.MODE_NIGHT_NO
it will change the display of your app but with a flicker
to avoid the activity recreation flicker (for smooth transition), in your activity add the below method
#Override
public void recreate() {
finish();
overridePendingTransition(R.anim.anime_fade_in,
R.anim.anime_fade_out);
startActivity(getIntent());
overridePendingTransition(R.anim.anime_fade_in,
R.anim.anime_fade_out);
}
setTheme() before super.onCreate(savedInstanceState) in GKA answer is perfect approach and work well, thanks to GKA.
but it creates new instances for all resources again, including activities, fragments, and recycler views. I think it may be heavy work and cause to loss of some saved data like local variables.
accourding to google document: https://developer.android.com/reference/android/app/Activity#recreate()
Cause this Activity to be recreated with a new instance. This results
in essentially the same flow as when the Activity is created due to a
configuration change -- the current instance will go through its
lifecycle to onDestroy() and a new instance then created after it.
there is another approach that you can change the theme programmatically with code (Java or Kotlin), in this approach you don't need to recreate all resources, and also you can use custom animation like ripple.
check my GitHub library:
https://github.com/imandolatkia/Android-Animated-Theme-Manager
in this library, you can create your custom themes and change them dynamically with ripple animation without recreating any resources.
Simply efficient one liner in fragment:
requireActivity().recreate();
For activity:
recreate();
There isn't anything preventing you from calling setTheme() and then setContentView() again. You'll just need to restructure your app a bit so that, if you change the theme, you need to reinitialize any member variables you might have that are holding references to View objects.
I have successfully implemented ActionBar-PullToRefresh in my code. Now whenever I refresh the list it shows "Loading ..." text in ActionBar.
So how to change that text in ActionBar. Do I directly change the string in the library or is there any other way to do that...
Approved approach from the samples
Source: https://github.com/chrisbanes/ActionBar-PullToRefresh/tree/master/samples
Create a theme with text overrides (e.g. ptrPullText),
that is, res/values/styles.xml:
<resources>
<style name="Theme.Holo.CustomPtrHeader" parent="android:Theme.Holo">
<item name="ptrHeaderStyle">#style/Widget.Custom.PtrHeader</item>
</style>
<style name="Widget.Custom.PtrHeader" parent="android:Widget">
<item name="ptrRefreshingText">Pulling down the internet</item>
</style>
</resources>
Apply the custom theme to your activity in AndroidManifest.xml
<activity
...
android:theme="#style/Theme.Holo.CustomPtrHeader" />
or Register you own HeaderTransformer
For the example on how to do this, please see the GridView sample.
or A little hackier way
Please note that setPullText is not on the HeaderTransformer interface, it's an instance method of DefaultHeaderTransformer:
attacher = PullToRefreshAttacher.get(this);
attacher.addRefreshableView(listView, this);
transformer = ((DefaultHeaderTransformer)attacher.getHeaderTransformer());
transformer.setRefreshingText("Pulling down the internet");