My custom view is only drawn when added to onCreate

I made a custom view of "GraphBar", which is a RelativeLayout with a TextView at the bottom and an ImageView with a different height above it. Here is the code:

 public class GraphBar extends RelativeLayout { private int mAvailHeight; // space for the bar (component minus label) private float mBarHeight; // 0.0-1.0 value public GraphBar(Context context) { this(context, null); } public GraphBar(Context context, AttributeSet attrs) { this(context, attrs, 0); } public GraphBar(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); LayoutInflater.from(context).inflate(R.layout.graphbar, this, true); setId(R.id.graphBar); // defined in <merge> but not assigned (?) } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mAvailHeight = getHeight()-findViewById(R.id.label).getHeight(); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); View bar2 = findViewById(R.id.smallBar); RelativeLayout.LayoutParams llp2 = (RelativeLayout.LayoutParams) bar2.getLayoutParams(); llp2.height = Math.round((float)mAvailHeight * mBarHeight); } public void setBarHeight(float value, float max) { mBarHeight = value / max; findViewById(R.id.smallBar).requestLayout(); } public void setLabel(CharSequence c) { ((TextView) findViewById(R.id.label)).setText(c); } } 

Adding these GraphBars and setting their height in onCreate() works well if I create them onClickSomething or call setBarHeight() again on the created bars, the only way to see the changes is the Load View hierarchy. I was told here that this means I need to call requestLayout() somewhere. Where else than after changing mBarHeight ? Any help? I tried everywhere and with invalidate() too.

Thanks Andrea

(if you need, I can post the activity with which I do my tests and graphbar.xml)


I found this is probably a mistake . The workaround should also be called requestLayout() . However, I do not understand where I can call.

0
source share
1 answer

I finally found a way to call requestLayout() again. I called setWillNotDraw(false) in the constructor, so in onDraw() (i.e. after onLayout() ) I can call an additional requestLayout() . This creates a stupid cycle, but solves the problem aesthetically.

If anyone knows a better solution, let me know ... here's the new code (changes next to the comments):

 //... public GraphBar(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); LayoutInflater.from(context).inflate(R.layout.graphbar, this, true); setWillNotDraw(false); // WORKAROUND: onDraw will be used to make the // redundant requestLayout() call setId(R.id.graphBar); } //... @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // i think it one of the worst workaround one could think of. // luckily android is smart enough to stop the cycle... findViewById(R.id.smallBar).requestLayout(); } public void setBarHeight(float value, float max) { mBarHeight = value / max; View bar = findViewById(R.id.smallBar); bar.requestLayout(); // because when we create this view onDraw is called... bar.invalidate(); // ...but not when we modify it!!! //so we need to invalidate too } //... 
0
source

Source: https://habr.com/ru/post/885903/


All Articles