Change app theme globally programatically - java

I am writing an app which has both light and dark modes as declared here:
styles.xml
<style name="Noon" parent="Theme.AppCompat.NoActionBar">
<item name="upper_bg">#drawable/day_sky_top</item>
<item name="lower_bg">#drawable/day_sky</item>
<item name="android:statusBarColor">#color/colorPrimaryDark</item>
</style>
<style name="Night" parent="Theme.AppCompat.NoActionBar">
<item name="upper_bg">#drawable/night_sky_top</item>
<item name="lower_bg">#drawable/night_sky</item>
<item name="android:statusBarColor">#color/colorNightDark</item>
</style>
By following this answer, I created the following file:
/res/values/attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="customAttrs">
<attr name="upper_bg" format="reference" />
<attr name="lower_bg" format="reference" />
</declare-styleable>
</resources>
And customized my ImageViews like this:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="#+id/top_bg"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.65"
android:src="?attr/upper_bg"/>
<ImageView
android:id="#+id/bottom_bg"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.35"
android:src="?attr/lower_bg"/>
</LinearLayout>
(Note that this is part of the code, all tags are properly closed.)
Everything works well provided I have:
boolean night = true;
setTheme(night ? R.style.Night : R.style.Noon);
setContentView(R.layout.activity_main); // or whatever activity I'm in.
on every single Activity of my app. Is there a way to run this code ONCE so that my theme changes globally?

You can still add a BaseActivity to then override override fun onCreate(), delegating it the responsibility of setTheme() for any other Activity that inherits from it.
override fun onCreate(savedInstanceState: Bundle?) {
val night = true
setTheme(if (night) R.style.Night else R.style.Noon)
}
if you don't prefer BaseActivity, you can create an extension function somewhere in charged of set theme according user preferences:
fun Activity.setTheme() {
val night = true
// Or even have more than two theme styles
this.setTheme(if (night) R.style.Night else R.style.Noon)
}
To then be called like this:
override fun onCreate(savedInstanceState: Bundle?) {
setTheme()
}
UPDATE: Java code
This class would be your base class for each required Activity
public abstract class BaseActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
boolean night = true;
setTheme(night ? R.style.Night : R.style.Noon);
}
}
So now, imagine you have to implement "Feature 1" and "Feature 2", so that, you just inherits them from BaseActivity.
"Feature 1":
public class Feature1Activity extends BaseActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // <- BaseActivity's onCreate() will set theme for you
setContentView(R.layout.activity_feature_1);
}
}
"Feature 2":
public class Feature2Activity extends BaseActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // <- BaseActivity's onCreate() will set theme for you
setContentView(R.layout.activity_feature_2);
}
}

Yes you can !
You have to use method setDefaultNightMode() of class AppCompatDelegate that take the value of the theme you want to apply , the values available is MODE_NIGHT_NO & MODE_NIGHT_YES & MODE_NIGHT_FOLLOW_SYSTEM for light , night and phone default theme respectively , you can do something like this :
AppCompatDelegate.setDefaultNightMode(THE_MODE_YOU_WANT);
Its important to note that starting with AppCompat v1.0.0 , when this method get called it recreates all running activity to apply the theme .
If you are running Api 29 or higher , you should consider using Force Dark , you can check it all in the official document to get better understanding of it .
Enjoy !

Related

Adding a Button to a Pre-existing ToolBar from the Theme

So far, it seems that I need to provide a custom Toolbar in order to add any Button. From my meager understanding, I can only get "3 dots" to show in the right-side of the Toolbar given by the Theme. On top of that, the "3 dots" button appears to only allow a menu of items.
The following code causes a crash:
toolbar = findViewById( R.id.notes_toolbar );
setSupportActionBar( toolbar );
And thus, I get:
Caused by: java.lang.IllegalStateException: This Activity already has an action bar supplied by the window decor. Do not request Window.FEATURE_SUPPORT_ACTION_BAR and set windowActionBar to false in your theme to use a Toolbar instead.
Avoiding a re-write of several of several class files, is there a simple way of addressing this?
Thank you kindly.
styles.xml :
<resources>
<!-- 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>
</resources>
Course_NoteTaking_Activity.java :
public class Course_NoteTaking_Activity extends AppCompatActivity {
private Button saveButton;
private EditText notes_EditText;
private Toolbar toolbar;
#Override
protected void onCreate( Bundle savedInstanceState ) {
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_course_notetaking );
toolbar = findViewById( R.id.notes_toolbar );
//TODO CAUSES A CRASH FROM PRE-EXISTING TOOLBAR.
//setSupportActionBar( toolbar );
//getSupportActionBar().setDisplayHomeAsUpEnabled( false );
//getSupportActionBar().setTitle( "Notes for the Course" );
Intent intent = getIntent();
String testString = intent.getStringExtra( "notes" );
saveButton = findViewById( R.id.notes_saveButtonXML );
saveButton.setOnClickListener( new View.OnClickListener() {
#Override
public void onClick( View view ) {
Intent returnIntent = new Intent();
String transferString = "Just testing... 1, 2, and a 3!!!";
returnIntent.putExtra( "return_Notes", transferString );
}
});
notes_EditText = findViewById( R.id.notes_EditTextXML );
notes_EditText.setText( testString );
}
}
activity_course_notetaking.xml :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/notes_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="4dp"
>
<Button
android:layout_width="wrap_content"
android:layout_height="8dp"
android:text="Test Button"
android:layout_gravity="right"
/>
</android.support.v7.widget.Toolbar>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
android:scrollbarAlwaysDrawVerticalTrack="true"
android:scrollbars="vertical"
android:showDividers="none"
tools:context="com.weslange.Term_Scheduling.Course_ChangingDetails_Activity"
>
<Button
android:id="#+id/notes_saveButtonXML"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Return to the Course's Details (Not Saved Yet)"
android:layout_marginVertical="2dp"
/>
<EditText
android:id="#+id/notes_EditTextXML"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="textPersonName|textCapWords"
android:imeOptions="actionDone"
android:layout_marginVertical="2dp"
/>
</LinearLayout>
</RelativeLayout>
it seems that I need to provide a custom Toolbar in order to add any Button
You do not need a custom Toolbar to add action bar items that show up as buttons in the action bar. You are welcome to use a Toolbar, of course, but that is not necessary.
From my meager understanding, I can only get "3 dots" to show in the right-side of the Toolbar given by the Theme
Or, you can inflate a menu resource, and add action bar items that either show up in the overflow ("3 dots") or as buttons (if there is room). This is the classic way of adding things to the action bar, and you can do it with Toolbar as well.
is there a simple way of addressing this?
In terms of the crash, don't use a theme that has an action bar. For example, you could replace parent="Theme.AppCompat.Light.DarkActionBar" with parent="Theme.AppCompat.Light.NoActionBar".

How to consider variation while switching theme?

I'm Working on an android app that has a requirement to switch theme based on the themeCode given from server. I'm using sharePref to save the theme code and applying it with setTheme(R.style.themeName);. Its working fine till the basic theme attributes like
colorPrimary
colorPrimaryDark
colorAccent
windowActionBar
windowNoTitle
For this I has created different styles in styles.xml. But I have a limitation that some fields say EditText has variation as EditText
person name
email
phone
password etc.
And similarly TextView has variation as TextView
Heading
Single Line
Mutiline
Link etc.
Before multi-theme requirement I had created separate themes for all as
Apptheme.Edittext.email
Apptheme.Edittext.Password
Apptheme.Edittext.PersonName etc.
And was applying to specific view in xml like
style="#style/AppTheme.EditText.PersonName"
Now I have viewed many tutorials/posts but did not find solution to the variations in attribute. Please help to apply these variation, I'll be thankful for this.
Regards:
Inzimam Tariq
In my opinion changing app theme at runtime, will definitely need to reload activity; this in most cases will create issues at some point (if project is extended to a mid scale, having a user control like toggle or a switch and if user taps switch repeatedly app may easily crash)
I would suggest to use custom control classes (Textviews, Buttons..etc); wherein this properties are differentiated with current theme value from sharedPref.
This approach has a con; it will require to change all views manually of current screen and those in already rendered in memory(if any), rest all it will be much smoother transition in compare to our conventional approach
EDIT: Example for CustomTextView ##
This is an example for customtextview class
public class CustomTextView extends android.support.v7.widget.AppCompatTextView {
private static final String TAG = "TextView";
private Typeface tf = null;
private SharedPreferenceUtils preferenceUtils = SharedPreferenceUtils.getInstance();
/**
* #param context:This is an abstract class whose implementation is provided by Android Operating System.
* #param attrs:A collection of attributes, as found associated with a tag in an XML document.
* #param defStyle:
*/
public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
if (preferenceUtils.getBooleanValue(PrefsKeyValue.bTheme)) {
this.setTextColor(ResourceUtils.getColor(R.color.lightThemeTextColor));
} else {
this.setTextColor(ResourceUtils.getColor(R.color.colorWhite));
}
try {
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.CustomEditText, defStyle, 0);
String str = a.getString(R.styleable.CustomTextView_FontEnum);
int original = a.getInt(R.styleable.CustomEditText_FontEnum, 0);
CustomEnum.CustomFontType customEnumValue = CustomEnum.CustomFontType.fromId(a.getInt(R.styleable.CustomEditText_FontEnum, 0));
a.recycle();
switch (customEnumValue) {
case BOLD:
setTypeface(HelveticaNeueBold.getInstance(context).getTypeFace());
break;
case LIGHT:
setTypeface(HelveticaNeueMedium.getInstance(context).getTypeFace());
break;
case REGULAR:
setTypeface(HelveticaNeue.getInstance(context).getTypeFace());
break;
default:
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
public CustomTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public boolean setCustomFont(Context ctx, String asset) {
try {
tf = Typeface.createFromAsset(ctx.getAssets(), asset);
} catch (Exception e) {
LogUtils.LogE(TAG, "Could not get typeface: " + e.getMessage());
return false;
}
setTypeface(tf);
return true;
}}
Herein I have changed textcolor in accordance to theme value from sharedPref
if (preferenceUtils.getBooleanValue(PrefsKeyValue.bTheme)) {
this.setTextColor(ResourceUtils.getColor(R.color.lightThemeTextColor));
} else {
this.setTextColor(ResourceUtils.getColor(R.color.colorWhite));
}
Then use this class as textview tag in xml file.
<com.mypkg.customview.CustomTextView
style="#style/signup_textViewStyle"
android:text="#string/activity_login_password" />
I believe, you can handle property variation with theme for controls in same manner.
What you can do is create custom attributes for your view types (e.g. TextView.Person, TextView.Date...), in your xml you can reference the attributes and then define the attributes in different themes. For instance, you style.xml could be
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar" >
<item name="TextView.Date">#style/DateTextViewDefault</item>
</style>
<style name="DateTextViewDefault">
<item name="android:textColor">#ff333333</item>
<item name="android:fontFamily">monospace</item>
</style>
<!-- Theme A -->
<style name="AppTheme.A">
<item name="colorPrimary">#3F51B5</item>
<item name="colorPrimaryDark">#303F9F</item>
<item name="colorAccent">#FF4081</item>
<item name="TextView.Person">#style/PersonTextViewA</item>
</style>
<style name="PersonTextViewA">
<item name="android:textSize">16sp</item>
<item name="android:fontFamily">serif</item>
<item name="android:textColor">#ff999999</item>
</style>
<!-- Theme B -->
<style name="AppTheme.B">
<item name="colorPrimary">#888888</item>
<item name="colorPrimaryDark">#555555</item>
<item name="colorAccent">#000000</item>
<item name="TextView.Person">#style/PersonTextViewB</item>
<item name="TextView.Date">#style/DateTextViewB</item>
</style>
<style name="PersonTextViewB">
<item name="android:textSize">20sp</item>
<item name="android:fontFamily">monospace</item>
<item name="android:textColor">#ff55aa</item>
</style>
<style name="DateTextViewB">
<item name="android:textColor">#ff0000BB</item>
<item name="android:fontFamily">sans-serif</item>
</style>
<attr name="TextView.Person" format="reference" />
<attr name="TextView.Date" format="reference" />
</resources>
then your activity xml layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
style="?attr/TextView.Person"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="John Doe" />
<TextView
style="?attr/TextView.Date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="31/12/1999" />
<Button
android:id="#+id/buttonA"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="THEME A" />
<Button
android:id="#+id/buttonB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="THEME B" />
</LinearLayout>
notice that the styles of the TextView are
style="?attr/TextView.Person"
and
style="?attr/TextView.Date"
AppTheme.A and AppTheme.B have 2 different resolutions for those attributes
In this example the attributes are entire styles for your views but you could easily have one style per view type (TextView.person) and then define generic attributes for single items of that style, e.g.
<attr name="TextView.Person.TextColor" format="color" />
and only change that single attribute in your themes.
Then in your Activity you just need to set the theme in onCreate with setTheme(int), the value could be in this case either R.style.AppTheme_A or R.style.AppTheme_B.
With this method you can add as many styles as you want without touching the layouts. Also, you can always define some default styles in your base theme and then only override that value in some of the custom themes, while others use the default one as for TextView.Date in the sample above.
If you want to give it a quick try, here's the code of the Activity I used to test style.xml and activity_main.xml above
class MainActivity : AppCompatActivity() {
private val prefs by lazy { getSharedPreferences("SharedPrefs", Context.MODE_PRIVATE) }
private var customTheme: Int
get() = prefs.getInt("theme", R.style.AppTheme_A)
set(value) = prefs.edit()
.putInt("theme", value)
.apply()
.also { recreate() }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setTheme(customTheme)
setContentView(R.layout.activity_main)
buttonA.setOnClickListener { customTheme = R.style.AppTheme_A }
buttonB.setOnClickListener { customTheme = R.style.AppTheme_B }
}
}

Changing Action Bar Colour Programmatically may cause nullPointerException?

I tried to change the colour of my action bar in Android app using the following line of code:
getSupportActionBar().setBackgroundDrawable(new ColorDrawable(getResources().getColor(R.color.background_actionbar)));
However, this gives a warning that reads:
Method invocation 'getSupportActionBar().setBackgroundDrawable(new ColorDrawable(getResources().getColor(R.color.backgr...' may produce 'java.lang.NullPointerException'
Any ideas how to work around this?
Note: I am changing the colour programmatically because changing it via XML theme/style didn't work.
Using minimum SDK 16.
Testing on Android 4.4.4 device.
Yes, If you are using themes with NoActionBar then you will get the NullPointerException.
Try this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// The Action Bar is a window feature. The feature must be requested
// before setting a content view. Normally this is set automatically
// by your Activity's theme in your manifest. The provided system
// theme Theme.WithActionBar enables this for you. Use it as you would
// use Theme.NoTitleBar. You can add an Action Bar to your own themes
// by adding the element <item name="android:windowActionBar">true</item>
// to your style definition.
getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
setContentView(R.layout.main);
// experiment with the ActionBar
ActionBar actionBar = getActionBar();
actionBar.setBackgroundDrawable(new ColorDrawable(getResources().getColor(R.color.background_actionbar)));
//actionBar.hide();
}
or
You can use Toolbar
toolbar.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:fitsSystemWindows="true"
android:minHeight="?attr/actionBarSize"
android:background="#color/light_blue">
</android.support.v7.widget.Toolbar>
Include it in activity's layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include layout="#layout/toolbar" />
</LinearLayout>
</RelativeLayout>
Use this code to Activity:
public class YourActivity extends AppCompatActivity {
private Toolbar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
// Set a Toolbar to replace the ActionBar.
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//toolbar.setTitle("Setting");
}
public void setSupportActionBar(#Nullable Toolbar toolbar) {
getDelegate().setSupportActionBar(toolbar);
}
}

When i click on header, no preferences show up

I am working of settings activity for my application. I seted up two headers for preferences and then i made fragment for each header. Problem is when i click on header, nothing shows up. Thank you for your help.
Here is my preference activity
public class Preferences extends PreferenceActivity {
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.prefheads, target);
}
}
Here is first fragment
public class Prefs1 extends PreferenceFragment {
public static class SettingsFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.fragment_prefs1);
}
}
}
Here is second fragment:
public class Prefs2 extends PreferenceFragment {
public static class SettingsFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.fragment_prefs2);
}
}
}
XML files:
Headers
<?xml version="1.0" encoding="utf-8"?>
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<header
android:fragment="com.example.lubys.prefs.prefs1"
android:title="First category"
android:summary="This doesnt need summary" />
<header
android:fragment="com.example.lubys.prefs.prefs2"
android:title="Second cat"
android:summary="This is awful summary">
</header>
</preference-headers>
Fragment1:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.lubys.prefs.prefs1"
android:layout_width="match_parent"
android:layout_height="match_parent">
<PreferenceCategory
android:title="the title"
android:key="key2">
<EditTextPreference android:title="Your Name"
android:key="username"
android:summary="Please provide your username"></EditTextPreference>
<CheckBoxPreference android:title="Application Updates"
android:defaultValue="false"
android:summary="This option if selected will allow the application to check for latest versions."
android:key="applicationUpdates" />
<ListPreference
android:title="Download Details"
android:summary="Select the kind of data that you would like to download"
android:key="downloadType"
android:defaultValue="1"
android:entries="#array/c"
android:entryValues="#array/c" />
</PreferenceCategory>
</PreferenceScreen>
Fragment2:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.lubys.prefs.prefs1"
android:layout_width="match_parent"
android:layout_height="match_parent">
<PreferenceCategory
android:title="sms"
android:key="pref_key_storage_settings">
<CheckBoxPreference
android:key="saas"
android:summary="asde"
android:title="Something"
android:defaultValue="false"/>
</PreferenceCategory>
</PreferenceScreen>
check if u didn't get:
java.lang.RuntimeException:
Subclasses of PreferenceActivity must override isValidFragment(String) to verify that the Fragment class is valid!
XXX has not checked if fragment YYY is valid.
isValidFragment Android API 19
when android's isValidFragment() from PreferenceActivity gets called?
http://securityintelligence.com/new-vulnerability-android-framework-fragment-injection#.VRGSv1V_NBc

setBackgroundResource doesn't work

Well, I'm trying to change my drawer navigator whenever I change the fragment, I managed to change the ActionBar color and the Background color, but the thing is that with the Background is not enough... I saw that I declare a BackgroundResource with other colors, and when I try to change the color it does not work.
My MainActivity.xml
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Displaying Fragments -->
<FrameLayout
android:id="#+id/frame_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<!-- Displaying Drawer -->
<ListView
android:id="#+id/list_slidermenu"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#color/list_divider"
android:dividerHeight="1dp"
android:listSelector="#drawable/drawer_list_selection"
android:background="#color/list_background"/>
</android.support.v4.widget.DrawerLayout>
My colors.xml (I've tried to change it manually but I don't know how to do, then I've created as colors as items are on my drawable navigator).
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="list_item_title">#fff</color>
<color name="list_background">#458A79</color>
<color name="list_background2">#ffc591</color>
<color name="list_background3">#ab91ff</color>
<color name="list_background4">#f784fe</color>
<color name="list_background5">#91dfff</color>
<color name="list_background_pressed">#6FA698</color>
<color name="list_background_pressed2">#ffc591</color>
<color name="list_background_pressed3">#ab91ff</color>
<color name="list_background_pressed4">#f784fe</color>
<color name="list_background_pressed5">#91dfff</color>
<color name="list_divider">#fff</color>
<color name="counter_text_bg">#626262</color>
<color name="counter_text_color">#c5c4c4</color>
</resources>
And the thing that I've tried on my MainActivity.java is
private void displayView(int position) {
// update the main content with called Fragment
Fragment fragment = null;
LlistaGenericaFragment frag = null;
FragmentTransaction ft = null;
ActionBar bar = getActionBar();
bar.setBackgroundDrawable(new ColorDrawable(Color.parseColor("#256F5C")));
switch (position) {
case 0:
fragment = new MetallsAlcalinsFragment();
bar.setBackgroundDrawable(new ColorDrawable(Color.parseColor("#ffc591")));
mDrawerList.setBackground(new ColorDrawable(Color.parseColor("#ffc591"))); //set the background but not the ListView
mDrawerList.setBackgroundResource(R.color.list_background2); //Don't see any change
break;
I know I'm doing something wrong, but I don't get what... Could you explain me how can I change this each time I change the fragment?
What you would want to do then is create a drawable selector -> list_selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/list_background2" android:state_pressed="true"/>
<item android:drawable="#color/list_background" />
</selector>
then on your list add this as a selector:
mDrawerList.setSelector(R.drawable.list_selector);
If you want to do this every time something happens in your fragment, you would create an interface:
public iterface TalkToActivity(){
public void sendChangeEvent(int changeType);
}
in Your fragment create a local variable:
TalkToActivity m_callBack;
Then in your onAttach method of the fragment:
#Override
public void onAttach(Activity activity) {
// Call to the Super Class
super.onAttach(activity);
// Attempt to Add the Interface
try {
m_callBack = (TalkToActivity) activity;
} catch (ClassCastException e) {
// Print to LogCat if the Parent Did not implement the interface
Log.e(FRAGMENT_TAG, "Failed to implement interface in parent.", e);
}
}
and then in the event that you want to capture and communicate the change:
public void buttonWasPressed(int changeType){
if(m_callBack != null){
m_callBack.sendChangeEvent(changeType);
}
}
Finally, in your activity make your activity 'implents TalkToActivity' which will force you to override the method sendChangeEvent and in this method
#Override
public void sendChangeEvent(int changeType){
switch(changeType){
case 0:
// Update you UI like above
// ...
if(mDrawerList != null){
mDrawerList.setSelector(R.drawable.list_selector);
}
break;
default: break;
}
}
NOTE: If you have list_item.xml and an adapter:
<?xml version="1.0" encoding="utf-8" ?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/linearLayoutItem"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/textViewNavItem"
android:layout_height="wrap_content"
android:layout_width="match_parent"/>
</LinearLayout
Then get a reference to the parent item
LinearLayout linearlayoutItem = (LinearLayout) findViewById(R.id.linearLayoutItem);
and dynamically change the background of this with the above approach...
linearLayoutItem.setBackground(R.drawable.list_selector);
but create 6 different list_selector_num1.xml etc... and change this using the switch statement. but you need the adapter to have a method like
public void updateViewBackground(Drawable drawable) {}
which will be in your adapter to do this.
For a demo on this communication between Fragments & activities look at:
https://github.com/lt-tibs1984/InterfaceDemo
Fragments talk to the main activity via bundle and onPause()
Passing data between a fragment and its container activity

Categories