How to set default parameters to custom UI Class? - android

I have created a Custom Class called RoundedButton that extends Button. I want to assign some default parameters. How to go about it?
There was no change after I implemented the xml codes below. Basically the style was not getting added by default. I don't know what I am missing.
in styles.xml
<resources>
<style name="AppTheme" parent="#android:style/Theme.Light">
<item name="RoundedButtonStyle">#style/CustomView</item>
</style>
<style name="CustomView">
<item name="android:clickable">true</item>
<item name="android:focusable">true</item>
<item name="android:focusableInTouchMode">true</item>
<item name="android:colorBackground">#color/transparent</item>
<item name="android:textColor">#color/blue</item>
<item name="android:windowBackground">#color/transparent</item>
<item name="android:background">#drawable/button_border</item>
<item name="android:gravity">center</item>
</style>
</resources>
in attrs.xml
<resources>
<attr name="RoundedButtonStyle" type="reference" />
</resources>
manifest:
android:theme="#style/AppTheme"
RoundButton.java
public RoundedButton(Context context) {
super(context);
ctx = context;
}
public RoundedButton(Context context, AttributeSet attrs) {
super(context, attrs, R.attr.RoundedButtonStyle);
ctx = context;
TypedArray attrsArray = context.obtainStyledAttributes(attrs, R.styleable.RoundedButtonAttrs, 0, 0);
initAttributesArray(attrsArray);
attrsArray.recycle();
initializeRoundedButton();
}
I have used this and this for trying to solve it.
EDIT: Earlier I had an issue that the background was light grey and did not change, I discovered the issue was because of a line of code that I had later in the UI Class.

Related

Different theme styles for not all views

In my Android app I have two different themes (light and dark).
For example:
<style name="AppThemeDark" parent="Theme.AppCompat">
<item name="colorPrimary">#android:color/black</item>
<item name="colorPrimaryDark">#android:color/black</item>
<item name="colorAccent">#android:color/holo_red_dark</item>
<item name="android:textColor">#android:color/white</item>
<item name="windowActionModeOverlay">true</item>
</style>
<style name="AppThemeLight" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
<item name="windowActionModeOverlay">true</item>
</style>
So, now I can apply, for example, different text colors to a TextView (white for dark theme and black for light):
<item name="android:textViewStyle">#style/TextViewDark</item>
<style name="TextViewDark">
<item name="android:textColor">?android:attr/colorAccent</item>
</style>
But it will apply to all TextViews.
The main question, is it possible to make in XML (not programmatically) next:
Light theme: Half of TextViews text color black, and another half green.
Black theme: TextViews that black in Light theme - red, and another half - blue (which are green in Light theme).
Create 2 classes extends TextView
public class OneTextView extends TextView {
public OneTextView(Context context) {
super(context);
init(context);
}
public OneTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public OneTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context){
int[] attrs = new int[] { R.attr.myFirstColor};
TypedArray ta = context.obtainStyledAttributes(attrs);
int appColor = ta.getColor(0, 0);
ta.recycle();
// set theme color
setTextColor(appColor);
}
}
public class SecondTextView extends TextView {
public SecondTextView(Context context) {
super(context);
init(context);
}
public SecondTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public SecondTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context){
int[] attrs = new int[] { R.attr.mySecondColor};
TypedArray ta = context.obtainStyledAttributes(attrs);
int appColor = ta.getColor(0, 0);
ta.recycle();
// set theme color
setTextColor(appColor);
}
}
each class you can use in xml like this
<com.route.to.class.OneTextView
android:layout_width="match_parent"
android:layout_height="match_parent" />
OneTextView can have black and red colors
SecondTextView can have green and blue colors
define attr.xml in values
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="myFirstColor" format="color" />
<attr name="mySecondColor" format="color" />
</resources>
Then in your styles.xml, define colors for each theme:
<style name="Theme.MyApp" parent="#style/Theme.Light">
<item name="myFirstColor">#color/black</item>
<item name="mySecondColor">#color/green</item>
</style>
<style name="Theme.MyApp.Dark" parent="#style/Theme.Dark">
<item name="myFirstColor">#color/green</item>
<item name="mySecondColor">#color/blue</item>
</style>
you have defined in styles.xml
<style name="TextViewDark">
<item name="android:textColor">?android:attr/colorAccent</item>
</style>
<style name="TextViewLight">
<item name="android:textColor">#color/green</item>
</style>
then you can use it in main.xml
<LinearLayout>
<TextView
android:id="#+id/light_text_view"
android:text"i´m use light theme"
style="#style/TextViewLight"/>
<TextView
android:id="#+id/dark_text_view"
android:text"i´m use darktheme"
style="#style/TextViewDark"/>
</LinearLayout>
you don´t need to define styles in AppThemes

Android: changing colour of floating label (hint) in TextInputLayout in error state

I want the floating label of TextInputLayouts to change colour (e.g. to red) when there is an error. I can change the colour of the error text, but it has no effect on the appearance of the floating label (unlike someone in some other thread claimed). I couldn't use selectors for the hint colour to solve this problem either, as there does not seem to be a state defined for errors. Does anyone have any idea how to do this without having to manually program the change on error events/create a new java class (with EditText as parent)?
Here are the stylings I defined:
<style name="EditTextFloatingLabel" parent="#android:style/TextAppearance">
<item name="android:textSize">#dimen/textsize_caption_small</item>
<item name="android:layout_marginBottom">8dp</item>
<item name="android:textColor">#color/input_text_color</item>
</style>
<style name="EditTextErrorText" parent="#android:style/TextAppearance">
<item name="android:textColor">#color/error_color</item>
</style>
<style name="EditTextLayout">
<item name="android:textColorHint">#color/placeholder_color</item>
<item name="android:background">#drawable/input_field_background</item>
<item name="android:paddingBottom">#dimen/default_margin_bottom</item>
<item name="android:paddingStart">#dimen/default_margin_left</item>
<item name="android:paddingEnd">#dimen/default_margin_right</item>
</style>
<style name="EditTextTheme">
<item name="android:imeOptions">actionDone</item>
<item name="android:maxLines">1</item>
<item name="colorControlNormal">#color/primary_line_color</item>
<item name="colorControlActivated">#color/nordea_blue</item>
<item name="android:colorControlHighlight">#color/error_color</item>
<item name="android:textColorPrimary">#color/input_field_text</item>
<item name="android:textSize">#dimen/textsize_caption</item>
<item name="android:textColorHint">#color/placeholder_color</item>
</style>
<style name="EditText">
<item name="android:theme">#style/EditTextTheme</item>
<item name="android:textCursorDrawable">#drawable/cursor_blue</item>
<item name="android:paddingTop">#dimen/default_padding_top</item>
<item name="android:paddingStart">#dimen/payment_text_input_padding</item>
</style>
Usage:
<android.support.design.widget.TextInputLayout
android:id="#+id/input_field_error_wrapper_light"
style="#style/EditTextLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="#dimen/testlogin_text_input_end_padding"
android:layout_marginStart="#dimen/testlogin_text_input_start_padding"
android:paddingTop="#dimen/default_padding_top"
app:hintTextAppearance="#style/EditTextFloatingLabel"
app:errorTextAppearance="#style/EditTextErrorText"
app:errorEnabled="true">
<EditText
android:id="#+id/input_field_light_error"
style="#style/EditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#Input Field Disabled Light"
android:imeOptions="actionDone"
/>
</android.support.design.widget.TextInputLayout>
And this is what I see:
As I needed to perform some other actions as well when the layout was in error state, I decided to go with the solution of creating a custom error state and a custom TextInputLayout which can enter this state.
Code:
Defining the new error state in res/values/attrs.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
...
<!-- custom states -->
<declare-styleable name="ErrorState">
<attr name="state_error" format="boolean" />
</declare-styleable>
</resources>
ErrorStateTextInputLayout class:
public class ErrorStateTextInputLayout extends TextInputLayout {
private boolean hasError = false;
private static final int[] ERROR_STATE = new int[]{R.attr.state_error};
public ErrorStateTextInputLayout(Context context) {
super(context);
}
public ErrorStateTextInputLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ErrorStateTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected int[] onCreateDrawableState(int extraSpace) {
int[] state = super.onCreateDrawableState(extraSpace + 1);
if (hasError) {
mergeDrawableStates(state, ERROR_STATE);
}
return state;
}
#Override
public void setError(#Nullable CharSequence error) {
if (error == null) {
setHasError(false);
} else {
setHasError(true);
}
super.setError(error);
}
public void setHasError(boolean error) {
this.hasError = error;
refreshDrawableState();
}
}
Selector for setting the hint text colour:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:color="#color/disabled_text_color" android:state_enabled="false" />
<item android:color="#color/error_color" app:state_error="true" />
<item android:color="#color/input_text_color" android:state_focused="true" />
<item android:color="#color/placeholder_color" />
</selector>
This blog post helped me a lot: http://code.neenbedankt.com/example-of-custom-states-in-android-components/
Try this..solid_red floating color.....
<style name="TextLabelInput" parent="TextAppearance.AppCompat">
<!-- Hint color and label color in FALSE state -->
<item name="android:textColorHint">#color/solid_red</item>
<item name="android:textSize">16sp</item>
<item name="android:textStyle">bold</item>
<item name="android:textColor">#color/solid_red</item>
<item name="android:duration">200</item>
<item name="android:textColorHighlight">#color/solid_red</item>
<!-- Label color in TRUE state and bar color FALSE and TRUE State -->
<item name="colorAccent">#color/solid_red</item>
<item name="colorControlNormal">#color/solid_red</item>
<item name="colorControlActivated">#color/solid_red</item>
<item name="colorPrimary">#color/solid_red</item>
<item name="colorPrimaryDark">#color/solid_red</item>
<android.support.design.widget.TextInputLayout
android:id="#+id/input_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
app:errorTextAppearance="#style/TextLabelInput"
>
hint text color manage over your main theme
which are colorPrimary and colorAccent
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
</style>

Custom view containing custom views with custom attributes and styling

Normal styling for a specific View:
<style name="Theme" parent="#android:style/Theme">
<item name="android:buttonStyle">#style/Button</item>
<item name="customDialogStyle">#style/CustomDialogStyle</item>
</style>
<style name="Button" parent="#android:style/Widget.Button">
<item name="android:textColor">#000000</item>
<item name="android:background">#FFFFFF</item>
</style>
<style name="Button.Dark">
<item name="android:textColor">#FFFFFF</item>
<item name="android:background">#000000</item>
</style>
<style name="CustomDialogStyle">
<item name="android:buttonStyle">#style/Button.Dark</item>
</style>
Some custom attributes:
<attr name="customDialogStyle" format="reference" />
<declare-styleable name="CustomDialog">
<attr name="android:buttonStyle" />
</declare-styleable>
Now with my CustomView:
public class CustomDialogContainer extends LinearLayout
{
public CustomDialogContainer(Context c) { this(c, null); }
public CustomDialogContainer(Context c, AttributeSet a) { this(c, a, R.attr.customDialogStyle); }
public CustomDialogContainer(Context c, AttributeSet a, int d) { super(c, a, d); init(c, a, d); }
private void init(Context c, AttributeSet a, int d)
{
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomDialog, d, R.style.CustomDialogStyle);
// tried getInteger and some others too
int style = a.getResourceId(R.styleable.CustomDialog_buttonStyle, android.R.attr.buttonStyle);
a.recycle();
Button bOK = new Button(c, attrs, style);
// and tried
Button bCancel = new Button(c, null, style);
// even
Button anyOne = new Button(new ContextThemeWrapper(c, style));
addView(bOK);
addView(bCancel);
}
}
This is the very basic of my DialogContainer that has all the basics (Icon, Title, Cancel, OK, Container for other views). But what I'm obviously trying to do is apply a different style from reference to the buttons on the DialogContainer.
Doesn't matter where this is. If I create any other ViewGroup or so and want to add some of my own CustomViews to it, if custom styling can't be done this way then I have no clue what they thought while creating Android.
An activity with dark buttons and a bright Dialog with bright buttons - can't be too weird?
The alternative is to add say, all the attributes individually: background, textColor, textAppearance, and so on. I thought programmers wanted to be effective.
If someone knows how to do this, I'd appreciate some input.

Apply style for button group in Android

In my Android application I need to apply style for a group of buttons, instead of styling each button individual. Something like this:
<?xml version="1.0" encoding="utf-8"?>
<!-- put here style="#ststyle/Button_Style" -->
<Button android:id="#+id/button1" android:text="#string/b01" />
<Button android:id="#+id/button2" android:text="#string/b02" />
<Button android:id="#+id/button4" android:text="#string/b03" />
<!-- end style -->
You can write the style for button like this ;
style_btn.xml
<style name="style_btn" parent="Wrap">
<item name="android:background">#drawable/btn_bg</item>
<item name="android:gravity">center</item>
<item name="android:textColor">#android:color/white</item>
<item name="android:textStyle">bold</item>
<item name="android:layout_marginTop">4dp</item>
<item name="android:minWidth">90dp</item>
</style>
apply that style to your button :
<Button
android:id="#+id/attach_file"
style="#style/style_btn"
android:layout_centerVertical="true"
android:background="#drawable/orange_bg"
android:drawablePadding="10dp"
android:drawableRight="#drawable/attach"
android:text="#string/str_email_attach" />
If you need the style to all of the buttons in your application, mention in your App theme style, Then no need to apply for every button.
<style name="YourTheme" parent="android:Theme.Light">
<item name="android:buttonStyle">#style/Button</item>
</style>
If you need the style to particluar button , then apply to every button
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="#style/Button"
android:text="Button" />
I know I'm late joining the party but I stumbled across this when trying to figure out the same problem myself.
What I did was:
Depending on how may button groups you have (say 3 for example) you need to subclass button and create three custom button classes (see below)
//Custom button 1
public class CustomButton1 extends Button {
public CustomButton1(Context context, AttributeSet attrs) {
super(context, attrs, R.attr.attrStyle1);
}
public CustomButton1(Context context, AttributeSet attrs, int defStyle) {
super(context, null, R.attr.attrStyle1);
}
}
//Custom button 2
public class CustomButton2 extends Button {
public CustomButton2(Context context, AttributeSet attrs) {
super(context, attrs, R.attr.attrStyle2);
}
public CustomButton2(Context context, AttributeSet attrs, int defStyle) {
super(context, null, R.attr.attrStyle2);
}
}
//Custom button 3
public class CustomButton3 extends Button {
public CustomButton3(Context context, AttributeSet attrs) {
super(context, attrs, R.attr.attrStyle3);
}
public CustomButton3(Context context, AttributeSet attrs, int defStyle) {
super(context, null, R.attr.attrStyle3);
}
}
You can see from the custom classes I have passed a custom attr. These I define in my styles.xml and use them as reference. See my styles.xml below:
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
</style>
<style name="theme1">
<item name="#attr/attrStyle1">#style/CustomButton1</item>
<item name="#attr/attrStyle2">#style/CustomButton2</item>
<item name="#attr/attrStyle3">#style/CustomButton3</item>
<item name="android:background">#color/warning_yellow_colour</item>
</style>
<style name="CustomButton1" parent = "#android:style/Widget.Button">
<item name="android:textColor">#color/white_colour</item>
<item name="android:padding">20dp</item>
<item name="android:background">#color/banner_background_sensor_colour</item>
</style>
<style name="CustomButton2" parent = "#android:style/Widget.Button">
<item name="android:textColor">#color/white_colour</item>
<item name="android:padding">20dp</item>
<item name="android:background">#color/button_red_colour</item>
</style>
<style name="CustomButton3" parent = "#android:style/Widget.Button">
<item name="android:textColor">#color/white_colour</item>
<item name="android:padding">20dp</item>
<item name="android:background">#color/text_blue_colour</item>
</style>
<attr name="attrStyle1" format="reference"/>
<attr name="attrStyle2" format="reference"/>
<attr name="attrStyle3" format="reference"/>
By linking the style to the attr, you then apply that style to your custom class, which you can then duplicate as many times as needed
CustomButton1 theme1 = (CustomButton1)findViewById(R.id.theme1);
CustomButton2 theme2 = (CustomButton2)findViewById(R.id.theme2);
CustomButton3 theme3 = (CustomButton3)findViewById(R.id.theme3);
Hopefully this is of benefit to someone!

How to define default styles for a custom control?

I have a custom control which extends the DialogPreference where I have custom attributes and I want to define default values for them.
Here is the relevent part of my attrs.xml:
<!-- definition of my custom attributes -->
<declare-styleable name="MyPreference">
<attr name="myAttr1" format="string" />
<attr name="myAttr2" format="reference" />
</declare-styleable>
<!-- declatation of my style for my AppTheme -->
<declare-styleable name="AppTheme">
<attr name="myPreferenceStyle" format="reference" />
</declare-styleable>
themes.xml:
<style name="AppTheme" parent="#style/Theme.Sherlock.Light.DarkActionBar">
<!-- try of replacing the default text color -->
<item name="android:textAppearance">#style/WhiteText</item>
<item name="myPreferenceStyle">#style/Preference.My</item>
</style>
styles.xml:
<style name="WhiteText" parent="#android:style/TextAppearance">
<!-- set the default color to white... however it doesn't work -->
<item name="android:textColor">#fff</item>
</style>
<style name="Preference">
<item name="android:positiveButtonText">#android:string/ok</item>
<item name="android:negativeButtonText">#android:string/cancel</item>
</style>
<style name="Preference.My">
<item name="android:dialogLayout">#layout/preferences_my_picker</item>
<item name="myAttr1">#string/unknown</item>
<item name="myAttr2">#array/bits</item>
</style>
So I have defined that I want that the class MyPreference should have the default values like this:
android:positiveButtonText = "OK"
android:negativeButtonText = "Cancel"
android:dialogLayout = <ref to a layout>
myAttr1 = "Unknown"
myAttr2 = [1, 2, 4]
But when I try to access them I get nothing:
public MyPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyPreference, defStyle, 0);
String txt = a.getText(R.styleable.MyPreference_myAttr1);
// txt == null :(
int bitsResId = a.getResourceId(R.styleable.MyPreference_myAttr2, -1);
// next line will crash bitsResId == -1
int[] bits = res.getIntArray(bitsResId);
a.recycle();
}
public MyPreference(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.myPreferenceStyle);
}
I would be really helpful if somebody could explain me what I do wrong. And also why I cannot change the default text color to white.

Categories

Resources