How to _Really_ Programmatically Change Primary and Accent Color in Android Lollipop

How to _really_ programmatically change primary and accent color in Android Lollipop?

Themes are immutable, you can't.

How to programmatically change the primary color in Android L?

You can, of course, implement custom subclasses of View that have methods for setting colors.

You can also define multiple themes with you various color schemes.

Views look up theme information from the context when they are created. So to change the styles applied from a theme you will have to recreate your view hierarchy with a context that uses the right theme.

One way to do that, is to create a new ContextThemeWrapper and then get a LayoutInflator that uses that theme wrapper, remove the old version of your layout and re-inflate your layout.

Roughly:

ContextThemeWrapper themeWrapper = new ContextThemeWrapper(this, R.style.AppThemeWithColorScheme2);
LayoutInflater layoutInflater = LayoutInflater.from(themeWrapper);
viewContainer.removeAllViews();
layoutInflater.inflate(R.layout.my_layout, viewContainer, true );

If you are using Action Bar, that may be a bit more tricky, because the Action Bar is created once per activity.

How to apply colors programmatically to app theme?

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);
}

Let the user set light or dark theme plus accent color

The approach I have used is that, keep your colors in an array and let users select the color and store the index of selected color in preferences. So once when the activity is loading read the stored color and set the color accordingly

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(ContextCompat.getColor(this,colors.getResourceId(chapter_key-1, 0)));
}

main screen where they select the book

package com.**********.app.customViews;

/**
* Created by pakistantechhouse on 18/02/2017.
*/

import android.content.Context;
import android.graphics.Canvas;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.widget.RelativeLayout;

import com.**********.app.R;


public class CRelativeLayout extends RelativeLayout {


public CRelativeLayout(Context context) {
super(context);
if (!isInEditMode()) {
//TODO get your color here from the preferences and apply to the view
this.setBackgroundColor(ContextCompat.getColor(context, R.color.colorPrimary));
}
}

public CRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
if (!isInEditMode()) {
//TODO get your color here from the preferences and apply to the view
this.setBackgroundColor(ContextCompat.getColor(context, R.color.colorPrimary));

}
}

public CRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
if (!isInEditMode()) {
//TODO get your color here from the preferences and apply to the view

this.setBackgroundColor(ContextCompat.getColor(context, R.color.colorPrimary));
}
}

protected void onDraw (Canvas canvas) {
super.onDraw(canvas);

}

}

changing app material theme colorPrimaryDark programatically in android?

There is no way such as per current available methods of android sdk. So Instead of changing colorPrimaryDark attribute programatically, I am applying different themes for different activities

Dynamically change android's accent color

I found the solution!

  1. All you have to put accent (or any other) color for light theme in MyApp.Android\Resources\values\colors.xml and for dark theme in MyApp.Android\Resources\values-night\colors.xml. Then reference that color by name in your theme in styles.xml <item name="colorAccent">@color/colorAccent</item>.
    Now, when device would switch to dark theme accent color also would change.
  2. Now. What if you have manual theme control in your app? You can force Android to display color for light or dark theme. Add similar interface to the shared project:
namespace MyApp.Core.Models.InterplatformCommunication
{
public interface INightModeManager
{
NightModeStyle DefaultNightMode { get; set; }
}

public enum NightModeStyle
{
/// <summary>
/// An unspecified mode for night mode.
/// </summary>
Unspecified = -100,

/// <summary>
/// Mode which uses the system's night mode setting to determine if it is night or not.
/// </summary>
FollowSystem = -1,

/// <summary>
/// Night mode which uses always uses a light mode, enabling non-night qualified resources regardless of the time.
/// </summary>
No = 1,

/// <summary>
/// Night mode which uses always uses a dark mode, enabling night qualified resources regardless of the time.
/// </summary>
Yes = 2,

/// <summary>
/// Night mode which uses a dark mode when the system's 'Battery Saver' feature is enabled, otherwise it uses a 'light mode'.
/// </summary>
AutoBattery = 3
}
}

  1. Add this implementation in Android project. Setting AppCompatDelegate.DefaultNightMode forces the app to load resources for light or dark theme without restarting the app.
[assembly: Xamarin.Forms.Dependency(typeof(NightModeManager))]
namespace MyApp.Droid.Dependences
{
public class NightModeManager : INightModeManager
{
public NightModeStyle DefaultNightMode
{
get => (NightModeStyle)AppCompatDelegate.DefaultNightMode;
set => AppCompatDelegate.DefaultNightMode = (int)value;
}
}
}

  1. Add this logic when changing theme of your app (AppTheme is a custom enum):
private static void UpdateNativeStyle(AppTheme selectedTheme)
{
NightModeStyle style = selectedTheme switch
{
AppTheme.Dark => NightModeStyle.Yes,
AppTheme.Light => NightModeStyle.No,
AppTheme.FollowSystem => NightModeStyle.FollowSystem,
_ => throw new InvalidOperationException("Unsupported theme"),
};

var nightModeManager = DependencyService.Get<INightModeManager>();
nightModeManager.DefaultNightMode = style;
}

More info about this:

  • https://medium.com/androiddevelopers/appcompat-v23-2-daynight-d10f90c83e94
  • https://www.journaldev.com/19352/android-daynight-theme-night-mode


Related Topics



Leave a reply



Submit