I have a problem with switching activity theme programmatically. I have an router activity that decide which activity to route based on some condition. And that router activity can be open at two time : application start up time with Splash screen theme and calling startActivity from somewhere to make router decision with NoDisplay or Transparent theme. I've set splash theme in manifest and it works fine. But I can't change to transparent theme at runtime when calling startactivity. It shows black background color instead of transparent.
RouterActivity:
override fun onCreate(savedInstanceState: Bundle?) {
val transparent = intent.extras?.getBoolean("Need_Transparent")?:false
if(transparent) setTheme(R.style.Theme_Transparent)
super.onCreate(savedInstanceState)
//no setContentView()
}
styles.xml
<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="Theme.Transparent" parent="android:Theme">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">#android:color/transparent</item>
<item name="android:windowContentOverlay">#null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:backgroundDimEnabled">false</item>
</style>
<style name="Theme.Splash" parent="android:Theme">
<item name="android:windowBackground">#android:color/holo_green_light</item>
</style>
AndroidManifest.xml:
<activity
android:name=".RouterActivity"
android:theme="#style/Theme.Splash">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
So how can I make that RouterActivity with two themes: Splash (default in manifest) and Transparent theme (open with startActivity from other activity).
I am giving this solution in Java, Hopefully same logic should also work in Kotlin,
Best way to set theme is overriding the Resources Theme in your class and putting the same logic which is present in OnCreate method
#Override
public Resources.Theme getTheme() {
Resources.Theme theme = super.getTheme();
if(useAlternativeTheme){
theme.applyStyle(R.style.AlternativeTheme, true);
}
// you could also use a switch if you have many themes that could apply
return theme;
}
Related
i embedding a code that contains one android:theme with my original code that also have one android:theme, is it possible to have 2 android:theme
I dont now any other way to have this 2 styles.
Androidmanifest.xml
<application
android:theme="#style/AppTheme"
android:theme="#style/AppTheme_1" />
<activity android:name="xxxxxxxxx.RegisterActivity"></activity>
styles.xml
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">#color/color_primary</item>
<item name="colorPrimaryDark">#color/color_primary_dark</item>
<item name="colorAccent">#color/accent_color</item>
</style>
<style name="AppTheme_1" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
</style>
You can’t do it in this way (having 2 android:theme).
Depending on your requirements, there can be other ways to achieves.
For example, for most of your screen you want to use your own theme and for certain Activity you want this AppTheme_1, you can try this in that Activity:
public void onCreate(Bundle savedInstanceState) {
setTheme(android.R.style.Theme);
}
No you can't have many themes for same app
but, I suggest do it programmatically using setTheme() method.
with that method, you can replace your themes as you need depending on your needs
you can learn more about themes and styles from here
I open activity with transparent style, it means that it has this theme at the start:
<style name="Theme.Transparent" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowIsTranslucent">true</item>
<item name="android:statusBarColor">#android:color/transparent</item>
<item name="android:windowBackground">#android:color/transparent</item>
</style>
After few moments I change theme
setTheme(R.style.AppThemeWithActionBar);
which looks like this:
<style name="AppThemeWithActionBar" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="windowNoTitle">false</item>
<item name="android:windowNoTitle">false</item>
<item name="android:windowIsTranslucent">false</item>
<item name="colorPrimary">#color/primaryDark</item>
<item name="colorPrimaryDark">#color/primary</item>
<item name="colorAccent">#color/accent</item>
</style>
But unfortunately, when I call getSupportActionBar() after changing theme I get null, what is the reason?
There are two ways to set a style:
Using AndroidManifest.xml
for Entire Application :
<application android:theme="#style/CustomTheme" >
</application>
for Individual Activity :
<application>
<activity android:theme="#style/CustomTheme" >
...
</activity>
</application>
Programmatically :
public void onCreate(Bundle savedInstanceState) {
setTheme(R.style.CustomTheme);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
}
It's not possible to change theme at runtime without reloading whole activity. Because I don't want to reload activity, I will have to stop using ActionBar and start using Toolbar.
I am trying to create base theme for whole my app, I have created custom styles for base components like EditText, Button, TextView and wanna to set them globally in my app.
Here is my xml code.
<style name="AppThemeBase" parent="Theme.AppCompat.NoActionBar">
<item name="colorPrimary">#color/base_app_color</item>
<item name="colorPrimaryDark">#color/base_app_color</item>
<item name="android:windowContentOverlay">#null</item>
<item name="android:windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="windowActionBarOverlay">true</item>
<item name="windowActionModeOverlay">true</item>
<item name="android:editTextStyle">#style/EditTextBaseStyle</item>
<item name="android:textViewStyle">#style/TextViewBaseStyle</item>
</style>
My custom edit text style
<style name="EditTextBaseStyle" parent="Widget.AppCompat.EditText">
<item name="android:textColor">#color/base_text_color</item>
<item name="android:textSize">#dimen/text_size_edit_text</item>
<item name="android:textColorHint">#color/base_hint_color</item>
<item name="android:layout_centerHorizontal">true</item>
<item name="android:background">#drawable/edit_text_rounded_corners_bg</item>
</style>
I also tried to use #android:style/Widget.EditText as a parent.
<style name="TextViewBaseStyle" parent="#android:style/Widget.TextView">
<item name="android:textColor">#color/base_text_color</item>
<item name="android:textSize">#dimen/size_text_base</item>
<item name="android:layout_margin">#dimen/margin_text_view_base</item>
</style>
And of course in AndroidManifest.xml file
<application
android:name=".application.QrApplication"
android:allowBackup="true"
android:icon="#drawable/ic_logo_green"
android:label="#string/app_name"
android:theme="#style/AppThemeBase">
<activity
android:name=".ui.activities.LoginActivity"
android:configChanges="orientation|keyboardHidden"
android:label="#string/app_name"
android:noHistory="true"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
I have several questions
Why it doesn't apply style for each view (EditText and TextView), if set style manually in xml layout it works like a charm, but I cannot get it working globally
About style inheritance. There are two types of inheritance explicit or implicit or for user custom styles using . (dot) and using keyword parent for default themes, but what will be if combine this types of inheritance like this <style name="SomeStyle.ParentStyle" parent="Widget.AppCompat.Button">?
Are styles and theme applied to fragments inside activity, theoretically it should because for inflating fragment context from activity is used which is ContextWrapper ?
Please if you have any ideas what can cause such problem, help to solve it or at least share your thoughts.
Thanks.
The problem was solved
Instead of overriding
<item name="android:editTextStyle">#style/EditTextBaseStyle</item>
I have to override
<item name="editTextStyle">#style/EditTextBaseStyle</item>
To figure out what style item you need to override, follow the inheritance tree of base style/theme and you will find what is the name of style item you need to use.
BUT NOTE
Text view style should be still
<item name="android:textViewStyle">#style/TextViewBaseStyle</item>
It is weird but as is.
I was able to create a floating activity after following this tutorial http://cases.azoft.com/android-tutorial-floating-activity/
However, to do so, I had to add this line in styles.xml :
<item name="android:windowIsTranslucent">true</item>
Is it possible to have the same effect using only Android/Java code ? (e.g. in Activity.onAttachedToWindow() or so...)
Thanks in advance for your help.
[EDIT 01] styles.xml must not be changed (and I'm not supposed to know what's in it...). But for testing purposes, I'm using the default one:
<resources>
<style name="AppBaseTheme" parent="Theme.AppCompat.Light">
</style>
<style name="AppTheme" parent="AppBaseTheme">
</style>
</resources>
[EDIT 02] Resources.Theme.applyStyle() seems to do what I want (according to the API description: "Place new attribute values into the theme" ).
So I created the following custom_style.xml :
<resources>
<style name="MyCustomStyle" >
<item name="android:windowIsTranslucent">true</item>
</style>
</resources>
Then, in onAttachedToWindow() , I called:
getTheme().applyStyle(R.style.MyCustomStyle, true);
But it didn't have any effect...
Is it possible to have the same effect using only Android/Java code ?
I am afraid, No. You will have to do it in styles.xml only. AFAIK value of android:windowIsTranslucent alone can't be changed programatically.
When we call super.onCreate(savedInstanceState); the Activity class provides empty graphical window on which we set our content ie.views. And a theme is applied to this window and then the content are loaded on this view.
Hence the sequence will be,
call to super.onCreate()
setting theme for the activty.
seting the content views for that activity.
eg.
styles.xml
<style name="AppTheme" parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
<item name="android:windowBackground">#drawable/background</item>
<item name="android:windowNoTitle">true</item>
</style>
<!-- Application theme.without title bar -->
<style name="AppTheme.NoTitleBar" parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
<item name="android:windowBackground">#drawable/background</item>
<item name="android:windowNoTitle">true</item>
</style>
<!--Floating activity theme -->
<style name="Theme_Translucent" parent="android:style/Theme.NoTitleBar.Fullscreen">
<item name="android:windowBackground">#android:color/transparent</item>
<item name="android:windowFrame">#null</item>
<item name="android:windowContentOverlay">#null</item>
<item name="android:windowIsFloating">true</item>
<item name="android:backgroundDimEnabled">true</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowAnimationStyle">#android:style/Animation.Dialog</item>
<item name="android:windowFullscreen">true</item>
</style>
Then set your theme for Floating activity as follows:
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setTheme(R.style.Theme_Translucent); // Set here
setContentView(...)
}
do this
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window w = getWindow(); // in Activity's onCreate() for instance
w.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
w.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
Can't say about to do this programatically .. but if you need to do this you can give a try like this ..
Add theme to you activity in manifest file like this ..
android:theme="#android:style/Theme.Translucent.NoTitleBar.Fullscreen"
Example :-
<activity
android:name="com.example.androidhackerphonelocker.MainActivity"
android:label="#string/app_name"
android:theme="#android:style/Theme.Translucent.NoTitleBar.Fullscreen"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Hope it solves some problem of your's ..
Maybe this can help.
#Override
protected void onCreate(Bundle savedInstanceState) {
processSetTheme(this);
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getWindow().setBackgroundDrawableResource(R.color.realTranslucent);
if (Build.VERSION.SDK_INT>=19){
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
super.onCreate(savedInstanceState);
<color name="realTranslucent">#00000000</color>
There a new method appeared in Android R
if android.app.Dialog
window.setDimAmount(0f)
window.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
I would like to add the support actionbar to one of my activities, I previously had been using the theme.translucent with this activity but in order to make the support actionbar work I needed to inherit the Theme.AppCompat, I need to maintain a translucent theme in this activity but unfortunately there isnt a Theme.AppCompat.translucent that i can see by default, is there any way that this can be done?
You can create a new set of styles to use which have the same properties as Theme.Translucent from themes.xml.
Add the following to your styles.xml file:
<style name="Theme.AppCompat.Translucent">
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">#android:color/transparent</item>
<item name="android:colorBackgroundCacheHint">#null</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowAnimationStyle">#android:style/Animation</item>
</style>
You can change the prefix Theme.AppCompat to something else if you want to inherit other things from the theme such as dialog styles etc. For example, a name like Theme.AppCompat.Light.Translucent would have the properties of the Light theme.
To use the new style, set the theme property to #style/Theme.AppCompat.Translucent
<activity
android:name=".TranslucentActivity"
android:theme="#style/Theme.AppCompat.Translucent" >
</activity>
Parama ,
<style name="Theme.AppCompat.Translucent" parent="Theme.AppCompat.NoActionBar">
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">#android:color/transparent</item>
<item name="android:colorBackgroundCacheHint">#null</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowAnimationStyle">#android:style/Animation</item>
</style>
This should be the style header if you want the toolbar to disappear.you can use any parent theme which has NoActionBar for other effects.
Hope this helps
If we use Translucent for transparent activity.
It raises other issues - the color of Msgbox (now white previously black), Default dialog color, the spinners do drop down but do not show the underline and drop-down arrow. The spinners are color black text black; drop-down white drop-down text black and etc.
To overcome this problem, you can just use below code
In style
<style name="Theme.AppCompat.Transparent.NoActionBar" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">#android:color/transparent</item>
<item name="android:windowContentOverlay">#null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">false</item>
<item name="android:backgroundDimEnabled">false</item>
</style>
In manifest file
<activity
android:name=".activity.YourActivityName"
android:theme="#style/Theme.AppCompat.Transparent.NoActionBar" />
I hope it will help
Thanks
Cameron's answer is a nice hack , but it produced a floating action bar and tinted my status bar, which i didn't wanted . So i added more xml attributes for making status bar transparent(for sdk >=19) and used java code for making action bar invisible.
mainActivity.java :
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().hide();
...
}
...
}
styles.xml
<style name="AppTheme.TranslucentBG">
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">#android:color/transparent</item>
<item name="android:colorBackgroundCacheHint">#null</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowAnimationStyle">#android:style/Animation</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
</style>
manifest.xml
<application
android:icon="#mipmap/ic_launcher"
...
android:theme="#style/AppTheme"
...
>
<activity android:name=".MainActivity"
android:theme="#style/AppTheme.TranslucentBG"
...
>
...
</activity>
</application>