i am doing a simple calculator aplication for android (my first app) and i have problems that are breaking my head when i try to apply a specific android:theme to a button.
The problem comes out when the button with the specific theme try to execute an activity method in onclick event. Based on what I 've searched in StackOverflow, is like the "context" of the button with the specific theme is different from the activity context, and because of that it cant find my method that handles the onclick written in the activity.
There is my style.xml where i define my aplication theme and my specific button theme:
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
<item name="colorButtonNormal">#dc000000</item>
<item name="android:background">#dc262626</item>
<!-- Customize your theme here. -->
</style>
<style name="contextButtonTheme" parent="AppTheme">
<item name="colorButtonNormal">#color/contextButtonsColor</item>
</style>
</resources>
There is my button in the layout xml:
<Button
android:layout_width="0dp"
android:layout_weight="25"
android:layout_height="match_parent"
android:text="X"
android:id="#+id/multButton"
android:textSize="11pt"
android:theme="#style/contextButtonTheme"
android:onClick="onClickButton"/>
The solution i read here is that change "android:theme" with "style", although this solves the crash, the colorButtonNormal new color is dont applied :(.
Pls help me D:
PD: Sorry for my bad english
I've answered a similar question here, where you can get a bit more background.
A possible solution to your problem is to not use android:onClick="onClickButton" but set an onClickListener in code. This way you can keep your themed Button. The official docs have an example how to do this.
Related
According to the documentation
A Button which supports compatible features on older versions of the
platform, including:
Allows dynamic tint of its background via the background tint methods
in ViewCompat. Allows setting of the background tint using
R.attr.backgroundTint and R.attr.backgroundTintMode. This will
automatically be used when you use Button in your layouts and the
top-level activity / dialog is provided by appcompat. You should only
need to manually use this class when writing custom views.
Now, this makes me assume that the following two buttons would look exactly the same on high level devices.
<androidx.appcompat.widget.AppCompatButton
android:text="AppCompatButton"
android:id="#+id/appcompatbutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:layout_below="#id/appcompatbutton"
android:id="#+id/button"
android:layout_width="wrap_content"
android:text="Button"
android:layout_height="wrap_content" />
However, here is how it actually looks:
I ran this on the following emulator:
Galaxy Nexus, API:28 (720 x 1280 xhdpi)
And when I apply buttonStyle in my appTheme like this:
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
<item name="buttonStyle">#style/Widget.MaterialComponents.Button</item>
</style>
It changes the AppCompatButton but not the normal button like this:
(Note the slight difference in the rounded edges)
I also tried to create a custom button that both inherited from android.widget.Button and also androidx.appcompat.widget.AppCompatButton, both of these buttons show the same behaviour as using AppCompatButton in xml does. So it feels like the only outlier is Button in XML.
Question 1:
This all seems incredibly confusing according to me. Can someone clarify this as either a bug or feature?
EDIT 1
Doing debugging I found that the Button actually gets transformed into a MaterialButton, see the following:
Question 2:
Why is this transformation happening?
EDIT 2
Question 2 answer:
The transformation of Button to MaterialButton is due to the parent theme I was using.
Question 3:
How do you implement a custom button which works just like Button in xml would?
As a side note and personal opinion, also a slight repetition, this system is not only confusing but its hard to get it right and foolproof for future changes. In addition to this, the documentation is very poor. I would appreciate if an answer to this would be included as well, or at least a discussion regarding it, how to deal with it for example.
Short answers.
This all seems incredibly confusing according to me. Can someone clarify this as either a bug or feature?
They use different styles.
Why is this transformation happening?
There is an auto-inflation enabled which will replace <Button with <com.google.android.material.button.MaterialButton at runtime.
How do you implement a custom button which works just like Button in xml would?
You can customize the attributes in xml or the theme attributes.
Long answers.
They use different styles.
The default style of MaterialButton is Widget.MaterialComponents.Button.
This style inherits from Widget.AppCompat.Button but changes some attributes.
Here you can find the differences.
The main difference is here:
<item name="shapeAppearance">?attr/shapeAppearanceSmallComponent</item>
You can read more about shaping in the official doc.
If you navigate through the style you will find:
<style name="ShapeAppearance.MaterialComponents.SmallComponent">
<item name="cornerSize">#dimen/mtrl_shape_corner_size_small_component</item>
</style>
where mtrl_shape_corner_size_small_component = 4dp.
It explains the slight difference in the rounded edges.
Also you are using
<item name="buttonStyle">#style/Widget.MaterialComponents.Button</item>.
It doesn't work for the MaterialButton. You have to use:
<item name="materialButtonStyle">#style/Widget.MaterialComponents.Button</item>
The auto-inflation is here.
The MaterialComponentsViewInflater replaces some framework widgets with Material Components ones at inflation time, provided a Material Components theme is in use.
Something similar happens also with AppCompat (you can check that MaterialComponentsViewInflater extends AppCompatViewInflater).
It means that, the <Button is replaced <com.google.android.material.button.MaterialButton at runtime, if you are using a Material Theme.
There are different options. One of these is to define a custom style for buttons.
<style name="AppTheme" parent="Theme.MaterialComponents.Light">
...
<item name="materialButtonStyle">#style/MyButtonStyle</item>
</style>
<style name="MyButtonStyle" parent="Widget.MaterialComponents.Button">
<item name="cornerRadius">xxx</item>
</style>
or
<style name="MyButtonStyle" parent="Widget.MaterialComponents.Button">
<item name="shapeAppearanceOverlay">#style/SShapeAppearanceOverlay.MyApp.Button.Rounded</item>
</style>
<style name="ShapeAppearanceOverlay.MyApp.Button.Rounded" parent="">
<item name="cornerFamily">rounded</item>
<item name="cornerSize">xxdp</item>
</style>
I changed the <Button> to <ImageButton>
Quick and short way.
Don't forget to check & change references in java/kotlin files. Compiler will alert you any way.
I can able to set theme to button using android:theme attribute in xml. Is there any equivalent programmatical code?
<Button
android:id="#+id/btnPayment"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1"
android:text="Add Payment"
android:theme="#style/ButtonPeter" // theme..
/>
style.xml
<style name="ButtonPeter" parent="Widget.AppCompat.Button">
<item name="colorButtonNormal">#color/fbutton_color_peter_river</item>
<item name="android:textColor">#android:color/white</item>
</style>
Can I able to set theme dynamically using something like this btnPayment.setTheme(R.style.ButtonPeter) ?
I search a lot but all posts are related to set style or create dynamic button and apply style to it but I dont want to do that .I want to set theme to button
How to achieve this?
I think you are confused with style and theme. From this document, it says: theme for the whole activity while style is for view.
A style is a collection of properties that specify the look and format for a View or window.
A theme is a style applied to an entire Activity or application, rather than an individual View.
For this code:
android:theme="#style/ButtonPeter" // theme is used but only valid style attributes for button will be applied
Hope this help.
As I mention here, using TextViewCompat.setTextAppearance should work :-)
A create a simple Theme as
<style name='one'>
<item name='android:textColor'>#eea</item>
<item name='android:textSize'>20sp</item>
</style>
However on viewing in the emulator the screen goes black.when i do not apply theme the screen has a white background .
what really happens here.i am just starting with android.
In addition ,if a apply a theme to my activity then the attributes of the theme applies to all components of my activity say button,textfields and edittexts .
why would i then write
android:textSize=?android:textSize
to reference value from the theme for any button in my layout when the same value would already be applying.
is the syntax above the correct way to reference an attribute from my theme to assign to attribute for any view in my layout.
thanks
tejinder
Yeah, so you need to do a little more reading.
Let's start with the basics,
You need to understand the differente betweent an Attribute, a Style, and a Theme.
An Attribute is something that can be styled. For instance: android:textSize is an attribute that can have any value.
A Style is a set of specific attributes that will be applied to a Widget. They are defined
in your /values/styles.xml
For instance:
<style name="normalTextThin" parent="android:Widget.Holo.Light.TextView">
<item name="android:gravity">left|center_vertical</item>
<item name="android:padding">8dp</item>
<item name="android:textColor">#FFFFFF</item>
<item name="android:textSize">16sp</item>
</style>
The styles can be applied either as part of a theme or directly as theme-independent.
Theme-indepentent styling of a widget is like this:
<TextView
android:id="#+id/text"
style="#style/normalTextThin"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
You are then theming only that one TextView.
A Theme is a collection of Styles that can be applied to a part of your UI, such a a whole Activity, or your whole Application.
For instance:
<style name="AppTheme" parent="android:Theme.Light">
<item name="android:editTextStyle">#style/EditTextAppTheme</item>
<item name="android:buttonStyle">#style/ButtonAppTheme</item>
<item name="android:imageButtonStyle">#style/ImageButtonAppTheme</item>
</style>
Here, we are declaring that all EditText in your application will use the style named EditTextAppTheme, and so forth and on. When done like this, in order to actually have the theme be active, you declare it in the manifest:
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
That means that you are not required to declare the style on each widget you create.
<EditText
android:id="#+id/input"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="#string/hint_search">
<requestFocus />
</EditText>
That widget right there would already be styled using EditTextAppTheme without the need of you explicitely declaring so.
I recommend you try to read on what attributes can be styled, how to style them, and so forth and on.
If you don't want to though, it's fine, you can still get a lot done with the following tools for styling:
ActionBarStyleGenerator to help you create styles for the ActionBar.
Android Holo Colors to help you style standard widgets.
Hope that helps.
Additional Info
Let me clarify on the whole ?attr/attributeName
The ? means that the system will choose the specific attributeName value for the current Configuration (not specific to different themes). This should be used only when you want the value to be different on different configurations. For example:
?android:attr/actionBarSize
This line is a dimension, and it will be different not based on the current theme, but on the current device screen size and orientation (values, values-land, values-sw600dp).
It's important to know that specifying ?android: means you are accessing preset Android values, not yours. If you have or want to create and use your own attribute values for specific configurations, you must do the following:
Create a file named attrs.xml on your /values/ folder.
Declare the desired custom attribute:
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<attr name="my_custom_attr" format="reference" />
</resources>
Declare a value for the custom attribute, let's say on your own theme.
<style name="AppTheme" parent="android:Theme.Light">
<item name="my_custom_attr">#resource_type/resource_name</item>
<item name="android:editTextStyle">#style/EditTextAppTheme</item>
<item name="android:buttonStyle">#style/ButtonAppTheme</item>
<item name="android:imageButtonStyle">#style/ImageButtonAppTheme</item>
</style>
And then you can use it on the Widget you'd like:
Hope that clears things out.
EDIT 2
For a better answer to your question, please update your question. And like I said, read more on how to properly create styles.
The Theme named 'one', what do you want to apply it to? An activity, a Widget, the whole Application?
How are you applying the theme? Show the lines of code where you specify the usage of theme 'one'.
Your theme as you specified is simply not a properly constructed theme/style.
<style name='one'>
<item name='android:textColor'>#eea</item>
<item name='android:textSize'>20sp</item>
</style>
This says absolutely nothing, and it is definitely not suitable for an Activity-level theme. The reason you specify a parent is so your theme can inherit all of the attributes from the parent, and then you specifiy which ones to change.
For instance, if you want to use your theme and have a light background, do this:
<style name='one' parent="android:Theme.Holo.Light>
<item name='android:textColor'>#eea</item>
<item name='android:textSize'>20sp</item>
</style>
But even here, despite the fact that it will apply, you don't want to have the same text color and size for the whole application do you? That'd be nonsense, different text color and sizes account for a big part of the user experience, so rather than setting those values from what we can refer to as the main style, we can create substyles and apply them to certain widgets.
I can't really go any more detailed that what I already have, the above explains how to accomplish Widget-specific styling, and activity/application level theming.
For a complete start-up guide, read the Android Developer Site, try the test styles declared there, see how they work, and until then try to create your own, don't try to create something out of nowhere if no reading has been made.
I am building a sample application based on latest version of Android OS..As per instructions given here I am trying to give holo:light theme to only one button in my application. How do i do it ? I have created a myStyles.xml in res/values folder but I am not able to find property to apply holo-light theme.
This is what i have in myStyles.xml file
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<style name="mybutton" parent="android:Theme.Holo.Light">
<item name="android:background">#android:color/holo_orange_light</item>
<item name="android:textColor">#android:color/holo_blue_dark</item>
</style>
</resources>
this is i have in my activity.
<Button
android:id="#+id/button1"
style="#style/mybutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="lol" />
I can confirm that backgroundcolor and textcolor are getting applied...(done this for testing purpose).
Currently, If i add android:theme="#android:style/Theme.Holo.Light" to AndroidManifest.xml, holo light theme is applied to entire application. However, I want this theme to be applied for only few controls ( in this case a single button control).
A theme is a style applied to an entire Activity or application, rather than an individual View.
Thus, what you are asking for is not possible. That being said, it seems odd that you would want to do this anyway. I suggest applying the holo theme to your entire app, and then customizing your Buttons only if you really need to. This is probably what the user will expect from your application.
i have a title bar one of my project and i want to use my all screen.I think that i can do be a general( means i want a something and i will call everywhere like a style tag or theme tag) i have no idea.What can i use for?
My title bar is here:
RelativeLayout
android:layout_height="44dip"
android:layout_width="320dip"
android:background="#drawable/merhaba_header_320_44dip">
<ImageView
android:layout_height="32dip"
android:layout_width="121dip"
android:background="#drawable/merhaba_logo_121_32dip"
android:layout_centerInParent="true">
</ImageView>
<ImageView
android:layout_height="30dip"
android:layout_width="64dip"
android:background="#drawable/merhaba_btn_nedir_64_30dip"
android:layout_margin="5dip"
android:layout_alignParentRight="true">
</ImageView>
</RelativeLayout>
Hi DuyguK are you asking for a way to have a title bar that you can apply as a theme or something to all the activities in your app?
If that's so, I would recommend you to do the following.
First define a style in your res/values/styles.xml
<resources>
<style name="MyTheme" parent="android:style/Theme.Light">
<item name="android:windowTitleSize">44dip</item>
//whatever item you want/need to edit for your custom title bar
</style>
</resources>
This allows you to have a theme that is applyable to your whole app. To do this you need to go to your AndroidManifest.xml file an inside the application tag add the following:
<application android:label="#string/app_name"
android:theme="#style/MyTheme">
The android:theme tells the app to use the theme named "MyTheme" that can be found in the res/values/styles.xml file in your project.
That way you can apply correctly your custom title bar to all your activities.
Hope this answers your question if not, please specify!
An additional recommendation is to take a look at the ActionBarCompat project that comes with the samples in Android SDKs. The Android Developers page shows the project:
http://developer.android.com/resources/samples/ActionBarCompat/index.html
It has the advantage of being compatible with pre-API11 devices, is applied as a theme to your app and it is being used by lots of apps available in the store.
If you have any questions/trouble with it please tell me.
create your own style which can ofcourse extend from existing from an existing theme.
change the windowNoTitle to true.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="noTitleBarStyle" parent="android:Theme.Black">
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">#color/darkGrey</item>
<item name="android:colorForeground">#ff3333</item>
</style></resources>