Scrolling EditText on ScrollView programmatically
I am trying to make a non-editable EditText that is placed in a ScrollView and scrolling is controlled programmatically (when a left/right fling is detected).
Ok, here's my simple layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<ScrollView
android:id="@+id/sv"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<EditText android:id="@+id/maintext"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:longClickable="false"
android:selectAllOnFocus="false"
android:focusable="false"
android:editable="false"/>
</ScrollView>
</LinearLayout>
And here is my simple program:
package com.test.testscroll;
import android.app.Activity;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.widget.EditText;
import android.widget.ScrollView;
import android.widget.Toast;
public class TestScroll extends Activity {
private EditText mMainText;
private ScrollView mScrollView;
private GestureDetector gestureDetector;
View.OnTouchListener gestureListener;
private GestureDetector scrollGestureDetector;
View.OnTouchListener scrollGestureListener;
private static final int SWIPE_MIN_DISTANCE = 120;
private static final int SWIPE_MAX_OFF_PATH = 250;
private static final int SWIPE_THRESHOLD_VELOCITY = 200;
private final String testString = "This is a very long line for testing purpose. Line number 1" +
"This is a very long line for testing purpose. Line number 2" +
"This is a very long line for testing purpose. Line number 3" +
"This is a very long line for testing purpose. Line number 4" +
"This is a very long line for testing purpose. Line number 5" +
"This is a very long line for testing purpose. Line number 6" +
"This is a very long line for testing purpose. Line number 7" +
"This is a very long line for testing purpose. Line number 8" +
"This is a very long line for testing purpose. Line number 9" +
"This is a very long line for testing purpose. Line number 10" +
"This is a very long line for testing purpose. Line number 11" +
"This is a very long line for testing purpose. Line number 12" +
"This is a very long line for testing purpose. Line number 13" +
"This is a very long line for testing purpose. Line number 14" +
"This is a very long line for testing purpose. Line number 15" +
"This is a very long line for testing purpose. Line number 16" +
"This is a very long line for testing purpose. Line number 17" +
"This is a very long line for testing purpose. Line number 18" +
"This is a very long line for testing purpose. Line number 19" +
"This is a very long line for testing purpose. Line number 20" +
"This is a very long line for testing purpose. Line number 21" +
"This is a very long line for testing purpose. Line number 22" +
"This is a very long line for testing purpose. Line number 23" +
"This is a very long line for testing purpose. Line number 24" +
"This is a very long line for testing purpose. Line number 25" +
"This is a very long line for testing purpose. Line number 26" +
"This is a very long line for testing purpose. Line number 27" +
"This is a very long line for testing purpose. Line number 28" +
"This is a very long line for testing purpose. Line number 29" +
"This is a very long line for testing purpose. Line number 30" +
"This is a very long line for testing purpose. Line number 31" +
"This is a very long line for testing purpose. Line number 32" +
"This is a very long line for testing purpose. Line number 33" +
"This is a very long line for testing purpose. Line number 34" +
"This is a very long line for testing purpose. Line number 35" +
"This is a very long line for testing purpose. Line number 36" +
"This is a very long line for testing purpose. Line number 37" +
"This is a very long line for testing purpose. Line number 38" +
"This is a very long line for testing purpose. Line number 39" +
"This is a very long line for testing purpose. Line number 40" +
"This is a very long line for testing purpose. Line number 41" +
"This is a very long line for testing purpose. Line number 42" +
"This is a very long line for testing purpose. Line number 43" +
"This is a very long line for testing purpose. Line number 44" +
"This is a very long line for testing purpose. Line number 45" +
"This is a very long line for testing purpose. Line number 46" +
"This is a very long line for testing purpose. Line number 47" +
"This is a very long line for testing purpose. Line number 48" +
"This is a very long line for testing purpose. Line number 49" +
"This is a very long line for testing purpose. Line number 50";
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mMainText = (EditText) findViewById(R.id.maintext);
mScrollView = (ScrollView) findViewById(R.id.sv);
mMainText.setText(testString);
// Gesture detection
gestureDetector = new GestureDetector(new MyGestureDetector());
开发者_运维问答gestureListener = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (gestureDetector.onTouchEvent(event)) {
return true;
}
return false;
}
};
mMainText.setOnTouchListener(gestureListener);
scrollGestureDetector = new GestureDetector(new ScrollGestureDetector());
scrollGestureListener = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (scrollGestureDetector.onTouchEvent(event)) {
return true;
}
return false;
}
};
mScrollView.setOnTouchListener(scrollGestureListener);
}
class MyGestureDetector extends SimpleOnGestureListener {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
try {
if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
return false;
// right to left swipe
if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
Toast.makeText(TestScroll.this, "Left Swipe", Toast.LENGTH_SHORT).show();
mScrollView.pageScroll(ScrollView.FOCUS_UP);
return true;
} else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
Toast.makeText(TestScroll.this, "Right Swipe", Toast.LENGTH_SHORT).show();
mScrollView.pageScroll(ScrollView.FOCUS_DOWN);
return true;
}
} catch (Exception e) {
// nothing
}
return false;
}
}
class ScrollGestureDetector extends SimpleOnGestureListener {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return true;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
{
return true;
}
@Override
public void onLongPress(MotionEvent e)
{
// Do nothing
}
}
}
So, to explain it simply, I have two custom simplegesture classes that I attached to the EditText and the ScrollView. For the EditText, I'm trying to detect a left/right fling and when detected, I'm scrolling the it up 1 page up/down. The custom simplegesture attached to the ScrollView is to disable finger scrolling.
Here's a screen shot after a right fling was done: http://img830.imageshack.us/i/textcut.png/
I kinda works right now but I have two questions:
- How do I control the scroll so that lines won't get "cut-off" (please refer to the picture above where the first line on the screen is a bit "cuf-off").
- Why when I scroll the page up/down programmatically, the EditText is auto select-all (please refer to the picture above where the whole screen turns orange after scrolling)?
- Why when I changed MyGestureDetector to detect fling on the Y-axis (vertical fling) and programmatically scroll the EditText, it doesnt' work? It wouldn't work even if I made the change in ScrollGestureDetector too. Does it have something to do with the behaviour of the ScrollView?
Thank you!
"3. programmatically scroll the EditText, it doesnt' work"
Post a Runnable with scrolling code to ScrollView instead of calling scrolling methods directly.
post (Runnable action)
Causes the Runnable to be added to the message queue. The runnable will be run on the user interface thread.
from: ScrollView and programmatically scrolling
Lance Nanek
There are past threads on this you can dig up. Basically you have to give the ScrollView a chance to realize it has had stuff added to it. For example:
scroll.post(new Runnable() {
public void run() {
scroll.fullScroll(ScrollView.FOCUS_DOWN); } });
Add below lines to xml edittext control,
android:scrollbars="vertical" android:fadeScrollbars="false"
and then add this liens to coding
"EditText Control Object".setMovementMethod(new ScrollingMovementMethod());
Its late but may help some one with this issue.. It takes around 200 miniseconds to add the last element and update it for a scrollView so this will surely work.
void scrollDown()
{
Thread scrollThread = new Thread(){
public void run(){
try {
sleep(200);
ChatActivity.this.runOnUiThread(new Runnable() {
public void run() {
myScrollView.fullScroll(View.FOCUS_DOWN);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
};
scrollThread.start();
}
Just call scrollDown();
after adding element to scrollView.
精彩评论