how to get Theme attributes values - android

Is it possible to obtain styled attributes values from particular Theme without setting the theme up to application/activity?
(I mean before invoking context.setTheme(..))

For example, to get editTextColor attribute's value of a theme called MyTheme:
TypedArray a = getTheme().obtainStyledAttributes(
R.style.MyTheme,
new int[] { R.attr.editTextColor });
// Get color hex code (eg, #fff)
int intColor = a.getColor(0 /* index */, 0 /* defaultVal */);
String hexColor = Integer.toHexString(intColor);
// Don't forget to recycle
a.recycle();

JavaDoc:
method TypedArray
android.content.res.Resources.Theme.obtainStyledAttributes(int[]
attrs)
Return a TypedArray holding the values defined by Theme which are
listed in attrs.
Be sure to call TypedArray.recycle() when you are done with the array.

if you need it in the xml file, you can use something like this:
style="?android:attr/panelTextAppearance"
for example:
<TextView
style="?android:attr/panelTextAppearance"
android:paddingTop="?android:attr/paddingTop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/your_text"
/>
if you're using eclipse, control+click on the item, to see other possible values (a file attrs.xml will open).

Related

Get attr color value based on current set theme

In my activity I'm maintaining a SuperActivity, in which I'm setting the theme.
public class SuperActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme(R.style.MyTheme);
}
}
themes.xml
<!-- ImageBackround -->
<style name="Theme.MyTheme" parent="ThemeLight">
<item name="myBgColor">#color/translucent_black</item>
</style>
Now I want to fetch this color in one of my child activity.
As mentioned in this probable answer, I wrote:
int[] attrs = new int[] { R.attr.myBgColor /* index 0 */};
TypedArray ta = ChildActivity.this.obtainStyledAttributes(attrs);
int color = ta.getColor(0, android.R.color.background_light);
String c = getString(color);
ta.recycle();
But everytime I'm getting the value of the default value of android.R.color.background_light & not of R.attr.myBgColor.
Where I'm doing wrong. Am I passing the wrong context of ChildActivity.this?
You have two possible solutions (one is what you actually have but I include both for the sake of completeness):
TypedValue typedValue = new TypedValue();
if (context.getTheme().resolveAttribute(R.attr.xxx, typedValue, true))
return typedValue.data;
else
return Color.TRANSPARENT;
or
int[] attribute = new int[] { R.attr.xxx };
TypedArray array = context.getTheme().obtainStyledAttributes(attribute);
int color = array.getColor(0, Color.TRANSPARENT);
array.recycle();
return color;
Color.TRANSPARENT could be any other default for sure. And yes, as you suspected, the context is very important. If you keep getting the default color instead of the real one, check out what context you are passing. It took me several hours to figure it out, I tried to spare some typing and simply used getApplicationContext() but it doesn't find the colors then...

Custom Type attributes for a custom android view

I want to create a custom Android View (MyCustomView). In this View I want to have a property of a custom Type (MyCustomType). Similar to this:
MyCustomView extends LinearLayout {
private MyCustomType prop1;
public MyCustomType getProp1()
{
return this.prop1;
}
public void setProp1(MyCustomType value)
{
this.prop1 = value;}
}
}
So far so good. But now I want to be able to set the value of this property from XML. I can create a custom attribute with string, int, reference format, but I do not see how to define this attribute to be of MyCustomType format. I image something similar to this:
<declare-styleable name="MyCustomView">
<attr name="prop1" format="MyCustomType"/>
</declare-styleable>
Is this possible somehow? Or custom type attributes are possible to be set only from code behind?
Thank you!
I don`t really understand why you need this. but you can use format="String" and write full class name in property field in your layout. For example:
custom:prop1="com.example.MyCustomType"
then in constructor of your View:
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.MyCustomView,
0, 0);
String className = a.getString(R.id.prop1);
Class<MySustomType> c = Class.forName(className);
MySustomType prop = c.newInstance();
setProp1(prop);
You cannot use own property types with android framework. You can come with own proprties based on available types but that's it. Not sure what type you got in mind in your case, but in most cases whatever that custom thing is, it could be solved by available primitives.

How to change textcolor of switch in Android

I'm creating an application which uses Android 4.0.
I'm wondering if it is possible to change the text color of the text in a switch.
I've tried setting the text color, but it doesn't work.
Any ideas?
Thanks in advance!
You must use android:switchTextAppearance attribute, eg:
android:switchTextAppearance="#style/SwitchTextAppearance"
and in styles:
<style name="SwitchTextAppearance" parent="#android:style/TextAppearance.Holo.Small">
<item name="android:textColor">#color/my_switch_color</item>
</style>
you can also do it in code, also using above styles:
mySwitch.setSwitchTextAppearance(getActivity(), R.style.SwitchTextAppearance);
...and as for setTextColor and Switch - this color will be used if your SwitchTextAppearance style doesn't provide a textColor
you can check it in Switch source code in setSwitchTextAppearance:
ColorStateList colors;
int ts;
colors = appearance.getColorStateList(com.android.internal.R.styleable.
TextAppearance_textColor);
if (colors != null) {
mTextColors = colors;
} else {
// If no color set in TextAppearance, default to the view's textColor
mTextColors = getTextColors();
}
ts = appearance.getDimensionPixelSize(com.android.internal.R.styleable.
TextAppearance_textSize, 0);
if (ts != 0) {
if (ts != mTextPaint.getTextSize()) {
mTextPaint.setTextSize(ts);
requestLayout();
}
}
I think you have to look at the theme which you are using for your application. Because the color of the switch is the responsibility of the theme, afaik. So I would suggest you have a look on how you can change the settings of a theme. Or you could create a custom theme with the new colors.
TextView.setTextColor() takes an int representing the color (eg. 0xFFF5DC49) not the resource id from the xml file. In an activity, you can do something like:
textView1.setTextColor(getResources().getColor(R.color.mycolor))
outside of an activity you'll need a Context eg.
textView1.setTextColor(context.getResources().getColor(R.color.mycolor))
For more refer this

Using an array reference as an XML attribute for custom android view

This problem has been solved, see comments for details.
I am extending an existing Android View and loading some custom attributes, as described in Declaring a custom android UI element using XML and Defining custom attrs.
Attributes with boolean and integer formats work fine, but when I try to specify a reference to an array resource, the application crashes at launch. I have defined an integer array inside an xml resource file and I'm trying to use it as an attribute for the custom view.
I can use the array resource to set the "entries" attribute of the android Spinner class with no errors, so it seems to be a problem in my implementation. The logcat messages don't seem to supply any specific information about the crash, but I'm still looking so I will update if I find something.
The attributes are declared by (in attrs.xml):
<declare-styleable name="CustomView">
<attr name="values" format="reference"/>
<attr name="isActive" format="boolean"/>
</declare-styleable>
The array is defined as (in arrays.xml):
<integer-array name="nums">
<item>1</item>
<item>2</item>
<item>3</item>
</integer-array>
And I am referencing the array by:
<com.test.CustomView cv:values="#array/nums" />
And this causes the application to crash immediately. In addition, if I reference a color resource instead of an array then the application does not crash. Does anybody know how to deal with this problem?
Just going to piggyback off your question here, since your post shows up first if you google something like "array reference XML attribute custom view", so someone might find this helpful.
If you want your custom view to reference an array of strings, you can use Android's existing android:entries XML attribute, instead of creating a totally new custom attribute.
Just do the following in res/values/attrs.xml:
<resources>
<declare-styleable name="MyCustomView">
<attr name="android:entries" />
</declare-styleable>
</resources>
Then do this in your custom View's constructor:
public MyCustomView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyCustomView, defStyle, 0);
try
{
CharSequence[] entries = a.getTextArray(R.styleable.MyCustomView_android_entries);
if (entries != null)
{
//do something with the array if you want
}
}
finally
{
a.recycle();
}
}
And then you should be able to reference a string array via the android:entries attribute when you add your custom View to an XML layout file. Example:
<com.example.myapp.MyCustomView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:entries="#array/my_array_of_strings" />
This is exactly how it is done in the ListView class (look in the source, you'll see).
The other answer works well with array of strings. However, arr.getTextArray(...) on array of references, e.g.
<array name="tmp">
<item>#drawable/a</item>
<item>#drawable/b</item>
</array>
will give you res/drawable/a.png as the CharSequence instead of the resource id.
The proper way to parse an array of references is this:
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomView);
int arrayResourceId = typedArray.getResourceId(R.styleable.CustomView_CustomAttr, 0);
if (arrayResourceId != 0) {
final TypedArray resourceArray = getResources().obtainTypedArray(arrayResourceId);
for (int i = 0; i < resourceArray.length(); i++) {
final int resourceId = resourceArray.getResourceId(i, 0);
// do stuff with resourceId, such as getResources().getDrawable(resourceId)
}
resourceArray.recycle();
}
typedArray.recycle();
The question is about obtain an integer array, for my case, I need to read the colors(int) from an array for my custom view, styeable definition as below:
<declare-styleable name="ColorPickerView">
<attr name="colors" format="reference" />
</declare-styleable>
Then I use my custom view like below:
<com.rainliu.colorpicker.ColorPickerView
android:id="#+id/rtePalette"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
colorPickerView:colors="#array/colorPickerColors"
/>
The colors definition is as below:
<resources>
<color name="colorPrimary">#FF9800</color>
<array name="colorPickerColors">
<item>#000000</item>
<item>#E65100</item>
<item>#color/colorPrimary</item>
</array>
</resources>
So I need to obtain the colors in my custom view (ColorPickerView), code as below:
TypedArray ta = context.obtainStyledAttributes(attributeSet, R.styleable.ColorPickerView);
int colorsId = ta.getResourceId(R.styleable.ColorPickerView_colors, 0);
int[] colorsArray = ta.getResources().getIntArray(colorsId);
for (int a : colorsArray) {
Log.e("AA", "color == " + a);
}
ta.recycle();
Here is the print of colorsArray:
03-11 14:25:53.894 15300-15300/com.chinalwb.are E/AA: color == -16777216
03-11 14:25:53.894 15300-15300/com.chinalwb.are E/AA: color == -1683200
03-11 14:25:53.894 15300-15300/com.chinalwb.are E/AA: color == -1683200
Hope this will help some guys.

Creating an Android View with a particular style programmatically

Other questions say that the style cannot be set programmatically, but a View can be initialised with a style such as when it is loaded from XML.
How can I initialise a View with a particular style programmaticly (not in XML)? I tried using View(Context context, AttributeSet attrs, int defStyle), but I don't know what to parse in for the second argument. Passing in null results in the View not being displayed
I'm having the same problem, but haven't found any practical way to directly set a style programmatically, so far. I would like to populate my screen with a lot of widgets, of a given type, let's say buttons. It is impractical to define them all in the layout file. I would like to create them programmatically, but I would also like to define their style in a style xml file.
The solution I have devised consists in defining just one of those widgets in the layout file, create all the others programmatically, and clone the style info from the first one to the other ones.
An example follows.
In the style file, define the style for your buttons. For example:
<style name="niceButton">
<item name="android:layout_width">160dip</item>
<item name="android:layout_height">60dip</item>
<item name="android:gravity">center</item>
<item name="android:textSize">18dip</item>
<item name="android:textColor">#000000</item>
</style>
Then subclass class "Button", by deriving a class "NiceButton". Define the constructor that will be needed by the inflater:
public NiceButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
Then define another constructor, which purpose is to clone an existing button:
public NiceButton(int id, NiceButton origButton) {
super(origButton.getContext());
setId(id);
setLayoutParams(origButton.getLayoutParams());
setGravity(origButton.getGravity());
setPadding(origButton.getPaddingLeft(),
origButton.getPaddingTop(),
origButton.getPaddingRight(),
origButton.getPaddingBottom());
setTextSize(TypedValue.COMPLEX_UNIT_PX, origButton.getTextSize());
setTextColor(origButton.getTextColors());
// ... also copy whatever other attributes you care about
}
In your layout file, define just the first one of your buttons. Suppose for example that you want to put your buttons in a table:
<TableLayout android:id="#+id/button_table"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TableRow android:id="#+id/button_row_0">
<com.mydomain.mypackage.NiceButton
style="#style/niceButton" android:id="#+id/button_0" />
<!-- More rows/buttons created programmatically -->
</TableRow>
</TableLayout>
Notice that the full qualified name of the widget class is used; obviously, you will have to replace com.mydomain.mypackage with the actual package name.
In your activity, you may want to define an array which is going to hold a reference to all of the buttons, and a common listener to be called when any of the buttons is pressed:
NiceButton[] mButtonViews = new NiceButton[10];
private View.OnClickListener mNiceButtonClickListener = new View.OnClickListener() {
public void onClick(View view) {
int i = view.getId();
mButtonViews[i].setText("PRESSED!");
}
};
Notice how the view id is used as an index in the array of buttons. So you will need your buttons to have an id from 0 to n-1.
Finally, here is the way you can create your buttons in the onCreate method:
// Retrieve some elements from the layout
TableLayout table = (TableLayout)findViewById(R.id.button_table);
TableRow row = (TableRow)findViewById(R.id.button_row_0);
NiceButton origButton = (NiceButton)findViewById(R.id.button_0);
// Prepare button 0
origButton.setId(0);
origButton.setText("Button 0");
origButton.setOnClickListener(mNiceButtonClickListener);
mButtonViews[0] = origButton;
// Create buttons 1 to 10
for (int i = 1; i < 10; i++) {
if (i % 2 == 0) {
row = new TableRow(this);
table.addView(row);
}
NiceButton button = new NiceButton(i, origButton);
button.setText("Button " + i);
button.setOnClickListener(mNiceButtonClickListener);
mButtonViews[i] = button;
row.addView(button);
}
Here's how the screen appears after you have pressed some buttons:
Well, there's some code involved, but in the end you can create as many widgets you want programmatically, and still have their attributes defined as a style.
If you want to style a view you have 2 choices: the simplest one is to just specify all the elements in code:
button.setTextColor(Color.RED);
button.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
The other option is to define the style in XML, and apply it to the view. In the general case, you can use a ContextThemeWrapper for this:
ContextThemeWrapper newContext = new ContextThemeWrapper(baseContext, R.style.MyStyle);
button = new Button(newContext);
To change the text-related attributes on a TextView (or its subclasses like Button) there is a special method:
button.setTextAppearance(context, R.style.MyTextStyle);
This last one cannot be used to change all attributes; for example to change padding you need to use a ContextThemeWrapper. But for text color, size, etc. you can use setTextAppearance.
AttributeSet contains the list of attributes specified in xml (ex. layout_width, layout_height etc).
If you are passing it as null, then you should explicitly set the height/width of view.

Categories

Resources