Java tutorial
//package com.java2s; import android.annotation.SuppressLint; import android.graphics.drawable.Drawable; import android.os.Build; import android.text.Editable; import android.text.TextUtils.TruncateAt; import android.text.TextWatcher; import android.view.View; import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.widget.TextView; public class Main { /** * Make a textview to a collapsible textview with the indicator on the right of the textview * * @param tv , {@link TextView} to be converted * @param upDrawableResId , drawable resource id to be used as up indicator * @param downDrawableResId , drawable resource id to be used as down indicator * @param lineTreshold , no of line to be displayed for the collapsed state */ public static void makeCollapsible(final TextView tv, int upDrawableResId, int downDrawableResId, final int lineTreshold) { final Drawable[] drawables = tv.getCompoundDrawables(); final Drawable up = tv.getContext().getResources().getDrawable(upDrawableResId); final Drawable down = tv.getContext().getResources().getDrawable(downDrawableResId); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) { tv.setCompoundDrawablesWithIntrinsicBounds(drawables[0], drawables[1], down, drawables[3]); tv.setEllipsize(TruncateAt.END); tv.setMaxLines(lineTreshold); tv.setTag(true); tv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (v instanceof TextView) { TextView tv = (TextView) v; boolean snippet = (Boolean) tv.getTag(); if (snippet) { // show everything snippet = false; tv.setMaxLines(Integer.MAX_VALUE); tv.setEllipsize(null); tv.setCompoundDrawablesWithIntrinsicBounds(drawables[0], drawables[1], up, drawables[3]); } else { // show snippet snippet = true; tv.setMaxLines(lineTreshold); tv.setEllipsize(TruncateAt.END); tv.setCompoundDrawablesWithIntrinsicBounds(drawables[0], drawables[1], down, drawables[3]); } tv.setTag(snippet); } } }); } else { tv.addTextChangedListener(new TextWatcher() { @Override public void afterTextChanged(Editable arg0) { ViewTreeObserver vto = tv.getViewTreeObserver(); vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @SuppressWarnings("deprecation") @SuppressLint("NewApi") @Override public void onGlobalLayout() { tv.setEllipsize(TruncateAt.END); int line = tv.getLineCount(); tv.setMaxLines(lineTreshold); if (line <= lineTreshold) { tv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { // empty listener // Log.d("line count", "count: "+ // tv.getLineCount()); } }); if (tv.getLayout() != null) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { tv.getViewTreeObserver().removeGlobalOnLayoutListener(this); } else { tv.getViewTreeObserver().removeOnGlobalLayoutListener(this); } } return; } tv.setCompoundDrawablesWithIntrinsicBounds(drawables[0], drawables[1], down, drawables[3]); tv.setTag(true); tv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (v instanceof TextView) { TextView tv = (TextView) v; boolean snippet = (Boolean) tv.getTag(); if (snippet) { snippet = false; // show everything tv.setMaxLines(Integer.MAX_VALUE); tv.setEllipsize(null); tv.setCompoundDrawablesWithIntrinsicBounds(drawables[0], drawables[1], up, drawables[3]); } else { snippet = true; // show snippet tv.setMaxLines(lineTreshold); tv.setEllipsize(TruncateAt.END); tv.setCompoundDrawablesWithIntrinsicBounds(drawables[0], drawables[1], down, drawables[3]); } tv.setTag(snippet); } } }); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { tv.getViewTreeObserver().removeGlobalOnLayoutListener(this); } else { tv.getViewTreeObserver().removeOnGlobalLayoutListener(this); } } }); } @Override public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { } @Override public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { } }); } } }