Reputation:
in application i can simply define attr.xml
into values
and use that into design layout. but i can not set this attributes programical into widgets, for example i have this attribute:
<declare-styleable name="ButtonTextStyle">
<attr name="font_button">
<enum name="consolas" value="0" />
<enum name="times" value="1" />
</attr>
</declare-styleable>
and i can use this attribute into xml by:
<com.sample.app.Widgets.ButtonTextStyle
android:id="@+id/btn_way_bill_click"
android:layout_width="fill_parent"
app:font_button="consolas">
now i'm define some Button programical into project and i want to use consolas
font defined into font_button
by:
button.setTextAppearance(context, R.attr.font_button);
but i get error for this code and i can not resolve problem, i'm define custom class extends from Button like with this:
public class ButtonTextStyle extends Button {
private Context mContext;
public ButtonTextStyle(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
init(attrs, defStyle);
}
public ButtonTextStyle(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
init(attrs,-1);
}
public ButtonTextStyle(Context context) {
super(context);
mContext = context;
init(null,-1);
}
private void init(AttributeSet attrs,int defStyle) {
if (!isInEditMode()) {
TypedArray a = mContext.obtainStyledAttributes(attrs,R.styleable.ButtonTextStyle, defStyle, 0);
String str = a.getString(R.styleable.ButtonTextStyle_font_button);
switch (Integer.parseInt(str)) {
case 0:
str = "fonts/consolas.ttf";
break;
case 1:
str = "fonts/times.ttf";
break;
}
setTypeface(FontManager.getInstance(getContext()).loadFont(str));
}
}
}
PROBLEM:
Expected resource of type style
and i can not set for example enum to widgets like with set times
font
HOW to set programical this custom class with attribute defined into attr.xml
UPDATED: my class to add button is below method. i want to set font for it programically:
private void addButton(final CDialog owner, final Dialog dialog, final DialogButton dlgBtn) {
LinearLayout linearLayout = (LinearLayout) dialog.findViewById(R.id.tsw__layerButton);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, 70);
//layoutParams.setMargins(11, 0, 8, 0);
Button button = new Button(context);
if (buttonTheme != -1) {
button.setBackgroundResource(buttonTheme);
}
button.setPadding(0,2,0,0);
button.setGravity(Gravity.CENTER);
button.setText(buttonMsg[dlgBtn.ordinal()]);
button.setTextSize(14);
button.setTextColor(G.context.getResources().getColor(R.color.white_text));
button.setWidth(dpToPx(buttonWidth));
//button.setHeight(dpToPx(32));
button.setLayoutParams(layoutParams);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
if (dialogListener != null) {
dialogListener.onCloseDialog(owner, dlgBtn);
}
}
});
linearLayout.addView(button);
}
Upvotes: 7
Views: 13169
Reputation: 14830
I believe the proper way to achieve what you are trying to do is by first declaring an enum attribute...
<declare-styleable name="ButtonTextStyle">
<attr name="font_button" format="enum">
<enum name="consolas" value="0" />
<enum name="times" value="1" />
</attr>
</declare-styleable>
Only change from your original code is the format
attribute. Then you can declare those custom style attributes as below...
<com.sample.app.Widgets.ButtonTextStyle
android:id="@+id/btn_way_bill_click"
android:layout_width="fill_parent"
app:font_button="consolas">
but, don't forget to declare the namespace(s) your sub-widget belongs to in the parent layout, otherwise you won't be able to reference the app
alias
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.sample.app.Widgets">
and finally, your init
method would look something like this...
private void init(AttributeSet attrs,int defStyle) {
if (!isInEditMode()) {
int i = -1;
TypedArray a = mContext.obtainStyledAttributes(attrs,R.styleable.ButtonTextStyle, defStyle, 0);
try{
a.getInt(R.styleable.ButtonTextStyle_font_button, -1);
}
finally{
a.recycle();
}
switch (i) {
case 0:
str = "fonts/consolas.ttf";
break;
case 1:
str = "fonts/times.ttf";
break;
}
setTypeface(FontManager.getInstance(getContext()).loadFont(str));
}
}
To set that property programmatically, you will need to expose a "setter" method that takes an integer value, then based on that value you can change the type face. To make things easier for consumers of your custom widget you can also define two constants in your class...
public static final int CONSOLAS = 0;
public static final int TIMES = 1;
then define the setter method...
public void setFontButton(int fontButton) {
if (fontButton != CONSOLAS && fontButton != TIMES) {
throw new IllegalArgumentException(
"fontButton must be one of CONSOLAS or TIMES");
}
//load the font and set it here, the same way you did in "init"
}
All you have to do is call that setter method and pass in one of the constants specified...
buttonTextStyle1.setFontButton(ButtonTextStyle.CONSOLAS);
Instead of doing...
Button button = new Button(context);
do...
ButtonTextStyle button = new ButtonTextStyle(context);
and make sure you import the correct class so it can be used in code...
import com.sample.app.Widgets.ButtonTextStyle;
Upvotes: 2
Reputation: 37936
Maybe this article will help you Android: Set Custom Attributes Programmatically and Via XML. Note, that there should be a style assigned to the R.attr.font_button
attribute somewhere (for example in "AppTheme"). Because it's just an attribute, and it holds a reference to a value.
If you assigned a style in "AppTheme":
ButtonTextStyle button = (TextView) findViewById(R.id.btn_way_bill_click);
Resources.Theme themes = getTheme();
TypedValue storedValueInTheme = new TypedValue();
if (themes.resolveAttribute(R.attr.font_button, storedValueInTheme, true))
button.setTextAppearance(storedValueInTheme.data);
Or if you declared your own theme. It can be declared as follows
<resources>
<style name="ConsolasBtn" parent="@android:style/Widget">
<item name="font_button">consolas</item>
</style>
</resources>
Then you need to apply this theme to your button. Try
ButtonTextStyle button = (TextView) findViewById(R.id.btn_way_bill_click);
button.setTextAppearance(this, R.style.ConsolasBtn); // *this* refers to Context
Or try to pass R.style.ConsolasBtn
to your constructor ButtonTextStyle(Context context, AttributeSet attrs, int defStyle)
as the defStyle
argument.
See also Styles and Themes, Resources.Theme, TypedValue, attrs.
Upvotes: 3