7

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);
}
15
  • but....what's the error? Commented Apr 17, 2015 at 6:08
  • @Leo topic updated sir Commented Apr 17, 2015 at 6:13
  • if you create your custom view by calling new ButtonTextStyle() so what xml file are you talking about? Commented Apr 17, 2015 at 6:30
  • why don't you use new ButtonTextStyle() ? Commented Apr 17, 2015 at 9:09
  • @pskink i can not use ButtonTextStyle inside programically to set font defined into attributes Commented Apr 17, 2015 at 9:19

2 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

2 Comments

now how to set consolas attribute font via programical ?? font_button is enum and i can not choose consolas from it
@mahdipishguy I've updated my answer. But I can not guarantee that it works.
2

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));
        }
    }

Setting the property programmatically

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);

Yet ANOTHER Update

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;

5 Comments

i say i dont have any problem to set attribute via xml, my problem is set that programical
thanks sir. i want to set app:font_button="consolas" like with xml via programical :)
thanks sir, i can use this method. my widgets is Button and i'm define that by this way: Button button = new Button(context); and i dont know whats buttonTextStyle1 and my app could not detect ButtonTextStyle.CONSOLAS
Your widget is ButtonTextStyle...unless I'm missing something. If you cast button to ButtonTextStyle you should have no problems...I'm pretty sure you know what I'm saying otherwise you wouldn't be able to write all that code in first place
hope this help, mate. If you happen to have more doubts. Please post a different question!!!!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.