I have this strange problem that happens on 1.6, 2.2 and MyTouch 3G Slide (which is API # 7 and is listed as “2.1-Update1” in the Android Device Chooser). If anyone can explain what I'm doing wrong and how to fix it (or maybe confirm that it is an Android error), I would really appreciate it!
The main idea for my application is to make a stopwatch - something like the user can press a button to start a timer, and then press it again to stop (pause) a timer; additional taps alternate between resuming the timer and pausing the timer.
I have a top-level ScrollView that contains a RelativelLayout that contains a bunch of widgets. The first widget is the HUGE button (so it's easy to press), which pushes all my other widgets below the bottom of the screen. This is intentional because I want to rely on ScrollView (and a screen reminder to the user) to make the rest of the input options available.
I have a simple state type setting, where mState is the current mode (STATE_TIMER_NOT_STARTED before the user presses any buttons, ... RUNNING after the first press, and then ... PAUSED after the second, back ... RUNNING after the third, etc. etc., etc.).
This all works great. EXCEPT that when the timer is started and the user presses the start / stop / resume button again, ScrollView will scroll down the path. I DO NOT issue this command (I don’t even have a reference to the ScrollView object), and I'm not sure why it does this.
REPRO: Compile + follow the examples below. When the application starts, click the "Start Timing" button. Use your thumb (or mouse) to touch the screen up (so you can see the RatingBar), and then drag it down (so that the button is fully on the screen again). Press the button (which now reads "PauseTiming") again and it will jump a little. He should NOT jump / scroll down, as there is no instruction (which I see) that tells her to scroll down. As far as I can tell, this is setText, which causes scrolling (when I comment on these lines, scrolling does not happen).
WHAT I ASK: If I do something dumb, and you can indicate what it is, I would really appreciate it :) :) I wonder if the “touch mode” can have something to do with it, since it’s DOES NOT happen (in the emulator) when I use the mouse scroll wheel to move the panel up (i.e. instead of a simulated finger -dragging). I can not find much in touch mode, and nothing special in focus / selection in touch mode in ScrollView
If you can confirm that this error occurs for you too, it will be good too (because poverty loves the .AHEM company, I mean, because it can help confirm that it is not only me :)).
MyTestApp.java
package bug.android.scrollview; import android.app.Activity; import android.os.Bundle; import android.text.format.Time; import android.view.Display; import android.view.View; import android.view.WindowManager; import android.widget.Button; import android.widget.TextView; public class MyTestApp extends Activity { public final static int STATE_TIMER_NOT_STARTED = 1; public final static int STATE_TIMER_RUNNING = 2; public final static int STATE_TIMER_PAUSED = 3; private int mState; Time t = new Time(); private Time data = new Time(); private Button btnStartStopResume; private TextView lblSpacer; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.new_time_entry); btnStartStopResume = (Button) findViewById(R.id.btnStartStopResume);
new_time_entry.xml
<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/windowScroller" android:layout_width="fill_parent" android:layout_height="fill_parent" > <RelativeLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <Button android:id="@+id/btnStartStopResume" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginBottom="5dip" android:text="Start Timing" android:textSize="40dp" android:height="290dp" android:onClick="doStartStopResume" /> <TextView android:id="@+id/lblSpacer" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/btnStartStopResume" android:layout_centerHorizontal="true" android:text="@string/add_scroll_down_for_more" /> <TextView android:id="@+id/lblTimeStartLabel" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_below="@id/lblSpacer" android:layout_alignParentLeft="true" android:clickable="true" android:onClick="adjustStartTime" android:text="Start of this run:" android:textSize="8dp" /> <TextView android:id="@+id/lblTimeStart" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/lblTimeStartLabel" android:layout_alignParentLeft="true" android:clickable="true" android:onClick="adjustStartTime" android:text="--:--:-- --" android:textColor="#FFFFFF" android:textSize="26dp" /> <TextView android:id="@+id/lblElapsedLabel" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/lblSpacer" android:layout_alignRight="@id/lblSpacer" android:layout_marginRight="5dp" android:text="Elapsed Time:" android:textSize="8dp" /> <TextView android:id="@+id/lblTimeElapsed" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/lblElapsedLabel" android:layout_alignRight="@id/lblSpacer" android:layout_marginRight="5dp" android:textColor="#99ff66" android:text="-- m -- sec" android:textSize="26dp" android:layout_marginBottom="10dip"/> <CheckBox android:id="@+id/chkNewRun" android:onClick="doNewRunClick" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_below="@id/lblTimeElapsed" android:text="This is a new run of timings" android:layout_marginBottom="10dip" /> <TextView android:id="@+id/lblIntensity" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Intensity (1 = none 5 = max)" android:layout_below="@id/chkNewRun" /> <RatingBar android:id="@+id/rbIntensity" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/lblIntensity" android:numStars="5" android:rating="2" android:layout_marginBottom="5dip" /> <TextView android:id="@+id/lblNotes" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Notes:" android:layout_below="@id/rbIntensity" /> <EditText android:id="@+id/txtNotes" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@android:drawable/editbox_background" android:layout_below="@id/lblNotes" android:layout_marginBottom="10dip" /> <Button android:id="@+id/btnReset" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/txtNotes" android:layout_alignParentLeft="true" android:layout_marginLeft="10dip" android:layout_marginRight="10dip" android:text="Reset" android:onClick="doReset" /> <Button android:id="@+id/btnOk" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/txtNotes" android:layout_toRightOf="@id/btnReset" android:layout_alignParentRight="true" android:layout_marginLeft="10dip" android:layout_marginRight="10dip" android:text="Add Timing To List" android:onClick="doAddTiming" /> </RelativeLayout> </ScrollView>
strings.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Timer</string> <string name="dlg_edit_timing_title">Edit A Timing</string> <string name="add_scroll_down_for_more">< Scroll down for more options! ></string> <string name="add_scroll_down_to_add">< Scroll down to save this timing! ></string> <string name="start_timing">Start Timing\n\n</string> <string name="stop_timing">Pause Timing\n\n</string> <string name="resume_timing">Resume Timing\n\n</string> </resources>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="bug.android.scrollview" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".MyTestApp" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-sdk android:minSdkVersion="5" /> </manifest>
UPDATE 1: Addendum
if( btnStartStopResume.isInTouchMode() ) Toast.makeText(this, "TOUCH MODE", 2000); else Toast.makeText(this, "NOT touch mode", 2000);
then setting breakpoints in the debugger confirms that the button is always in touch mode (regardless of whether I drag the panel up / down or the mouse wheel up / down). Thus, this is a combination of the fact that you are in touch-touch mode and drag the panel after pressing the second button (i.e., when the application is in the stop / pause time mode), which causes odd additional timers in subsequent pauses.
UPDATE 2: I just noticed that it scrolls to EditText, and no further. It looks like when you move the panel down, the EditText gets the selection, and after the click event, the ScrollView returns to what it has the choice. It seems to explain why the mouse-wheel approach does not have this problem (it moves the selection / focus back to the button).