Madhukar Hebbar
Madhukar Hebbar

Reputation: 3183

Alter AttributeSet values in android

I am having custom view which will take attribute set(xml value) as constructor value

public CustomView(Context context)  // No Attributes in this one.
{
    super(context);
    this(context, null, 0);
}

public CustomView(Context context, AttributeSet attrs) {
    super(context, attrs);
    this(context, attrs, 0)
}

public CustomView(Context context, AttributeSet attrs, int default_style) {
    super(context, attrs, default_style);
    readAttrs(context, attrs, defStyle);
    init();
}

In Fragment class i am setting the view as

CustomView customView = (CustomView) view.findViewById(R.id.customView); 

where custom view contains various value such as height,width,padding etc.

i want to modify those values based on required condition and set it back to custom view. I placed setting width height code in onDraw method and called invalidte view. But above method will set the every time if i called invalidate method in CustomView class. how to overcome this so that i can pass modified attribute set value in constructor only.?

Edit: I need to modify the view values(initialize with new values) which is set during attribute constructor so that i will get a refreshed view with a new values. Override @OnDraw or 'Invalidate' is not a good function for me where inside invalidate i have written the methods which will execute in each second interval.

Upvotes: 3

Views: 2157

Answers (3)

Henry
Henry

Reputation: 17851

I see that your CustomView can have multiple attributes and you want to modify some of these attributes based on some condition and pass this in the constructor.

Few best practices while designing a custom view:

  1. If you have custom attributes, make sure that you expose them via setters and getters. In your setter method, call invalidate();
  2. Don't try modifying any attributes inside onDraw() or onMeasure() methods.
  3. Try your best to avoid writing Custom constructors for your Custom View.

So the ideal way to solve your problem is to instantiate your CustomView and then modify the attributes, either externally (in your Activity or Fragment), or have a method inside the CustomView.java and then invoke it externally. Doing this will still give you the same result you are looking for.

Upvotes: 2

Tim Mutton
Tim Mutton

Reputation: 756

It's probably not the solution you were hoping for, but put a FrameLayout in your xml instead of the CustomView, and then create your CustomView programmatically with the FrameLayout as it's parent

Upvotes: 0

Inverce
Inverce

Reputation: 1496

So lets say you declared your custom attributes like this for view named StarsView

<declare-styleable name="StarsView">
    <attr name="stars" format="integer" />
    <attr name="score" format="float" />
</declare-styleable>

And you want to read attributes from something like this

<my.package..StarsView
    app:stars="5"
    app:score="4.6"

You do just this in constructor

public StarsView(Context context, AttributeSet attrs) {
    super(context, attrs);
    if(attrs != null) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.StarsView, defStyleAttr, 0);
        stars = Tools.MathEx.clamp(1, 10, a.getInt(R.styleable.StarsView_stars, 5));
        score =  (int)Math.floor(a.getFloat(R.styleable.StarsView_score, stars) * 2f);
        a.recycle(); // its important to call recycle after we are done
    }
}

Upvotes: 0

Related Questions