I’m working on an interface that provides a set of multiple Button objects, each of which has attached the same OnClickListener. When said Buttons are clicked, they should launch an Activity, as specified in onClick.
Here is my code for reference:
public class Calcs extends SherlockFragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// ...
CalcLoader buttonListener = new CalcLoader(getActivity());
LinearLayout buttons = (LinearLayout) v.findViewById(R.id.calculatorlist); // v is the inflated View
for (int i = 0; i < buttons.getChildCount(); i++) {
View b = buttons.getChildAt(i);
if (b instanceof Button) {
((Button) b).setOnClickListener(buttonListener);
}
}
// Test Code: Location 1
Intent i = new Intent(getActivity(), MyCalcActivity.class);
getActivity().startActivity(i);
// ...
}
private class CalcLoader implements OnClickListener {
private Activity mOwner;
public CalcLoader(Activity owner) {
mOwner = owner;
// Test Code: Location 2
Intent i = new Intent(mOwner, MyCalcActivity.class);
mOwner.startActivity(i);
}
public void onClick(View v) {
if (v instanceof Button) {
// Actual Code: Location 3
Intent i = new Intent(mOwner, MyCalcActivity.class);
mOwner.startActivity(i);
}
}
}
}
Despite this, however, I’m getting some odd behavior. In the above code, I’ve placed some startActivity tests, labelled locations 1 and 2. In both cases, the Activity launches correctly, and all is well!
However, at location 3, where the working code should execute, I get some strange behavior from the launched Activity:
- At first, the
Activityis launched just fine. It displays a single text field and it is focused, with the soft keyboard coming up. This is correct. - Now, when I click the back button, the keyboard closes. This is correct.
- Click back again, and the field loses focus. This should NOT happen. Instead, the
ActivitySHOULD close and return to the previous one. - Click back again, and the entire app closes (instead of returning to the previous
Activity). Obviously, this should NOT happen.
To reiterate, when the Activity is started from location 1 or 2, everything functions correctly; the back stack is correct and returns to the initial Activity properly.
What is going wrong here? Why, when I start my Activity from onClick, does it fail, while it works from any other location?
Update: Saving the Intent in the constructor and reusing it in the onClick method produces the same glitched result, as does starting the Activity from the UI thread.
Second update: Making the text field unfocusable had no effect on the glitch; the back button still closed the app. Additionally, running in the 2.3.3 emulator had the same result. Oddly, though, after the second back button press (the text field losing focus), if you wait ~3 seconds, the Activity closes and returns to the main one.
Third update: No key events (onKeyDown or onBackPressed) are fired for the back button that takes focus from the text field. Additionally, if you interact with the Activity after the text field loses focus, it shows the animation of loading a new Activity of the same type, but the glitch is present here as well.
This appears to be an OS-level issue, found in Android 2.2 (API 8), 2.3.1 (API 9), and 2.3.3 (API 10). Eclair (API 7), and APIs 11+ do not have this issue. At this point, I believe I’m looking for some kind of workaround…
Turns out my issue was not caused by something I detailed in my original post, so I apologize for that.
The issue was caused by a
SurfaceViewitem on a tab unrelated to the tab I was testing on. After rebuilding the tabs and layouts from the ground up (and building each time), I discovered the lag-back-glitch was only caused when aSurfaceViewwas present in a non-focused tab.I finally found that I was not the only one with this issue.
To solve:
onPausemethod in the mainActivity. In here, I destroy theSurfaceViewusingcontainer.removeView(..);.onResumemethod in the mainActivity. In here, I inflate theSurfaceViewfrom a new XML file containing ONLY theSurfaceViewitem, and add it to the originalcontainer.android.view.SurfaceHolder.Callbackin theSurfaceViewto erase the contents of the surface before it is removed.It stumps me that this happens only on APIs 8-10, but I’m glad it’s solved now. Kudos to everyone that offered their assistance!