Setting the value for custom Attribute android - android

I have a custom attribute say like this :
<attr name="colorPrimarySdk" format="color"/>
<attr name="colorSecondarySdk" format="color"/>
<attr name="colorAccentSdk" format="color"/>
And I am using them in my styles like this:
<style name="MyTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">?colorPrimarySdk</item>
<item name="colorPrimaryDark">?colorSecondarySdk</item>
<item name="colorAccent">?colorAccentSdk</item>
</style>
Now what I want is to set the value of my attributes dynamically from the code like, say :
colorPrimarySdk.value = myCustomColor
I have already tried using TypedValue and accessing the attribute itself.
If anyone can help changing the value for my custom attribute, that would be a great help. Thanks in advance.

it's hard :)
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;
}
...
}

Define the colors for the specific theme in your colors file:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="my_link_color1">#0077CC</color>
<color name="my_link_color2">#626262</color>
</resources>
Create file res/values/attrs.xml with contents:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="myLinkColor" format="reference" />
</resources>
Suppose we have 2 themes in our styles.xml (Theme1 and Theme2) define:
<style name="Theme1" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="myLinkColor">#color/my_link_color1</item>
</style>
<style name="Theme2" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="myLinkColor">#color/my_link_color2</item>
</style>
Use the color in the XML:
android:textColor="?attr/myLinkColor"

Related

Android DarkMode : Value night not working

I am developing Day/Night feature in my app so I read those documents and start developing it.
It's working fine with default value in Day or Night
with deligate method AppCompatDelegate.setDefaultNightMode(*).
For customize night theme color I create values-night folder and inside I create colors.xml file like below.
res -> values -> colors.xml
res -> values-night -> colors.xml
After I place that color but not applying in Night theme! Its very strange why value-night colors is not applying always its showing default night color?
I have researched some but can't find the solution.
Note: Recreate activity is resolved my issue but I don't want to recreate
Here is my build.gradle file
Advance Thanks.
Try below dark mode code which I am use.
Step - 1
First of create night folder into your resource file like below image(i.e. values-night)
Step - 2
Create styles,strings and colors xml file for night mode same as below image and add your night mode color,string and style which you want to show in your app when night mode was apply.
For better user experience add window Animation in your style.
values --> style.xml
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
</style>
<style name="NoActionBarAppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/white</item>
<item name="colorPrimaryDark">#color/white</item>
<item name="colorAccent">#color/main_click_txt</item>
<item name="android:windowLightStatusBar" tools:targetApi="m">true</item>
</style>
<!-- Add this theme where you change mode -->
<style name="NoActionBarWithChangeTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/white</item>
<item name="colorPrimaryDark">#color/white</item>
<item name="colorAccent">#color/main_click_txt</item>
<item name="android:windowAnimationStyle">#style/WindowAnimationTransition</item>
<item name="android:windowLightStatusBar" tools:targetApi="m">true</item>
</style>
<!-- This will set the fade in animation on your change theme activity by default -->
<style name="WindowAnimationTransition">
<item name="android:windowEnterAnimation">#anim/fade_in</item>
<item name="android:windowExitAnimation">#anim/fade_out</item>
</style>
</resources>
values-night --> style.xml
<!-- Base application theme. values-night.xml -->
<style name="NoActionBarAppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/white</item>
<item name="colorPrimaryDark">#color/white</item>
<item name="colorAccent">#color/main_click_txt</item>
<item name="android:windowLightStatusBar" tools:targetApi="m">true</item>
</style>
<!-- Add this theme where you change mode -->
<style name="NoActionBarWithChangeTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/white</item>
<item name="colorPrimaryDark">#color/white</item>
<item name="colorAccent">#color/main_click_txt</item>
<item name="android:windowAnimationStyle">#style/WindowAnimationTransition</item>
<item name="android:windowLightStatusBar" tools:targetApi="m">true</item>
</style>
<!-- This will set the fade in animation on your change activity by default -->
<style name="WindowAnimationTransition">
<item name="android:windowEnterAnimation">#anim/fade_in</item>
<item name="android:windowExitAnimation">#anim/fade_out</item>
</style>
fade_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="#android:anim/linear_interpolator">
<alpha
android:duration="2000"
android:fromAlpha="0.0"
android:toAlpha="1.0">
</alpha>
</set>
fade_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/linear_interpolator">
<alpha
android:duration="2000"
android:fromAlpha="1.0"
android:toAlpha="0.0" >
</alpha>
</set>
Step - 3
Add this below code in your splash screen if you want to set night mode as per device mode first time when application installed.
#Override
protected void onCreate(Bundle savedInstanceState) {
if (!CommonUtils.isToogleEnabled(SplashActivity.this)) {
if (CommonUtils.isDarkMode(SplashActivity.this)) {
CommonUtils.setIsNightModeEnabled(SplashActivity.this, true);
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
} else {
CommonUtils.setIsNightModeEnabled(SplashActivity.this, false);
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
}
} else {
if (CommonUtils.isNightModeEnabled(SplashActivity.this)) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
}
}
super.onCreate(savedInstanceState);
...
//your code
}
Step - 4
Add this below code in your all activity
#Override
protected void onCreate(Bundle savedInstanceState) {
if (CommonUtils.isNightModeEnabled(MainActivity.this)) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
}
super.onCreate(savedInstanceState);
...
//your code
}
Step - 5
Change mode using below code
private WeakReference<Activity> mActivity;
binding.imgNightMode.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mActivity = new WeakReference<Activity>(MainActivity.this);
CommonUtils.setIsToogleEnabled(MainActivity.this, true);
if (CommonUtils.isNightModeEnabled(MainActivity.this)) {
CommonUtils.setIsNightModeEnabled(MainActivity.this, false);
mActivity.get().recreate();
} else {
CommonUtils.setIsNightModeEnabled(MainActivity.this, true);
mActivity.get().recreate();
}
}
});
Below methods are CommonUtils.
private static final String NIGHT_MODE = "NIGHT_MODE";
private static final String TOOGLE = "TOOGLE";
public static boolean isNightModeEnabled(Context context) {
SharedPreferences mPrefs = context.getSharedPreferences("MY_PREF", MODE_PRIVATE);
return mPrefs.getBoolean(NIGHT_MODE, false);
}
public static void setIsNightModeEnabled(Context context, boolean isNightModeEnabled) {
SharedPreferences mPrefs = context.getSharedPreferences("MY_PREF", MODE_PRIVATE);
SharedPreferences.Editor editor = mPrefs.edit();
editor.putBoolean(NIGHT_MODE, isNightModeEnabled);
editor.apply();
}
public static void setIsToogleEnabled(Context context, boolean isToogleEnabled) {
SharedPreferences mPrefs = context.getSharedPreferences("MY_PREF", MODE_PRIVATE);
SharedPreferences.Editor editor = mPrefs.edit();
editor.putBoolean(TOOGLE, isToogleEnabled);
editor.apply();
}
public static boolean isToogleEnabled(Context context) {
SharedPreferences mPrefs = context.getSharedPreferences("MY_PREF", MODE_PRIVATE);
return mPrefs.getBoolean(TOOGLE, false);
}
public static boolean isDarkMode(Activity activity) {
return (activity.getResources().getConfiguration()
.uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;
}
I hope this can help you!
Thank You.
Change appcompat dependency from 1.1.0 to 1.0.0, There is some issue to update resource in 1.1.0. This trick worked for me.
implementation 'androidx.appcompat:appcompat:1.1.0'//Remove
implementation 'androidx.appcompat:appcompat:1.0.0' // Add
Hope this will help you!!

How to change background color of app permanently

I want to be able to change the background color of my app so that whenever i want to change the color during runtime, i can just press a button in the app to change the background color. After the changing the color i want that it should stay there whenever i open the app again. Also i would like to know how to change the color of other activities while I am in another activity.
Thanks in advance.
my colors.xml:
<resources>
<color name="original">#25383C</color>
<color name="grey">#484849</color>
<color name="red">#881A27</color>
<color name="orange">#ffa500</color>
<color name="yellow">#CDE707</color>
<color name="green">#00ff00</color>
<color name="aqua">#00FFCC</color>
<color name="marine">#0C0C84</color>
<color name="purple">#630A86</color>
<color name="silver">#c0c0c0</color>
styles.xml(it has themes):
<resources>
<style name="original">
<item name="android:background">#25383C</item>
</style>
<style name="grey">
<item name="android:background">#484849</item>
</style>
<style name="red">
<item name="android:background">#881A27</item>
</style>
<style name="orange">
<item name="android:background">#ffa500</item>
</style>
<style name="yellow">
<item name="android:background">#CDE707</item>
</style>
<style name="green">
<item name="android:background">#00ff00</item>
</style>
<style name="aqua">
<item name="android:background">#00FFCC</item>
</style>
<style name="marine">
<item name="android:background">#0C0C84</item>
</style>
<style name="purple">
<item name="android:background">#630A86</item>
</style>
<style name="silver">
<item name="android:background">#c0c0c0</item>
</style>
You can use Android Shared Preferences to remember the selected background color for the app.So every time you open the app you can check the value of the shared preference and apply the color accordingly.
Use a common base activity class that all the other activities will derive and in the "OnCreate" and "OnResume" methods write the code to read shared preference value and apply back ground color.This way when you open any activity selected background color will be applied.
Try below code, it is tested and working.
BaseActivity Class
public class BaseActivity extends ActionBarActivity {
private static final String PREFS_NAME="color_settings";
SharedPreferences prefsReader = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
prefsReader=getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
}
#Override
public void setContentView(int layoutResID) {
super.setContentView(layoutResID);
setBackgroundColor();
}
protected void setBackgroundColor()
{
int background_resource_id= prefsReader.getInt("background_resource_id",0);
View bgView= findViewById(R.id.main_container);
bgView.setBackgroundColor(getResources().getColor(background_resource_id));
}
protected void setCurrentBackgroundColor(int colorResourceId)
{
SharedPreferences.Editor editor=getSharedPreferences(PREFS_NAME, MODE_PRIVATE).edit();
editor.putInt("background_resource_id", colorResourceId);
editor.commit();
}
}
Activity Class
public class MainActivity extends BaseActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//save the color resource value in shared pref
setCurrentBackgroundColor(R.color.red);
setContentView(R.layout.activity_main);
}
}
Colors.xml color list
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="blue" type="color">#FF33B5E5</item>
<item name="purple" type="color">#FFAA66CC</item>
<item name="green" type="color">#FF99CC00</item>
<item name="orange" type="color">#FFFFBB33</item>
<item name="red" type="color">#FFFF4444</item>
<item name="darkblue" type="color">#FF0099CC</item>
<item name="darkpurple" type="color">#FF9933CC</item>
<item name="darkgreen" type="color">#FF669900</item>
<item name="darkorange" type="color">#FFFF8800</item>
<item name="darkred" type="color">#FFCC0000</item>
</resources>
For doing such thing you can maintain a database to store the values for the different colors.
Now, Whenever you press the button after choosing the particular color for your application you just have to update the color value in your database.
In onCreate() method of your MainActivity(Launcher Activity), You just have to retrieve the color value from the field of database and can set it in your application.

Resources NotFoundException getColor() that uses colorAccent attribute

Why can't this color be resolved programmatically:
Definition of the style.xml:
<style name="MyTheme.Light" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorAccent">#ff0000</item>
</style>
Definition of colors.xml:
<color name="button_color">?attr/colorAccent</color>
Source:
getResources().getColor(R.color.button_color);
Throws the following exception:
android.content.res.Resources$NotFoundException: Resource ID #0x7f07001b type #0x2 is not valid
at android.content.res.Resources.getColor(Resources.java:752)
...
Change:
Definition of the style.xml:
<style name="MyTheme.Light" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorAccent">#color/button_color</item>
</style>
Definition of colors.xml:
<color name="button_color">#ff0000</color>
Source:
getResources().getColor(R.color.button_color);
TypedValue typedValue = new TypedValue();
TypedArray typedArray = context.obtainStyledAttributes(typedValue.data, new int[] { android.R.attr.colorAccent });
int color = typedArray.getColor(0, 0);
This works for me. You might be able to replace android.R.attr.colorAccent with your color resource.

Set style programmatically does not work?

This is the code of a compound view I wrote. It uses android.support.v7.widget.CardView as parent class:
public class ItemListItem extends CardView {
TextView tvName;
ImageView ivIcon;
public ItemListItem(Context context) {
super(context, null, R.style.GreenCardView);
LayoutInflater.from(context).inflate(R.layout.item_list_item, this, true);
tvName = (TextView) findViewById(R.id.tvName);
ivIcon = (ImageView) findViewById(R.id.ivIcon);
}
public void setItem(Item item)
{
tvName.setText(item.getName());
}
}
Although I'm adding a custom style (R.style.GreenCardView) to the super constructor call at line 7, it initializes every instance of this class with the default white style. Why is this the case?
edit:
style
<style name="GreenCardView" parent="CardView.Dark">
<item name="contentPadding">#dimen/default_margin</item>
<item name="cardBackgroundColor">#color/guiColor</item>
<item name="cardElevation">#dimen/cardElevation</item>
<item name="cardCornerRadius">#dimen/cardCornerRadius</item>
<item name="android:foreground">?android:attr/selectableItemBackground</item>
</style>
The third argument to the View constructor needs to be a theme attribute, e.g. R.attr.myCardViewStyle. You will need to specify the value of the attribute in your app theme and define the attribute in attrs.xml.
res/values/attrs.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
...
<attr name="myCardViewStyle" format="reference" />
</resources>
res/values/themes.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
...
<style name="AppTheme" parent="...">
...
<item name="myCardViewStyle">#style/GreenCardView</item>
</style>
</resources>

How to use Custom Selector Styles on a TextView

I'm trying to figure out how to add an outer glow to a TextView when it's touched. The approach I'm working with is to use a Selector, but it doesn't seem to be working.
I've got the following structure
layout\HomeView.axml
<TextView
android:id="#+id/textview1"
android:clickable="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
style="#drawable/control_selector_state" />
drawable\control_selector_state.xml
<!-- yes these are all the same for testing purposes -->
<?xml version="1.0" encoding="utf-8" ?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true"
style="#style/control_style_focused"/>
<item android:state_focused="true"
android:state_pressed="true"
style="#style/control_style_focused" />
<item android:state_pressed="true"
style="#style/control_style_focused" />
<item style="#style/control_style_focused" />
</selector>
values\styles.xml
<resources>
<style name="control_style_focused">
<item name="android:shadowColor">#0000ff</item>
<item name="android:textColor">#ff0000</item>
<item name="android:shadowDx">0.0</item>
<item name="android:shadowRadius">8</item>
</style>
</resources>
The problem I'm having is that my TextView text is white, and the style doesn't seem to be applying.
How do I get this style to apply to my TextView?
so as #Longwayto said, selector styles are only available for drawables. That doesn't mean it's impossible.
Here's a working approach.
First you create a custom TextView that extends TextView
public class MyTextView: TextView
{
private readonly Context _context;
public FontIconTextView(Context context, IAttributeSet attrs) : base(context)
{
_context = context;
Initialize(attrs);
}
private void Initialize(IAttributeSet attrs)
{
var a = _context.Theme.ObtainStyledAttributes(attrs, Resource.Styleable.MyTextView, 0, 0);
_touchGlowColor = a.GetString(Resource.Styleable.MyTextView_TouchGlowColor);
_touchGlowSize = a.GetInteger(Resource.Styleable.MyTextView_TouchGlowSize, 0);
Initialize();
}
private void Initialize()
{
// other initialize stuff happens here...
}
private int _touchGlowSize;
private string _touchGlowColor;
public override bool OnTouchEvent(MotionEvent motionEvent)
{
if (Enabled)
{
var color = string.IsNullOrEmpty(_touchGlowColor) ? new Color(255, 255, 255, 255) : Color.ParseColor(_touchGlowColor);
switch (motionEvent.Action)
{
case MotionEventActions.Down:
SetShadowLayer(_touchGlowSize, 0, 0, color);
break;
case MotionEventActions.Up:
case MotionEventActions.Cancel:
SetShadowLayer(0, 0, 0, new Color(255, 255, 255, 255));
break;
}
}
return base.OnTouchEvent(motionEvent);
}
}
then, you have to go into your values directory and specify your custom attributes.
Resources\values\CustomBindingAttributes.xml
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<declare-styleable name="MyTextView">
<attr name="TouchGlowColor" format="string" />
<attr name="TouchGlowSize" format="integer" />
</declare-styleable>
</resources>
All of the above will be reusable across your entire application... no more duplicating shit on every view.
Lastly, here's how your button will look.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- obviously the foo/bar is just to show that you add android attrs like normal -->
<some.name.space.MyTextView
android:foo="foo"
amdroid:bar="bar"
local:TouchGlowColor="#66e400"
local:TouchGlowSize="20" />
</LinearLayout>
one gotcha I ran into is setting TouchGlowSize to 30 caused the app to crash. not sure why atm

Categories

Resources