Question

At least I believe that is the problem. From the API documentation:

inflate(int resource, ViewGroup root) Inflate a new view hierarchy from the specified xml resource.

I've been fighting with an orientation change bug for some time now, and I think I have isolated the origin of the problem. The following code does not behave as I would expect:

SeekBarTestActivity.java

public class SeekBarTestActivity extends Activity {

private LinearLayout layout;
private InflateSeekBar bar1;
private InflateSeekBar bar2;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    layout = new LinearLayout(this);
    layout.setOrientation(LinearLayout.VERTICAL);
    setContentView(layout);

    bar1 = new InflateSeekBar(this, layout);
    bar2 = new InflateSeekBar(this, layout);
}
}

InflateSeekBar.java

public class InflateSeekBar {

private SeekBar seekBar;

public InflateSeekBar(Context ctx, ViewGroup parent) {

    LayoutInflater inflater = LayoutInflater.from(ctx);
    View view = inflater.inflate(R.layout.seekbar_layout, null);

    seekBar = (SeekBar) view.findViewById(R.id.seekBar);
    seekBar.setMax(300);
    parent.addView(view);
}
}

The .xml resource file is just as one would expect, a SeekBar inside a LinearLayout. What I am expecting is two objects each containing a new SeekBar, not tied to one another in any way. Furthermore, I would not expect the SeekBars to retain their progress on an orientation change, instead they should be destroyed and recreated with the activity. However, not only does the second SeekBar retain it's progress, but the first SeekBars progress matches the second. I'm hoping that someone could explain to me why the seekbars are behaving this way so that I can use this knowledge to fix the bugs in my program. Thank you for any knowledge in advance.

Edit - Solved: Just to be clear, my problem was the fact that I was not giving unique ID's to the SeekBars after they were inflated, causing the JVM to treat them as the same object in some respects. Thank you for your help Emanuel Moecklin, that bug was driving me nuts!

Was it helpful?

Solution

What I am expecting is two objects each containing a new SeekBar, not tied to one another in any way.

They are tied to each other because the have the same id (which is R.id.seekBar). When Android saves and restores the view hierarchy each view to save/restore needs a unique id:

The default implementation takes care of most of the UI per-instance state for you by calling onSaveInstanceState() on each view in the hierarchy that has an id, and by saving the id of the currently focused view (all of which is restored by the default implementation of onRestoreInstanceState(Bundle))

see http://developer.android.com/reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle)

So what you need to do is call seekBar.setId(id) with id being a unique id within this view hierarchy. You can e.g. use this answer to generate a unique id: https://stackoverflow.com/a/21000598/534471

Furthermore, I would not expect the SeekBars to retain their progress on an orientation change, instead they should be destroyed and recreated with the activity.

You can simply override onSaveInstanceState() to prevent the view hierarchy from being saved and restored but I doubt that this makes sense from a user perspective. If I rotate the screen I don't want to lose the position of "my" SeekBars.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top