Android - Expandable TextView with Animation
You can check my blog post on ExpandableTexTView:
The idea is, initially the TextView will show a small portion of a long text and when it is clicked, it will show the rest of the text.
So here is the code that how I solved it.
package com.rokonoid.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.text.SpannableStringBuilder;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;
/**
* User: Bazlur Rahman Rokon
* Date: 9/7/13 - 3:33 AM
*/
public class ExpandableTextView extends TextView {
private static final int DEFAULT_TRIM_LENGTH = 200;
private static final String ELLIPSIS = ".....";
private CharSequence originalText;
private CharSequence trimmedText;
private BufferType bufferType;
private boolean trim = true;
private int trimLength;
public ExpandableTextView(Context context) {
this(context, null);
}
public ExpandableTextView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ExpandableTextView);
this.trimLength = typedArray.getInt(R.styleable.ExpandableTextView_trimLength, DEFAULT_TRIM_LENGTH);
typedArray.recycle();
setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
trim = !trim;
setText();
requestFocusFromTouch();
}
});
}
private void setText() {
super.setText(getDisplayableText(), bufferType);
}
private CharSequence getDisplayableText() {
return trim ? trimmedText : originalText;
}
@Override
public void setText(CharSequence text, BufferType type) {
originalText = text;
trimmedText = getTrimmedText(text);
bufferType = type;
setText();
}
private CharSequence getTrimmedText(CharSequence text) {
if (originalText != null && originalText.length() > trimLength) {
return new SpannableStringBuilder(originalText, 0, trimLength + 1).append(ELLIPSIS);
} else {
return originalText;
}
}
public CharSequence getOriginalText() {
return originalText;
}
public void setTrimLength(int trimLength) {
this.trimLength = trimLength;
trimmedText = getTrimmedText(originalText);
setText();
}
public int getTrimLength() {
return trimLength;
}
}
And add the following line in your attr.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ExpandableTextView">
<attr name="trimLength" format="integer"/>
</declare-styleable>
</resources>
Put the following in your 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">
<com.rokonoid.widget.ExpandableTextView
android:id="@+id/lorem_ipsum"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
And test your activity
package com.rokonoid.widget;
import android.app.Activity;
import android.os.Bundle;
public class MyActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String yourText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " +
"Ut volutpat interdum interdum. Nulla laoreet lacus diam, vitae " +
"sodales sapien commodo faucibus. Vestibulum et feugiat enim. Donec " +
"semper mi et euismod tempor. Sed sodales eleifend mi id varius. Nam " +
"et ornare enim, sit amet gravida sapien. Quisque gravida et enim vel " +
"volutpat. Vivamus egestas ut felis a blandit. Vivamus fringilla " +
"dignissim mollis. Maecenas imperdiet interdum hendrerit. Aliquam" +
" dictum hendrerit ultrices. Ut vitae vestibulum dolor. Donec auctor ante" +
" eget libero molestie porta. Nam tempor fringilla ultricies. Nam sem " +
"lectus, feugiat eget ullamcorper vitae, ornare et sem. Fusce dapibus ipsum" +
" sed laoreet suscipit. ";
ExpandableTextView expandableTextView = (ExpandableTextView) findViewById(R.id.lorem_ipsum);
expandableTextView.setText(yourText);
}
}
Reference: Android – Expandable TextView
Android Expandable text view with View More Button displaying at center after 3 lines
This is how i have achieved the desired output,
MytextView which i want to expand is: tvDescription
I have a see more button with name: btnSeeMore
To check if the textview has more than 4 lines i had a listener for it as follows,
tvDescription.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if(expandable) {
expandable = false;
if (tvDescription.getLineCount() > 4) {
btnSeeMore.setVisibility(View.VISIBLE);
ObjectAnimator animation = ObjectAnimator.ofInt(tvDescription, "maxLines", 4);
animation.setDuration(0).start();
}
}
}
});
I have kept a boolean value to check if textview is already expanded so that there will not be any hickups while collapsing it.
if textview has more than four lines, boolean flag will be true and the button will be visible so this is the code for expanding and collapsing animation.
btnSeeMore.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (!expand) {
expand = true;
ObjectAnimator animation = ObjectAnimator.ofInt(tvDescription, "maxLines", 40);
animation.setDuration(100).start();
btnSeeMore.setImageDrawable(ContextCompat.getDrawable(getActivity(), R.drawable.ic_collapse));
} else {
expand = false;
ObjectAnimator animation = ObjectAnimator.ofInt(tvDescription, "maxLines", 4);
animation.setDuration(100).start();
btnSeeMore.setImageDrawable(ContextCompat.getDrawable(getActivity(),R.drawable.ic_expand));
}
}
});
Comment below for further information
Custom Expandable TextView
Finally I did it my self, here is the repo
https://github.com/CorradiSebastian/ExpandableTextView
Android: Expand/collapse animation
I see that this question became popular so I post my actual solution. The main advantage is that you don't have to know the expanded height to apply the animation and once the view is expanded, it adapts height if content changes. It works great for me.
public static void expand(final View v) {
int matchParentMeasureSpec = View.MeasureSpec.makeMeasureSpec(((View) v.getParent()).getWidth(), View.MeasureSpec.EXACTLY);
int wrapContentMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
v.measure(matchParentMeasureSpec, wrapContentMeasureSpec);
final int targetHeight = v.getMeasuredHeight();
// Older versions of android (pre API 21) cancel animations for views with a height of 0.
v.getLayoutParams().height = 1;
v.setVisibility(View.VISIBLE);
Animation a = new Animation()
{
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
v.getLayoutParams().height = interpolatedTime == 1
? LayoutParams.WRAP_CONTENT
: (int)(targetHeight * interpolatedTime);
v.requestLayout();
}
@Override
public boolean willChangeBounds() {
return true;
}
};
// Expansion speed of 1dp/ms
a.setDuration((int)(targetHeight / v.getContext().getResources().getDisplayMetrics().density));
v.startAnimation(a);
}
public static void collapse(final View v) {
final int initialHeight = v.getMeasuredHeight();
Animation a = new Animation()
{
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
if(interpolatedTime == 1){
v.setVisibility(View.GONE);
}else{
v.getLayoutParams().height = initialHeight - (int)(initialHeight * interpolatedTime);
v.requestLayout();
}
}
@Override
public boolean willChangeBounds() {
return true;
}
};
// Collapse speed of 1dp/ms
a.setDuration((int)(initialHeight / v.getContext().getResources().getDisplayMetrics().density));
v.startAnimation(a);
}
As mentioned by @Jefferson in the comments, you can obtain a smoother animation by changing the duration (and hence the speed) of the animation. Currently, it has been set at a speed of 1dp/ms
Android - create sliding up animation for textview similar to movie credits
i figured it out ...here is the slide in :
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/linear_interpolator" >
<translate
android:duration="1000"
android:fromYDelta="100%p"
android:toYDelta="0%" />
</set>
and the slide out:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/linear_interpolator" android:fillAfter="true" >
<translate
android:duration="1000"
android:fromYDelta="0%"
android:toYDelta="-100%p" />
</set>
this page was very useful for me so i could know what the p stood for in the fromYDelta
here is the final results:
Expandable for text view in kotlin
If you need something like intext suffix "Read More" button. Then, you need to make custom view but if you can compromise on that, then use any of the libraries.
- https://github.com/Chen-Sir/ExpandableTextView
- https://github.com/Blogcat/Android-ExpandableTextView
If you got the answer you want please accept my answer by giving green check. If I haven't got your question then give me more details in comment section of this answer. Love from India.❤️
TextView animation expand only one line
SOLVED
I changed my expand
method adding a listener in which i set the height to wrap_content at the end of the animation:
private void expand(final View v) {
v.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
v.getLayoutParams().height = 0;
v.setVisibility(View.VISIBLE);
final int targetHeight = v.getMeasuredHeight();
ValueAnimator mAnimator = slideAnimator(0, targetHeight);
mAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
v.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
v.requestLayout();
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
mAnimator.start();
}
how to proper animate (expand and collapse) a textview with multiple lines
I found the answer here (Hermann Klecker post)
Android: get height of a view before it´s drawn
private void expandView( final View view ) {
view.setVisibility(View.VISIBLE);
LayoutParams parms = (LayoutParams) view.getLayoutParams();
final int width = this.getWidth() - parms.leftMargin - parms.rightMargin;
view.measure( MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
final int targetHeight = view.getMeasuredHeight();
view.getLayoutParams().height = 0;
Animation anim = new Animation() {
@Override
protected void applyTransformation( float interpolatedTime, Transformation trans ) {
view.getLayoutParams().height = (int) (targetHeight * interpolatedTime);
view.requestLayout();
}
@Override
public boolean willChangeBounds() {
return true;
}
};
anim.setDuration( ANIMATION_DURATION );
view.startAnimation( anim );
}
Related Topics
Background-Attachment: Fixed Interfering with Background-Size
Send File to Server via Retrofit2 as Object
How to Pin a Certificate with Square Okhttp
HTML5 <Video> Element on Android Does Not Play
Adding a Progress Dialog in a Webview
How to Get Code Coverage Using Android Studio
Flutter: How to Fix "A Renderflex Overflowed by Pixels " Error
When Does Adt Set Buildconfig.Debug to False
Textview with Background Color and Line Spacing
Fragment View in Viewpager Is Not Restored When Resuming
Android Imageview Change Tint to Simulate Button Click
Value <Br of Type Java.Lang.String Cannot Be Converted to JSONobject on Android
Making Sense of Android Meta-Viewport Scaling: What Am I Missing
Using Picasso Library with Listview
How to Change The Navigationview's Item Text Size
Android Back Button on a Progressive Web Application Closes De App
A Correct Way to Convert Byte[] in Java to Unsigned Char* in C++, and Vice Versa