I am displaying text in a TextView that appears to be too long to fit into one screen. I need to make my TextView scrollable. How can I do that?
Here is the code:
final TextView tv = new TextView(this);
tv.setBackgroundResource(R.drawable.splash);
tv.setTypeface(face);
tv.setTextSize(18);
tv.setTextColor(R.color.BROWN);
tv.setGravity(Gravity.CENTER_VERTICAL| Gravity.CENTER_HORIZONTAL);
tv.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent e) {
Random r = new Random();
int i = r.nextInt(101);
if (e.getAction() == e.ACTION_DOWN) {
tv.setText(tips[i]);
tv.setBackgroundResource(R.drawable.inner);
}
return true;
}
});
setContentView(tv);
You don't need to use a ScrollView
actually.
Just set the
android:scrollbars = "vertical"
properties of your TextView
in your layout's xml file.
Then use:
yourTextView.setMovementMethod(new ScrollingMovementMethod());
in your code.
Bingo, it scrolls!
This is how I did it purely in XML:
<?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/SCROLLER_ID"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
android:fillViewport="true">
<TextView
android:id="@+id/TEXT_STATUS_ID"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1.0"/>
</ScrollView>
</LinearLayout>
NOTES:
android:fillViewport="true" combined with android:layout_weight="1.0" will make the textview take up all available space. When defining the Scrollview, DO NOT specify android:layout_height="fill_parent" otherwise the scrollview doesn't work! (this has caused me to waste an hour just now! FFS).
PRO TIP:
To programmatically scroll to the bottom after appending text, use this:
mTextStatus = (TextView) findViewById(R.id.TEXT_STATUS_ID);
mScrollView = (ScrollView) findViewById(R.id.SCROLLER_ID);
private void scrollToBottom()
{
mScrollView.post(new Runnable()
{
public void run()
{
mScrollView.smoothScrollTo(0, mTextStatus.getBottom());
}
});
}
mTextView.getBottom()
, just use the method mScrollView.fullScroll(View.FOCUS_DOWN)
as it is a part of the ScrollView API. See here and here for more info.
LinearLayout
or the ScrollView
may be useless in this example (I removed the LinearLayout
completely). It also warns that for the TextView
, it should be android:layout_height="wrap_content"
to match the ScrollView
. These warnings may be due to the 3 years that have passed since this answer was posted. Regardless, this answer supports smooth scrolling and flicking...+1
<!--suppress AndroidLintUselessParent -->
above the ScrollView
in the xml file will take care of those warnings.
All that is really necessary is the setMovementMethod(). Here's an example using a LinearLayout.
File main.xml
<?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"
>
<TextView
android:id="@+id/tv1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="@string/hello"
/>
</LinearLayout>
File WordExtractTest.java
public class WordExtractTest extends Activity {
TextView tv1;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tv1 = (TextView)findViewById(R.id.tv1);
loadDoc();
}
private void loadDoc() {
String s = "";
for(int x=0; x<=100; x++) {
s += "Line: " + String.valueOf(x) + "\n";
}
tv1.setMovementMethod(new ScrollingMovementMethod());
tv1.setText(s);
}
}
ScrollView
method.
StringBuilder
instead of a String
... what you have is a little wasteful.
Make your textview just adding this
TextView textview= (TextView) findViewById(R.id.your_textview_id);
textview.setMovementMethod(new ScrollingMovementMethod());
It is not necessary to put in
android:Maxlines="AN_INTEGER"`
You can do your work by simply adding:
android:scrollbars = "vertical"
And, put this code in your Java class:
textview.setMovementMethod(new ScrollingMovementMethod());
You can either
surround the TextView by a ScrollView; or set the Movement method to ScrollingMovementMethod.getInstance();.
The best way I found:
Replace the TextView with an EditText with these extra attributes:
android:background="@null"
android:editable="false"
android:cursorVisible="false"
There is no need for wrapping in a ScrollView.
ScrollView
is the correct way to go.
Simple. This is how I did it:
XML Side:
Bonus:
To let the text view scroll down as the text fill it, you have to add:
android:gravity="bottom"
to the TextView xml file. It will scroll down automatically as more text comes in.
Of course you need to add the text using the append function instead of set text:
tv_log.append("\n" + text);
I used it for Log purpose.
I hope this helps ;)
This is "How to apply ScrollBar to your TextView", using only XML.
First, you need to take a Textview control in the main.xml file and write some text into it ... like this:
<TextView
android:id="@+id/TEXT"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/long_text"/>
Next, place the text view control in between the scrollview to display the scroll bar for this text:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_height="wrap_content"
android:layout_width="fill_parent">
<ScrollView
android:id="@+id/ScrollView01"
android:layout_height="150px"
android:layout_width="fill_parent">
<TextView
android:id="@+id/TEXT"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/long_text"/>
</ScrollView>
</RelativeLayout>
That's it...
In kotlin for making the textview scrollable
myTextView.movementMethod= ScrollingMovementMethod()
and also add in xml this property
android:scrollbars = "vertical"
This will provide smooth scrolling text with a scroll bar.
ScrollView scroller = new ScrollView(this);
TextView tv = new TextView(this);
tv.setText(R.string.my_text);
scroller.addView(tv);
The "pro tip" above from Someone Somewhere (Making TextView scrollable on Android) works great, however, what if you're dynamically adding text to the ScrollView and would like to automatically scroll to the bottom after an append only when the user is at the bottom of the ScrollView? (Perhaps because if the user has scrolled up to read something you don't want to automatically reset to the bottom during an append, which would be annoying.)
Anyway, here it is:
if ((mTextStatus.getMeasuredHeight() - mScrollView.getScrollY()) <=
(mScrollView.getHeight() + mTextStatus.getLineHeight())) {
scrollToBottom();
}
The mTextStatus.getLineHeight() will make it so that you don't scrollToBottom() if the user is within one line from the end of the ScrollView.
If you want text to be scrolled within the textview, then you can follow the following:
First you should have to subclass textview.
And then use that.
Following is an example of a subclassed textview.
public class AutoScrollableTextView extends TextView {
public AutoScrollableTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setEllipsize(TruncateAt.MARQUEE);
setMarqueeRepeatLimit(-1);
setSingleLine();
setHorizontallyScrolling(true);
}
public AutoScrollableTextView(Context context, AttributeSet attrs) {
super(context, attrs);
setEllipsize(TruncateAt.MARQUEE);
setMarqueeRepeatLimit(-1);
setSingleLine();
setHorizontallyScrolling(true);
}
public AutoScrollableTextView(Context context) {
super(context);
setEllipsize(TruncateAt.MARQUEE);
setMarqueeRepeatLimit(-1);
setSingleLine();
setHorizontallyScrolling(true);
}
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
if(focused)
super.onFocusChanged(focused, direction, previouslyFocusedRect);
}
@Override
public void onWindowFocusChanged(boolean focused) {
if(focused)
super.onWindowFocusChanged(focused);
}
@Override
public boolean isFocused() {
return true;
}
}
Now, you have to use that in the XML in this way:
<com.yourpackagename.AutoScrollableTextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="This is very very long text to be scrolled"
/>
That's it.
Add the following in the textview in XML.
android:scrollbars="vertical"
And finally, add
textView.setMovementMethod(new ScrollingMovementMethod());
in the Java file.
If you use Kotlin , in this way : XML
<TextView
android:id="@+id/tvMore"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="3"
android:scrollbars="vertical" />
Activity
tvMore.movementMethod = ScrollingMovementMethod()
I didn't find TextView scrolling to support the 'fling' gesture, where it continues scrolling after a flick up or down. I ended up implementing that myself because I didn't want to use a ScrollView for various reasons, and there didn't seem to be a MovementMethod that both allowed me to select text and click on links.
When you are done with scrollable, add this line to the view's last line when you enter anything in the view:
((ScrollView) findViewById(R.id.TableScroller)).fullScroll(View.FOCUS_DOWN);
If you don't want to use the EditText solution then you might have better luck with:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.yourLayout);
(TextView)findViewById(R.id.yourTextViewId).setMovementMethod(ArrowKeyMovementMethod.getInstance());
}
Add this to your XML layout:
android:ellipsize="marquee"
android:focusable="false"
android:marqueeRepeatLimit="marquee_forever"
android:scrollHorizontally="true"
android:singleLine="true"
android:text="To Make An textView Scrollable Inside The TextView Using Marquee"
And in code you have to write the following lines:
textview.setSelected(true);
textView.setMovementMethod(new ScrollingMovementMethod());
yourtextView.setMovementMethod(new ScrollingMovementMethod());
you can scroll it now.
I know this is an older post, but this is how I am handling the issue on the Java side.
// Allow textView to scroll
tv.setSingleLine(true);
tv.setHorizontallyScrolling(true);
tv.setEllipsize(TextUtils.TruncateAt.MARQUEE);
tv.setMarqueeRepeatLimit(-1); // Infinite
// TextView must be 'selected'
tv.setSelected(true);
// Padding not necessary, but this helps so the text isn't right
// up against the side of a screen/layout
tv.setPadding(10, 0, 10, 0);
The code below creates an automatic horizontal scrolling textview:
While adding TextView to xml use
<TextView android:maxLines="1"
android:ellipsize="marquee"
android:scrollHorizontally="true"/>
Set the following properties of TextView in onCreate()
tv.setSelected(true);
tv.setHorizontallyScrolling(true);
I had this problem when I was using TextView
inside the ScrollView
. This solution has worked for me.
scrollView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
description.getParent().requestDisallowInterceptTouchEvent(false);
return false;
}
});
description.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
description.getParent().requestDisallowInterceptTouchEvent(true);
return false;
}
});
Use it like this
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:maxLines = "AN_INTEGER"
android:scrollbars = "vertical"
/>
Put maxLines
and scrollbars
inside TextView in xml.
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scrollbars="vertical"
android:maxLines="5" // any number of max line here.
/>
Then in java code.
textView.setMovementMethod(new ScrollingMovementMethod());
whenever you need to use the ScrollView as parent, And you also use the scroll movement method with TextView.
And When you portrait to landscape your device that time occur some issue. (like) entire page is scrollable but scroll movement method can't work.
if you still need to use ScrollView as parent or scroll movement method then you also use below desc.
If you do not have any problems then you use EditText instead of TextView
see below :
<EditText
android:id="@+id/description_text_question"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:editable="false"
android:cursorVisible="false"
android:maxLines="6"/>
Here, the EditText behaves like TextView
And your issue will be resolved
In my case.Constraint Layout.AS 2.3.
Code implementation:
YOUR_TEXTVIEW.setMovementMethod(new ScrollingMovementMethod());
XML:
android:scrollbars="vertical"
android:scrollIndicators="right|end"
I struggled with this for over a week and finally figured out how to make this work!
My issue was that everything would scroll as a 'block'. The text itself was scrolling, but as a chunk rather than line by line. This obviously didn't work for me, because it would cut off lines at the bottom. All of the previous solutions did not work for me, so I crafted my own.
Here is the easiest solution by far:
Make a class file called: 'PerfectScrollableTextView' inside a package, then copy and paste this code in:
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.TextView;
public class PerfectScrollableTextView extends TextView {
public PerfectScrollableTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setVerticalScrollBarEnabled(true);
setHorizontallyScrolling(false);
}
public PerfectScrollableTextView(Context context, AttributeSet attrs) {
super(context, attrs);
setVerticalScrollBarEnabled(true);
setHorizontallyScrolling(false);
}
public PerfectScrollableTextView(Context context) {
super(context);
setVerticalScrollBarEnabled(true);
setHorizontallyScrolling(false);
}
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
if(focused)
super.onFocusChanged(focused, direction, previouslyFocusedRect);
}
@Override
public void onWindowFocusChanged(boolean focused) {
if(focused)
super.onWindowFocusChanged(focused);
}
@Override
public boolean isFocused() {
return true;
}
}
Finally change your 'TextView' in XML:
From: <TextView
To: <com.your_app_goes_here.PerfectScrollableTextView
XML - You can use android:scrollHorizontally
Attribute
Whether the text is allowed to be wider than the view (and therefore can be scrolled horizontally).
May be a boolean value, such as "true" or "false".
Prigramacaly - setHorizontallyScrolling(boolean)
Try this:
android:scrollbars = "vertical"
Success story sharing
maxLines
requires you to enter an arbitrary number; this isn't something that will work for every screen size and font size? I find it simpler to just wrap it with aScrollView
, meaning I don't have to add any further XML attributes or code (like setting the movement method).ScrollView
take up as much space as it needs (e.g. via theandroid:fillViewport
attribute), or you set the specific size you want. UsingmaxLines
should not be used to set sizes of UI elements, so that is no solution.