1

I am running into a problem with RelativeLayout and ViewSwitcher here and maybe someone is able to help. So what I want is switching two views using a ViewSwitcher, however, the fact that a switcher is even part of the equation should be hidden from the user/developer; instead, they should only ever deal with either one of the two views that are being switched.

For this to work, what I am doing is provide a custom widget which upon inflation, removes itself from the view tree, inserts a ViewSwitcher in its previous position, and then re-inserts itself as a child of the view switcher. That part works fine.

If now I have two of these views, positioning them relative to the parent (e.g. using layout_alignParentBottom) works just fine, but not when I try to position them relative to each other using e.g. layout_toRightOf=id.

It does work, however, when I copy the switched view's ID over to the ViewSwitcher (its new parent), but I don't understand why that is necessary and will probably rain frogs or something when having more than one view with the same ID in the view tree?

Here's some code for clarification:

// onLayout of the custom view that automatically inserts itself under a ViewSwitcher
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);

    if (!(getParent() instanceof ViewSwitcher)) {

        // uncommenting this line fixes the issue,
        // but I don't want duplicate IDs!
        //switcher.setId(getId());

        // "migrate" this view's LPs to the new parent
        switcher.setLayoutParams(getLayoutParams());

        ViewGroup parent = (ViewGroup) this.getParent();
        System.out.println("PARENT: " + parent);
        int selfIndex = parent.indexOfChild(this);
        parent.removeView(this);
        parent.addView(switcher, selfIndex);

        ViewSwitcher.LayoutParams newParams = new ViewSwitcher.LayoutParams(
                LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
        switcher.addView(this, newParams);
    }
}

Then in a layout XML file, the user merely needs to inflate this custom view:

<com.myview.CustomView android:id="@+id/one" ... />
<!-- this works: -->
<com.myview.CustomView android:layout_alignParentTop="true" ... />
<!-- this doesn't without the ID hack: -->
<com.myview.CustomView android:layout_toRightOf="@id/one" ... />

in other words, since layout_toRightOf becomes an attribute of the new ViewSwitcher, while the ID remains an attribute of the custom view, aligning the switcher relative to a view that's a child of another view switcher does not work, and I have no idea why. Only if I also give the switcher the same ID as its child then positioning will work.

Any pointers as to what's going wrong here?

mxk
  • 43,056
  • 28
  • 105
  • 132

1 Answers1

1

Not sure if I'm right, but isn't it the case that views have to be on the same level of the view hierarchy when you're positioning them relatively to each other?

So maybe you should define your reference the other way round: View one has the android:layout_toRLeftOf"@id/two attribute and once you create the ViewSwitcher you just copy the layout param of the child.

Macarse
  • 91,829
  • 44
  • 175
  • 230
Maria Neumayer
  • 3,337
  • 3
  • 27
  • 44
  • I think you may be right about only being able to reference views on the same level (i.e. siblings). Not sure I understand your suggestions though. Wouldn't that introduce the same asymmetry? Just to clarify: the views inside the view switcher should keep their IDs, since otherwise a call to findViewById would return a different view from the one declared in the layout XML. Moreover, they cannot specify `layout_toRightOf`, since they will have `ViewSwitcher.LayoutParams`, which doesn't support relative placement. Or am I just missing your point? – mxk May 03 '12 at 09:56
  • Interesting, reading another post here I just discovered that in fact view IDs need *not* be unique. I then checked what `findViewById` returns, and it was the child view, not the ViewSwitcher, even if they share the ID. This is exactly what I need, but I wonder which logic findViewById applies if there's more than one view with the same ID? – mxk May 03 '12 at 10:06
  • But you have to use the layoutParams of the parent, which should be a RelativeLayout. So you should be able to get the layoutParams of your CustomView, set the layoutParams of the ViewSwitcher (not the child!) and it should be fine. Not sure if I understood your hierarchy completely though :) – Maria Neumayer May 03 '12 at 11:05
  • And about the second question (and this is just guessing) I assume it uses the view that has been defined first, which is the one you've defined in the xml. – Maria Neumayer May 03 '12 at 11:07