I'm extending a HorizontalScrollView. This layout will add children to a LinearLayout when the public setItems
method is called. These children views are dynamically inflated and their widths depend on the parent (fill parent when only one view, and 1/2 parent when >= 2 items).
<!-- custom_layout.xml -->
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/container"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="match_parent">
</LinearLayout>
</merge>
Sometimes, setItems
is called in a callback of a network request, so the layout might already be fully inflated. Where should I be calling updateView
which needs the parent's width and to add inflated children? I put the call in both onSizeChanged
and setItems
like below.
public class CustomLayout extends HorizontalScrollView {
private LinearLayout container;
private List<Item> items;
public void setItems(List<Item> items) {
this.items = items;
updateView();
}
public CustomLayout(Context context) {
super(context);
init();
}
public CustomLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
View v = inflate(getContext(), R.layout.custom_layout, this);
container = (LinearLayout) v.findViewById(R.id.container);
updateView();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
updateView();
}
public void updateView() {
if (items == null) {
return;
}
container.removeAllViews();
int width = getWidth();
if (items.size() > 1) {
width = width * 1 / 2;
}
for (final Item item : items) {
View child = LayoutInflator.from(getContext(), R.layout.custom_item, container, false);
child.setLayoutParams(new LinearLayout.LayoutParams(width, LinearLayout.LayoutParams.MATCH_PARENT));
container.addView(child);
}
}
}
I don't know why this way does not always work. Sometimes, the child, container
just fails to render for some reason. Seeing the layout hierarchy shows that HorizontalScrollView has no children. What happened to container
?
Also, it seems that even when placed in a network call, setItems
is called before onSizeChanged
, which makes me think that onSizeChanged
is the wrong place to do updateView
?
Try to place the
updateView()
method insideonMeasure
instead ofonSizeChanged
, and usegetMeasuredWidth()
instead ofgetWidth()
:Also, if you call
setItems()
method from callback of async request, dont forget to run it on UI thread by usingrunOnUiThread
method ofActivity
.