Error applying image style dynamically, why? - android

attrs.xml:
<declare-styleable name="AppTheme">
<attr name="actionbarCompatLogoStyle" format="reference" />
</declare-styleable>
styles.xml:
<style name="Theme.MyApp" parent="android:style/Theme.Light">
<item name="actionbarCompatLogoStyle">#style/ActionBarCompatLogo</item>
</style>
<style name="ActionBarCompatLogo">
<item name="android:layout_width">30dp</item><!-- original image is huge -->
<item name="android:layout_height">30dp</item>
<item name="android:src">#drawable/app_logo</item>
</style>
Problem: if I use this, image dimensions won't work (huge image):
ImageButton logo = new ImageButton(context, null, R.attr.actionbarCompatLogoStyle);
If I use this, it works (tiny image, which is what I want):
<ImageView style="#style/ActionBarCompatLogo"></ImageView>
Why?

Any attribute prefixed with layout_ is part of a LayoutParams object. LayoutParams are special arguments to the parent view about how it should lay out the child view. The type of LayoutParams you set on a view is dependent on what type of ViewGroup you are adding it to. Each container view type can be different and so can the LayoutParams. layout_weight is specific to LinearLayout, layout_below is for RelativeLayout, etc. layout_width and layout_height are part of the base ViewGroup LayoutParams.
The takeaway from this is that LayoutParams are not parsed by the view's constructor, they're parsed by another step that your code above isn't doing. (The LayoutInflater involves the parent ViewGroup's generateLayoutParams method.)
Since LayoutParams are dependent on the intended parent of the View it's not recommended to put LayoutParams in styles. It mostly works when you are inflating views from layout XML but it has other implications similar to the edge case you've found here and requires you to be aware of them. For example, a style may specify layout_weight for a LinearLayout but if a view with that style is added to a RelativeLayout instead it will not behave as expected since RelativeLayout does not support layout_weight.

As far as I know it's not possible to apply styles to specific views programmatically, only via XML.
What you can do is to set a theme on your activity inside the onCreate() method. Consult this question: android dynamically change style at runtime

Related

Issue with custom attributes in child views when parent layout has specified own theme

I'm trying to solve an odd problem where in my layout xml file a parent view (<LinearLayout>) has an attribute called android:theme="#style/blueTheme" and it's children (<TextView>) have android:background=?attr/backgroundColor.
The issue here is that the returned attribute has no value. I've expected that the value would be retrieved from it's parent theme (ie. #style/blueTheme) but can't just make it to work.
Is this feature supported at all?
edit-
<style name="blueTheme">
<item name="backgroundColor">#color/blue</item>
</style>
and the backgroundColor is defined as
<attr name="backgroundColor" format="reference" />

What is the difference between style and android:theme attributes?

What are the key differences between android:theme and style attributes used for views like buttons and textviews in android layout xml files?
How to use them?
and When to use which?
There are two key differences:
First, attributes assigned to a view via style will apply only to that view, while attributes assigned to it via android:theme will apply to that view as well as all of its children. For example, consider this style resource:
<style name="my_background">
<item name="android:background">#drawable/gradient</item>
</style>
If we apply it to a LinearLayout with three child TextViews by using style="#style/my_background", then the linearlayout will draw with a gradient background, but the backgrounds of the textviews will be unchanged.
If instead we apply it to the LinearLayout using android:theme="#style/my_background" then the linearlayout and each of the three textviews will all use the gradient for their background.
The second key difference is that some attributes only affect views if they are defined in that view's theme. For example, consider this style resource:
<style name="checkboxes">
<item name="colorAccent">#caf</item>
<item name="colorControlNormal">#caf</item>
</style>
If I apply this to a CheckBox using style="#style/checkboxes", nothing will happen. If instead I apply it using android:theme="#style/checkboxes", the color of the checkbox will change.
Just like the first rule said, styles containing theme attributes will apply to all children of the view with the android:theme attribute. So I can change the color of all checkboxes in a linearlayout by applying android:theme="#style/checkboxes" to my linearlayout.

Is there a way to wrap text in an EditText?

I am setting the texts inside of EditTexts in Java. Right now, what happens is, when the text is long, it just gets cut off.
In the XML, the height of the EditText is set to wrap_content. I want the height to change depending on the length of the String I will place in it so that all the text can be seen. Any solution for this? Thanks in advance!
Edit: My EditText's setup
<item name="android:layout_width">310dp</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:padding">15dp</item>
<item name="android:gravity">center</item>
<item name="android:editable">false</item>
<item name="android:textColor">#color/color_darktext</item>
<item name="android:textColorHint">#color/color_hint</item>
<item name="android:textAllCaps">true</item>
<item name="android:textSize">18sp</item>
<item name="android:layout_marginBottom">8dp</item>
<item name="android:background">#drawable/button50radius</item>
<item name="android:stateListAnimator">#null</item>
<item name="android:inputType">none</item>
The reason could be your padding and restricting the width of the EditText.Please do change those values and you can notice the difference.Try changing the width to wrap_content and add the attribute maxWidth="310dp" to restrict your width.
The height of the EditText is set to wrap_content
That means it will be wrapped properly how ever long your text is, It doesn't matter.
Any solution for this ?
Yes there are some possibilities, You have not posted your XML so that it would be hard to recognize the mistake. But one of the possibility is
Your parent layout which is containing the TextView may be having the paddingBottom attribute so that your TextView won't be able to show the full text inside.
If the above one is not what you did in your case, Then you can addandroid:layout_gravity attribute,
It is Standard gravity constant that a child supplies to its parent. Defines how the child view should be positioned, on both the X and Y axes, within its enclosing layout.
You can set it to android:layout_gravity="fill" which will grow the horizontal and vertical size of the object if needed so it completely fills its container.
also set the parent layout, Layout_width property .
For example
layout_width=250sp
otherwise , EditText or TextView dont wrap to next line till it reach the end of mobile border. So define the Layout_width

FrameLayout not use the styles correctly

I am very happy with this website. I'm learning a lot.
Today I doubt has arisen. And I want to put a style to a FrameLayout. and do not use.
The style is as follows:
<style name="textAsk">
<item name="android:textColor">#000000</item>
<item name="android:padding">2dp</item>
<item name="android:minWidth">88dp</item>
<item name="android:minHeight">36dp</item>
<item name="android:textSize" >18dp</item>
<item name="android:layout_marginRight">12dp</item>
<item name="android:layout_marginLeft">12dp</item>
<item name="android:layout_marginTop">5dp</item>
</style>
I show fragments that are changing in a FrameLayout. Each Fragment contains a TextView with a text in it.
There are a lot of fragments, and I would like to set a style, a common one, for all the TextViews, in order to save time and not setup the style in each TextView.
I had tried this code:
<FrameLayout
android:id="#+id/fragmentaskGRP1"
android:layout_width="match_parent"
android:layout_height="450dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="5dp"
style="#style/textAsk"/>
But the only thing that works for me is:
<item name="android:layout_marginRight">12dp</item>
<item name="android:layout_marginLeft">12dp</item>
<item name="android:layout_marginTop">10dp</item>
Thank you very much for everything
The FrameLayout doesn't support the textColor or textSize attribute (API). So it's never set for the FrameLayout and ignored. See the style properties section from the guide Styles and Themes for more information.
Quote from the Guide:
However, if you apply a style to a View that does not support all of the style properties, the View will apply only those properties that are supported and simply ignore the others.
Define the text-related styles in a separate style definition and use it for this one for the matching views like TextView
The thing is that child views don't inherit styles from their enclosing ViewGroup. Styles can have parents, but in your case TextViews are not going to get these attributes from the FrameLayout.
The other styles will not be applied to fragments. You have to create another logic to apply styles to all fragments (Most probably you will have to apply styles individually to each fragment)
FrameLayout have nothing to do with text so textColor, textSize will have no effect.
Where as minWidth, minHeight are properties of View it think they should work.

Programmatically create ListView with custom style - Why is android:layout_marginXY not recognized?

I am trying to create a new ListView programmatically and to apply a custom style to is:
// Somewhere within a Fragment...
ListView myListView = new ListView(getActivity(), null, R.attr.myListViewStyle);
someContainerView.addView(myListView);
// In attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="AppTheme">
<attr name="myListViewStyle" format="reference"/>
</declare-styleable>
</resources>
// in styles.xml
<style name="AppTheme" parent="AppBaseTheme">
<item name="myListViewStyle">#style/ListViewStyle</item>
</style>
<style name="BookingsSectionListView" parent="#android:style/Widget.ListView">
<!-- Setting the Padding DOES work... -->
<item name="android:paddingLeft">50dp</item>
<!-- ...while setting the Margin has NO effect -->
<item name="android:layout_marginTop">50dp</item>
</style>
While the creation of the ListView is no problem the custom style is not applied correctly. The android:layout_marginXY attributes are not recognized and thus the ListView is not placed correctly. If I use android:paddingX instead everything works fine. Why is that?
If I don't create the the ListView programmatically but directly in XML and apply the style to it the android:layout_marginXY attributes works without any problem.
What is the difference between creating the ListView and applying the style in XML or Java?
You shouldn't think of layout_* attributes as a part of child's style (ListView in this case). layout_* attributes are in context of the parent to which the child is added. They tell the parent where to position and how to layout a child (child doesn't have this logic).
In this line:
ListView myListView = new ListView(getActivity(), null, R.attr.myListViewStyle);
all attributes are passed to the ListView and the style will be applied to the ListView itself. It doesn't have any parent - it's just newly created object not attached to view hierarchy yet.
someContainerView.addView(myListView);
This is a line where LayputParams are assigned to child. You are not specifying any LayoutParams (there are different version on this method), so the default one will be used.

Categories

Resources