6

I have following custom button view.

public class PrayerTimeLabel extends Button {

int hours;
int minutes;
String dayHalf; //am or pm
Context parentActivity;
PrayerControl parentControl;

public PrayerTimeLabel(Context context,PrayerControl parent) {
    super(context);                 
    init(context,parent,0);
}

public PrayerTimeLabel(Context context, int defStyle, PrayerControl parent) {
    //super(context, null, R.style.Button_PrayerTimeButton);
    super(context, null, defStyle);             
    init(context,parent,defStyle);
}


private void init(final Context context, PrayerControl parent, int defStyle)
{        
    parentActivity = context;
    parentControl = parent;
    Typeface tf = Typeface.createFromAsset(context.getAssets(),"fonts/digital.ttf");
    this.setTypeface(tf);       
    this.setText(false);

    this.setOnClickListener(new OnClickListener() {         
        public void onClick(View v) {
            TimeDialog dialogBox = parentControl.getDialogBox();
            dialogBox.setTime(hours, minutes, dayHalf);
            dialogBox.show();
        }
    });
}


public void setTime(int hrs, int min, String half,boolean signalParent)
{
    hours = hrs;
    minutes = min;
    dayHalf = half;
    this.setText(signalParent);
}

public void setText(boolean signalParent)
{
    super.setText(String.format("%02d", hours)+":"+String.format("%02d", minutes)+" "+dayHalf);
    if(signalParent){
        parentControl.setPrayerTime(hours, minutes, dayHalf);
    }
}

}

and I have the following style defined in my style.xml

    <style name="Button.PrayerTimeButton" parent="@android:style/TextAppearance.Widget.Button">
    <item name="android:background">#000</item>
    <item name="android:textSize">18dp</item>
    <item name="android:textColor">#FFFF00</item>
</style>

The extended button is not getting this style. Can some on point our what I am doing wrong? I searched for the solution and found this. Can some one suggest some thing

Note: I cannot use XML to apply styles. It has to be constructor.

Edit:

Following is the class where this custom button is created and used. I have deleted many irrelevant lines of code

public class PrayerControl extends LinearLayout {


protected PrayerTimeLabel prayerTimeButton;

protected String prayerName;
protected static int counter=0;


public PrayerControl(Context context) {
    super(context);
    init(context);
}

public PrayerControl(Context context, AttributeSet attrs) {
    super(context, attrs);
    getXMLAttributes(context, attrs);
    init(context);
}

    protected void getXMLAttributes(Context context, AttributeSet attrs)
{
    TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.PrayerControl);

    prayerName = a.getString(R.styleable.PrayerControl_name);
    dayHalf = a.getString(R.styleable.PrayerControl_dayHalf);
    hours = a.getInteger(R.styleable.PrayerControl_hours, 4);
    minutes = a.getInteger(R.styleable.PrayerControl_minutes, 30);

    ltrProgress = a.getInteger(R.styleable.PrayerControl_postNamazInterval, 0);
    rtlProgress = a.getInteger(R.styleable.PrayerControl_preNamazInterval, 0);
    intervalMax = a.getInteger(R.styleable.PrayerControl_intervalMax, 30);


    a.recycle();

}

protected void init(Context context)
{
    counter++;
    parentActivity = context;
    this.setOrientation(LinearLayout.HORIZONTAL);
    this.setId(counter);    

    prayerTimeButtonStyle = R.style.Button_PrayerTimeButton;
    initializePrayerTimeButton();

}


protected void initializePrayerTimeButton()
{
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
            LinearLayout.LayoutParams.WRAP_CONTENT,
            40);        
    params.gravity = Gravity.CENTER;
    //params.weight  = 1.0f;

    prayerTimeButton = new PrayerTimeLabel(parentActivity,prayerTimeButtonStyle,this);
    prayerTimeButton.setTime(hours, minutes, dayHalf,false);

    prayerTimeButton.setLayoutParams(params);
    this.addView(prayerTimeButton);
}

}
sadaf
  • 719
  • 2
  • 8
  • 19

5 Answers5

3

This is an old answer: I got a -1 a couple of minutes ago and here is the

NEW SOLUTION:

The basic idea is to pass an attribute to the constructor. Check this link for the complete solution: Applying style to views dynamically in java code

OLD SOLUTION (NOT WORKING):

Add these constructors to your class:

public StyledButton(Context context) {
    super(context, null, R.style.Button_PrayerTimeButton);
//... whatever
}

public StyledButton(Context context, AttributeSet attrs) {
    super(context, attrs, R.style.Button_PrayerTimeButton);
//... whatever
}

public StyledButton(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, R.style.Button_PrayerTimeButton);
//... whatever
}
Sherif elKhatib
  • 45,786
  • 16
  • 89
  • 106
2

Why not use setTextAppearance(Context context, int resid);. It lets you set the text color, size, style, hint color, and highlight color.

In PrayerTimeLabel class,

private void init(final Context context, PrayerControl parent, int defStyle)
{        
    setTextAppearance(context, R.style.Button_PrayerTimeButton);
    ...
}

For more info see this post : setTextAppearance through code referencing custom attribute

Community
  • 1
  • 1
Ron
  • 24,175
  • 8
  • 56
  • 97
  • Its not just textView, textview is the simplest of all that is why I have pasted the code for textview. I have other custom controls that inherit from SeekBar and other android controls. I am having issues setting the styles for all of them. – sadaf Jun 26 '12 at 19:14
1

Here is an old answer (and simpler) for this topic: https://stackoverflow.com/a/21455192/4360308

Summarizing:

ContextThemeWrapper newContext = new ContextThemeWrapper(baseContext, R.style.MyStyle); button = new Button(newContext);

Community
  • 1
  • 1
giroxiii
  • 655
  • 5
  • 14
0

You should make in your constructor a call to the super(context,attrs,defStyle) constructor, which will apply the defStyle to your View.

However you can not than change the style dinamically.

Ovidiu Latcu
  • 71,607
  • 15
  • 76
  • 84
  • I am doing it in the following line super(context, null, R.style.Button_PrayerTimeButton); in second constructor. Can you please point out what is wrong with this code? – sadaf Jun 22 '12 at 10:52
  • can I also see the code where you add those custom views to a layout? – Ovidiu Latcu Jun 22 '12 at 10:54
  • Actually, this custom button is part of another custom control which is then added to the layout. That is why i want to apply styles using constructor and not using XML. Let me update the question to add code there... – sadaf Jun 22 '12 at 11:13
0

The bug report you link to states:

In addition, when dynamically creating elements at run-time this means that you can't simply apply a style in code. You need to create a separate XML layout for the view you're building, and inflate it [...]

With this in mind, a solution could look like this:

Create an xml layout for your button - let's call it prayertimebutton.xml:

<Button android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#FFFF00"
        //...etc
/>

Then, in the initializePrayerTimeButton method in your PrayerControl class, inflate and add the PrayerTimeLabel button to the PrayerControl layout:

//Retrieve a LayoutInflater instance that is hooked up to the current context
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//The LayoutInflater instantiates the layout file into a PrayerTimeLabel object
PrayerTimeLabel button = (PrayerTimeLabel)inflater.inflate(R.layout.prayertimebutton, this, false);
//add the PrayerTimeLabel to the PrayerControl
this.addView(button);

Note that the second parameter of LayoutInflater.inflate() is a reference to the parent View(Group).

The below answer by adamp, an Android framework engineer at Google, discusses this approach in more detail.

Why so complex to set style from code in Android

Community
  • 1
  • 1
Gunnar Karlsson
  • 28,350
  • 10
  • 68
  • 71
  • Yes, I read that but I don't want to use XML layout files. It has to be done using constructors. This issue was reported in 2010, I am surprised that there is no updates to this issue.. – sadaf Jun 29 '12 at 08:17
  • May I ask why you have to use constructors? My understanding was you need to instantiate the button dynamically with its own style and add it dynamically to a layout, which the solution in my answer makes possible. From the bug report it appears using constructors to pass the style is a dead end. It is indeed surprising there are no updated to this. – Gunnar Karlsson Jun 29 '12 at 09:18
  • because I have about 15 custom controls and inflating so many XML files is not good in terms of resources so i was thinking may be some one has found a solution for this issue but it seems i was wrong :( – sadaf Jun 29 '12 at 09:59