TextInputLayout error message size - android

Is there a way to force the TextInputLayout error message to take a single line ?
I tried to place app:errorTextAppearance="#style/error_appearance" on the TextInputLayout with the error_appearance style containing :
<item name="android:maxLines">1</item>
<item name="android:ellipsize">end</item>
<item name="android:inputType">text</item>
and it does not work. Changing the color works however. I don't get it, the mErrorView is just a TextView, it should work.

you can fetch error TextView by id
TextView errorView = textInputLayout.findViewById(R.id.textinput_error);
errorView.setMaxLines(1);
errorView.setSingleLine(true);

It's true the the error is a TextView, but a TextAppearance style affects only text, not the View that the text is in. The maxLines and ellipsize attributes belong to TextView, so they will be ignored in a TextAppearance style, which expects attributes like textColor, textSize, typeface, etc.1
Knowing this, we just need to find a way to set those attributes' values on the error TextView. kjurkovic's answer on this very question
shows how to do that in code, for the current versions of TextInputLayout.2 It turns out that there's also a way we can do this in the layout XML, which might be preferable for some.
That error TextView is instantiated with the TextInputLayout's Context, which we can actually modify in the layout XML, to some extent, with the android:theme attribute. Using an overlay with this attribute, we can cause that Context's theme to have an android:textViewStyle – essentially, the basic settings for TextViews – that contains our desired attribute values.
In your theme/style resource XML:
<style name="ThemeOverlay.TextInputLayout.TextView" parent="">
<item name="android:textViewStyle">#style/Widget.TextView.SingleLineEllipsized</item>
</style>
<style name="Widget.TextView.SingleLineEllipsized" parent="">
<item name="android:maxLines">1</item>
<item name="android:ellipsize">end</item>
</style>
On the <TextInputLayout> in the layout XML, simply add the android:theme attribute:
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/text_input_layout_phone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Phone number"
android:theme="#style/ThemeOverlay.TextInputLayout.TextView">
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/edit_text_phone"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
Though the current TextInputLayout has different design details than the original, we can see that the maxLines and ellipsize settings have worked:
The main caveat with this approach is that all of TextInputLayout's internal TextViews will have these base attribute values. Currently, aside from the error, those comprise the helper, the counter, the prefix, and the suffix.
The helper occupies the same spot as the error, so if you want single-line-and-ellipsized on one, you very likely want it on the other as well, if you're even using it.
The counter is already being set up as single-line, and the extraneous ellipsize would only have effect if the counter were to grow wider than the EditText.
The prefix and the suffix, by their nature, are meant to be single-line anyway.
If any of that is undesired, then kjurkovic's findViewById() demonstration should work with all of those TextViews,3 though you must ensure to set the corresponding text first, as the TextViews are instantiated on demand.
1 You can find the full list of valid TextAppearance attributes in the platform's res/values/attrs.xml resource file. I don't believe there is any documentation or developer page that covers it; at least, there didn't used to be.
2 The very first versions of TextInputLayout did not assign IDs to the inner TextViews, so getting direct reference to the error TextView required reflection, or awkwardly searching the internal hierarchy. I've not tested the theme overlay solution on those ancient versions, but if for whatever reason you're stuck with one and this doesn't work, previous revisions of this answer have those other options for you.
3 Incidentally, the IDs for all of those are as follows: R.id.textinput_error, R.id.textinput_helper_text, R.id.textinput_counter, R.id.textinput_prefix_text, and R.id.textinput_suffix_text.

Related

Two textviews with different colors using one theme?

I'm new to android and I have been trying to find out an answer to this. I have a layout file .xml for listview that has two textviews, one is for heading with a greater size and other below is for description. What I want is that heading textview's text stays white and description textview's text stays grey in my current theme. That is dark theme. But user has the option to change the theme, so when user selects Light theme I want my heading textview's text (that is within layout that I have for listview's rows) to become black and also the description textview's text to become black.
Please help and thanks in advance.
you can set the text color programmatically using the method textView.setTextColor(int color), or via XML using the attribute android:textColor="#yourhexcolor"
You can change theme programmatically. There is one guy asked this hours ago. Can you check this: how-to-change-colour-when-user-wants-another-colour-in-the-app
Also if you want to use diferent themes for different TextViews you can try like :
textView.setTextAppearance(context, android.R.style.TextAppearance_Small);
How can i create custom themes for TextViews
in your styles.xml create different styles :
<style name="MyBlueTextTheme" parent="#android:style/TextAppearance.Medium">
<item name="android:textSize">18sp</item>
<item name="android:textColor">#123456</item>
<item name="android:textStyle">bold</item>
</style>
Then use it like :
<TextView
android:id="#+id/textBlue"
android:text="This is a blue styled text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
style="#style/MyBlueTextTheme" />
Or use it like: textView.setTextAppearance(context,R.style.MyBlueTextTheme);
but its deprecated and you can use textView.setTextAppearance(R.style.MyBlueTextTheme); but this can be used Api23 or higher

Why are some of my styles not working with lower APIs?

I have a quick question!
In my styles.xml file, I have
<style name="TextViewStyle" parent="android:Widget.TextView">
<item name="android:padding">20px</item>
<item name="android:background">#9cd0e8</item>
<item name="android:textColor">#254b7c</item>
<item name="android:textSize">18sp</item>
<item name="android:textStyle">bold</item>
</style>
And in my activity_main.xml, I have
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:theme="#+styles/TextViewStyle"
android:text="Sample Text"/>
What I am trying to do is, in my Android application, on a certain activity I plan to place many TextViews with similar properties. Instead of writing these 'properties' every time with each TextView instance, I grouped them together in a style in styles.xml file and set theme of each of my TextViews to that style.
It works fine and does what I want it to do, but only with APIs above 21! My application's supposed to support devices from API level 15 up. Why is my approach not working with lower APIs?
Please help soon. I need to finish this soon.
EDIT
By 'working', I meant that the attributes I set in my style (padding, color, etc.) appear on the TextViews as they should. In lower APIs however, the TextViews appear as if I had not applied any attribute on them. Plain text appears instead of a styled one.
remove parent from your style
remove android:theme from textView, (why there is + sign?)
instead of theme put this into your textView
style="#style/TextViewStyle"
btw, use dp instead of px ;)

Issues changing the color of views

So I am trying to change my app color to blue and some of most the views I have are not willing to cooperate with me.
Here is the image:
Here I want to change the color of the green parts on the spinner, edittext and checkbox views (which are green) to black or blue.
I've looked all over Stack Overflow and I can't find the solution!
Thank you very much, If possible I would like to have a XML solution but I wouldn't mind a programmatic solution!
Add these to your base theme in styles.xml
<item name="colorControlNormal">#color/YOUR_COLOR</item>
<item name="colorControlActivated">#color/YOUR_COLOR</item>
<item name="colorControlHighlight">#color/YOUR_COLOR</item>
Note: The above change will affect the EditTexts and other views probably throughout the application.
If not, and if you are using the AppCompat v22 support library, you can specify the theme in the EditText like: android:theme="#style/Theme.App.Base.
This will ensure the style won't also affect other views in your layouts that you don't want to change
Also if you want to change the above solution, just add another Theme specific to EditTexts and Spinners and apply it to all Spinners if you want
<style name="MyWidgetTheme">
<item name="colorControlNormal">#color/YOUR_COLOR</item>
<item name="colorControlActivated">#color/YOUR_COLOR</item>
<item name="colorControlHighlight">#color/YOUR_COLOR</item>
</style>
and in your EditText, Spinner or any other View, just assign this theme:
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Demo"
android:lines="1"
android:theme="#style/MyWidgetTheme"
/>
<Spinner
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:theme="#style/MyWidgetTheme"></Spinner>
Take a look to this resource generator.
Choose your color, the widgets you want to generate and voila! You copy them to your project and reference them in your xmls.

coding style in Android: when should you use a style instead of inline attributes?

I'm not sure what is the best way to develop interfaces in Android.
is it better to clean the layout file by moving inline attributes to a style file? As far as I know, in HTML it is better to use classes and ids inside HTML, and use them in style.css file. What about android?
I found this, maybe it helps someone else.
When to use Styles
The first problem we must address is a simple one: when should you use a style instead of inline attributes?
Rule #1: Use styles when multiple Views are semantically identical.
This rule is best illustrated with a few examples:
You're creating a calculator. Each button should look the same, so it makes sense to create a `CalculatorButton` style.
You've got a couple screens with multiple text formats - say, headers, subheaders, and text. You can unify their look by creating `Header`, `Subheader` and `Text` styles.
You've got thumbnails all over your app. You want them all to look the same. The `Thumbnail` style is born.
The common thread in all these examples is that these Views are not just using the same attributes - they play the same role across the app. Now, when you want to tweak the look/feel of any of these Views, you can just edit the style and change them all at once. It saves you time, effort and keeps your Views consistent.
Want to save even more work? Use resource references!
Rule #2: Use references within styles when appropriate.
You could define a style this way:
<style name="MyButton">
<item name="android:minWidth">88dp</item>
<item name="android:minHeight">48dp</item>
</style>
What if you wanted minWidth to vary based on screen size? You could just duplicate the style once per screen size (say, sw600dp and sw900dp), but then you're having to duplicate the minHeight attribute as well. What if you want both attributes to change? Suddenly you've got tons of MyButtons defined everywhere, each one duplicating all other attributes. It's a recipe for disaster; it's so easy to forget to change one attribute in one of the many copies.
Styles are just an alias to a series of attributes. It's a lot easier to just define the style like this:
<style name="MyButton">
<item name="android:minWidth">#dimen/button_min_width</item>
<item name="android:minHeight">#dimen/button_min_height</item>
</style>
Now you can just modify a single attribute for each resource qualifier. It's absurd to think about duplicating a layout just to change, say, the width of one View in portrait vs. landscape. You'd use a dimension for that. The same applies for styles.
I don't mean to imply you should always use resource references in styles; just that you should use it if you need multiple values switched on resource qualifiers.
This isn't to say that sometimes you won't need to duplicate a style across resource qualifiers, but you can keep it to a minimum. Usually the only reason to do so is because of platform changes (e.g., the change from paddingLeft and paddingRight to paddingStart and paddingEnd).
Multiple Styles
It would be wonderful if you could apply multiple styles to a single View, like CSS.
You can't. Sorry.
But you can, in a couple of cases, get an approximation of multiple styles.
Rule #3: Use themes to tweak default styles.
Themes provide ways of defining the default style of many standard widgets. For example, if you want to define the default button for the app, you could do this:
<style name="MyTheme">
<item name="android:buttonStyle">#style/MyButton</item>
</style>
If you're just tweaking the default style, the only tricky part is figuring out the parent of your style; you want it to match the appropriate theme for the device, but that varies based on OS version.
If you're using an AppCompat theme, you should use their styles as the parent since they handle differences across platforms as well. For example, they have a Spinner style:
<style name="MySpinner" parent="Widget.AppCompat.Spinner" />
If the style doesn't exist in AppCompat (or you're not using it), the problem is a bit trickier, since you need the parent to switch based on the theme. Here's an example of a custom Button style that uses Holo normally, but Material when appropriate.
You'd put this in /values/values.xml:
<style name="ButtonParent" parent="android:Widget.Holo.Button />
<style name="ButtonParent.Mine">
<item name="android:background">#drawable/my_bg</item>
</style>
Then, in /values-v21/values.xml:
<style name="ButtonParent" parent="android:Widget.Material.Button />
Setting up the correct parent will ensure consistency with both your app and the platform.
If you truly want to define all necessary attributes (instead of just tweaking the defaults), you could skip parenting entirely.
Rule #4: Use text appearance when possible.
TextAppearance allows you to merge two styles for some of the most commonly modified text attributes. Take a look at all your styles: how many of them only modify how the text looks? In those cases, you could instead just modify the TextAppearance.
First, you need to define your TextAppearance:
<style name="MyTextAppearance" parent="TextAppearance.AppCompat">
<item name="android:textColor">#0F0</item>
<item name="android:textStyle">italic</item>
</style>
Notice how I've set a parent - text appearances won't merge, so you need to make sure to define all attributes. You can use any appropriate TextAppearance as the parent.
Now you can use it in a TextView:
<TextView
style="#style/MyStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="#style/MyTextAppearance" />
Notice that I can still apply a style to this TextView, getting me a whopping TWO styles for one view! Not as good as true multiple styles, but I'll take what I can get.
You can use TextAppearance in any class that extends TextView. That means that EditText, Button, etc. all support text styling.
Common Pitfalls
I've explained all the times when I use styles. Unfortunately, it is easy to abuse styles in ways that will hurt you in the long run. Here's a few anti-patterns to avoid.
Rule #5: Do NOT create a style if it's only going to be used once.
Styles are an extra layer of abstraction. It adds complexity. You have to lookup the style to see the attributes they apply. As such, I see no reason to use them unless you're going to use the style in multiple places.
Which would you rather see when you open up a layout: This?
<TextView style="HelloWorldTextView" />
Or this?
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
It's so easy to create a style later if you need to do so. Don't plan ahead too much.
Rule #6: DO NOT create a style just because multiple Views use the same attributes.
The main reason to use styles is to reduce the number of repeated attributes, right? Why not just use a style whenever multiple Views use the same attributes?
The problem with this attitude is that those Views, if they are not used in the same context, may eventually want to differ in how they look. And at that point, your base style becomes difficult to edit without unintended side effects.
Think about this scenario: you've got a few TextViews that the same text appearance and background. You think, "hey, I'll create a style, that'll cut down on code duplication." Everything is hunky dory at first, but eventually you want to tweak how some of the TextViews look. The problem is, by now that style is used all over the place, so you can't edit it without some collateral damage.
Fine, you say - I'll just override the style directly in the layout XML. Problem solved. Then it happens again. And again. Eventually that style is meaningless because you're having to override it everywhere. It ends up adding extra work instead of making life easier.
That's why I specified in rule #1 that you should use styles when the Views are semantically identical. This ensures that when you change a style, you really do want every View using the style to change.
Implicit vs. Explicit Parenting
Styles support parenting, wherein a child style adopts all attributes of a parent style. It would be rather limiting if they did not.
Suppose I want every Button in the app to look the same, so I make a ButtonStyle. Later, I decide half the Buttons should look slightly different - with parenting, I can just create ButtonStyle.Different, getting the base style + the tweaks.
It turns out there are two ways of defining parents, implicitly and explicitly:
<!-- Our parent style -->
<style name="Parent" />
<!-- Implicit parenting, using dot notation -->
<style name="Parent.Child" />
<!-- Explicit parenting, using the parent attribute -->
<style name="Child" parent="Parent" />
Simple enough, right? But what do you think happens here, when we define parents with both methods?
<style name="Parent.Child" parent="AnotherParent" />
If you answered that the style has two parents, you are wrong. It turns out that it only has one parent: AnotherParent.
Each style can only have one parent, even though there are two ways to define it. The explicit parent (using the attribute) takes precedence. This leads me to the next rule:
Rule #7: DO NOT mix implicit and explicit parenting.
Mixing the two is a recipe for confusion. Suppose I have this layout:
<Button
style="#style/MyWidgets.Button.Awesome"
android:layout_width="match_parent"
android:layout_height="match_parent" />
But it turns out that my style is defined thus:
<style name="MyWidgets.Button.Awesome" parent="SomethingElse" />
Even though it looks like my Button is based on MyWidgets.Button, it's not! The style name is misleading and the only way to discover that is to do extra work and dig into your style files.
The common temptation is to keep using dot notation with explicit parenting so that your styles look hierarchically related:
<style name="MyButton" parent="android:Widget.Holo.Button" />
<style name="MyButton.Borderless" parent="android:Widget.Holo.Button.Borderless" />
Object-oriented styles! They look so pretty, right? But looks are all you're getting - an illusion that styles are related when they are not. The deception is that MyButton.Borderless is related to MyButton, but they have nothing in common! Let's remove the confusion by removing the dots from the name:
<style name="MyButton" parent="android:Widget.Holo.Button" />
<style name="MyBorderlessButton" parent="android:Widget.Holo.Button.Borderless" />
I lose out on the hierarchy looking pretty, but I gain a lot of utility in code.
Styles vs. Themes
Styles and themes are two different concepts. While styles apply to a single View, themes are applied to a set of Views (or to a whole Activity).
For example, suppose you are using AppCompat and you want to set the primary color for the screen. For this, you must theme the entire Activity:
<style name="MyTheme">
<style name="colorPrimary">#color/my_primary_color</style>
</style>
Themes use the same data structure as styles - even using the style tag - but they are, in fact, used in totally different circumstances! They don't operate on the same attributes - for example, you can define a textColor on a View, but there is no textColor attribute for a theme. Likewise, there exists colorPrimary in themes, but in styles they go unused. Thus:
Rule #8: DO NOT mix styles and themes.
Two common mistakes I've seen:
Applying a theme (as a style) to a `View`:
It just makes no sense because a `View` can't use any of the theme attributes anyways. Nothing happens.
Combining the themes/styles in your hierarchy via parenting. I've seen this as a result of people trying to maintain the illusion of hierarchy using dot notation:
Stupid! So, stupid! It does not make any sense and sometimes misfires in strange ways. Just don't do it!
As of Lollipop, you can apply themes to a View and all its children2. Even in that circumstance, you shouldn't mix up the two, though you could use them both in parallel:
<View
style="#style/MyView"
android:theme="#style/MyTheme" />
AppCompat has a simulacrum of View theming for the Toolbar, but that's all you'll get for a while until Lollipop is the minimum supported version of your app. In other words - you can have fun with this feature in a couple years. :P
Conclusion
The unifying element of these rules are to be careful and thoughtful when using styles. They can save you time, but only if you know when to use them.
Font: this article

Android style descriptions

I tried changing the appearance of a spinner and I partly succeeded. I'm doing this via overriding parts of the theme. I managed to change the text size of the spinner item (i.e. the text size in the drop down button) with my themes.xml and styles.xml:
My themes.xml file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="CustomTheme" parent="#android:Theme.Holo.Light">
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
<item name="android:spinnerItemStyle">#style/CustomSpinnerItem</item>
</style>
</resources>
My styles.xml file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="CustomSpinnerItem" parent="#android:Widget.TextView.SpinnerItem">
<item name="android:textAppearance">#style/CustomTextAppearance</item>
</style>
<style name="CustomTextAppearance">
<item name="android:textSize">30dp</item>
</style>
</resources>
However I cannot find the attributes that are responsible for the text appearance of the items in the dropdown list of the spinner. I tried dropDownItemStyle amongst other things. In my opinion the attribute names are not self-explanatory, so I wanted to know whether there is a documentation of what attribute does what in a style to find out which attributes to override. I found it very cumbersome to trace back all the styles used in a theme via the themes.xml and styles.xml of the platfrom and then try to find the right attributes via trial and error.
I know that one can change the appearance by passing layouts to the adapter, however, this is not really what I was looking for, since (as far as I know), you can only use inheritance in styles and not in layout xml files. If I created a custom layout for the adapter I'd have to create 9-patch images etc., which I think is a bit too time consuming in case I only want to change the text size.
Of course it's possible that I misunderstood the whole concept, since I'm new to Android ;)
You probably have found out the answer since you asked but for others looking at similar questions:
I do not know of a list of attribute names with good explanation of what they do (R.attr's page mostly gives information that is already in the name) but the way I do it is:
Start from the element I give to setDropDownViewResource(), in my case: android.R.layout.simple_spinner_dropdown_item and find.
Find its layout definition in \sdk\platforms\android-17 (specific platform version to avoid redundant results).
Get its style from the layout file. In this case: ?android:attr/spinnerDropDownItemStyle
We now have the attribute name we need.
It's better to do it that way rather than try to guess what attribute to use because you know which attribute the system itself use so it's very likely to be the correct one (unless there's a bug).
If I created a custom layout for the adapter I'd have to create
9-patch images etc.
Well, no, the layout determines what kind of GUI element you would have (a textfield, a spinner, an imagebutton, a custom element...), not how they are styled (nine-patch backgrounds, text colors...), so you still would have to mess with styles to get the right appearance.
For example, for visual consistency I ported the button, checkbox and spinner style from Theme.Holo to Gingerbread, yet I did not mess with layout, all I did was the aforementioned steps plus looking up the result (spinnerDropDownItemStyle in the above example) in themes.xml, which gave me the style name (e.g.: Widget.Holo.DropDownItem.Spinner).
Then I looked that up in styles.xml and imported it (and any parent*) in my project's styles.xml, searching and copying any Holo specific reference in my project and adjusting the namespace accordingly (add android: to attributes and replace ?android:attr with #style for what I copy to my styles.xml file).
So far I haven't had to mess with layouts at all (even the presence of radio buttons in spinner dialogs on Gingerbread is determined by an xml attribute: android:checkMark).
If a style has no parent attribute (like Widget.Holo.DropDownItem.Spinner) then its parent is the same style minus the last element (e.g.: Widget.Holo.DropDownItem)

Categories

Resources