Turns out that even if the layout you include has layout_width and layout_height in order for android to honor the layout params that you are giving your include you need to set layout_width and layout_height within the
Wednesday, October 17, 2018
How to set layout attributes on an included layout
If you're using the tag to include parts of a layout into another layout you might also want to be able to add layout attributes to them. For example, in a RelativeLayout you might want to say that whatever you include will be below some other view. Or in a ConstraintLayout you might want to set the constraint rules on that included layout.
Turns out that even if the layout you include has layout_width and layout_height in order for android to honor the layout params that you are giving your include you need to set layout_width and layout_height within the tag.
Turns out that even if the layout you include has layout_width and layout_height in order for android to honor the layout params that you are giving your include you need to set layout_width and layout_height within the
Tuesday, February 27, 2018
How to create a selector drawable and change its states on the fly in code
If you've ever built your own buttons you will
likely use a selector Drawable to describe all the different states that the
button will go through when it's pressed or disabled etc...
To do that
the most common way to do it is by using a selector XML resource file.
Here's an
example:
<selector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:state_enabled="true" android:drawable="@drawable/normal_button"/> <item android:state_pressed="true" android:drawable="@drawable/pressed_button"/> <item app:state_red="true" android:drawable="@color/red"/> <item android:state_enabled="false" android:drawable="@color/white"/> </selector>
Now, what if
you want to change some of these conditionally or simply you want to do this in
code?
Here's what
you would write to get to the same selector behavior but using code:
StateListDrawable states = new StateListDrawable();
states.addState(
new int[]{android.R.attr.state_enabled},
getResources().getDrawable(R.drawable.blue_button));
states.addState(
new int[]{android.R.attr.state_pressed},
getResources().getDrawable(R.drawable.grey_button));
states.addState(
new int[]{R.attr.state_red},
getResources().getDrawable(R.color.red));
states.addState(
new int[]{-android.R.attr.state_enabled},
getResources().getDrawable(R.color.white));
myButton.setBackgroundDrawable(states);
As you can
see all you need is to create a StateListDrawable and add all the
states that your selector has. You can even add your own custom states (for
example here I'm using my own R.attr.state_red)
The trick is
to know that if you want to set the drawable for true you use the attribute as
it is and if you want the false case you use its negative value. (in this
example I set the disabled state using -android.R.attr.state_enabled)
Once all your
states are defined you can just use that StateListDrawable as a background
for your Button or ImageView or whatever...
Now you can
change anything you want on the fly and switch or test behavior as you need.
PS: to
declare your own stylable attributes (like my state_red) you create an attrs.xml file in your res/values/ folder and define
them like this: (all you need here for this example is the line with state_red but I added more
examples for the other possible types)
<resources> <declare-styleable name="MyButton"> <attr name="primaryColor" format="reference|color" /> <attr name="myButtonStyle" format="string" /> <attr name="state_red" format="boolean" /> <attr name="state_test" format="boolean" /> <attr name="myflags"> <flag name="one" value="1" /> <flag name="two" value="2" /> <flag name="four" value="4" /> <flag name="eight" value="8" /> </attr> <attr name="myenum"> <enum name="one" value="1" /> <enum name="two" value="2" /> <enum name="three" value="3" /> </attr> </declare-styleable> </resources>
BONUS: If you
want to set custom states and change them at runtime and in code here's what
you do:
You will have
to define your own class that extends Button or ImageView or whatever it is that
your modifying.
In that child
class, you will want to override the onCreateDrawableState method so that it
will set different states depending on whatever use case you have. Here I'm
making the state green or red depending on the value of a field variable called mMyBoolean:
@Override protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 2);
if (mMyBoolean) {
mergeDrawableStates(drawableState, {R.attr.state_green});
} else {
mergeDrawableStates(drawableState, {R.attr.state_red});
}
return drawableState;
}
}
Then all you
have to do is set that boolean to whatever value it needs to be for your use
case and then call refreshDrawableState(); on
your Button or ImageView or whatever your View is.
Subscribe to:
Posts (Atom)