ExpandableTextView——一个可折叠的Textview

来源:互联网 发布:航天证券交易软件 编辑:程序博客网 时间:2024/05/01 06:58

一、简单介绍

本文是在GitHub上找的一个库

ExpandableTextView is an Android library that allows developers to easily create an TextView which can expand/collapse just like the Google Play's app description. Feel free to use it all you want in your Android apps provided that you cite this project.

ExpandableTextView 是一个提供给android开发者的安卓库,它能让你很容易实现textview的拓展折叠像Google Play’s app那样。在你的app项目中用它你会感觉到自由定制你想要的一切。

这里写图片描述

二、具体使用

Requirements(要求)

 API Level 8 (Froyo) and above.

导包

The library is pushed to Maven Central as an AAR, so you just need to add the followings to your build.gradle file:

dependencies {    compile 'com.ms-square:expandableTextView:0.1.4'}

Usage

Using the library is really simple, just look at the source code of the provided sample. (Look at the SampleTextListAdapter.java for the use within a ListView)The important thing to note is that the view Ids for TextView and ImageButton must be set to "@id/expandable_text" and "@id/expand_collapse" respectively for this library to work.Also, you can optionally set the following attributes in your layout xml file to customize the behavior of the ExpandableTextView.maxCollapsedLines (defaults to 8) The maximum number of text lines allowed to be shown when the TextView gets collapsedanimDuration (defaults to 300ms) Duration of the Animation for the expansion/collapseanimAlphaStart (defaults to 0.7f) Alpha value of the TextView when the animation starts (NOTE) Set this value to 1 if you want to disable the alpha animation.expandDrawable Customize a drawable set to ImageButton to expand the TextViewcollapseDrawable Customize a drawable set to ImageButton to collapse the TextView

使用本库很简单,看例子就行。
重要的是:

1、TextView 和ImageButton 的id必须按照库要求的设置,分别设置为”@id/expandable_text” 和”@id/expand_collapse” ,只有这样才能生效。

2、当然,你也可以设置以下属性满足你项目的需要。

maxCollapsedLines 折叠的时候允许显示的最大行,默认为8

animDuration 折叠展开时动画所用的时间,默认300ms

animAlphaStart 动画执行的时候,渐变动画,背景虚化。默认为0.7f,设置为1,则不会有虚化。

expandDrawable 你自定义展开动画。

collapseDrawable 你自定义折叠动画。

三、小例子。

 <!-- sample xml -->  <com.ms.square.android.expandabletextview.ExpandableTextView      xmlns:android="http://schemas.android.com/apk/res/android"      xmlns:expandableTextView="http://schemas.android.com/apk/res-auto"      android:id="@+id/expand_text_view"      android:layout_width="match_parent"      android:layout_height="wrap_content"      expandableTextView:maxCollapsedLines="4"      expandableTextView:animDuration="200">      <TextView          android:id="@id/expandable_text"          android:layout_width="match_parent"          android:layout_height="wrap_content"          android:layout_marginLeft="10dp"          android:layout_marginRight="10dp"          android:textSize="16sp"          android:textColor="#666666" />      <ImageButton          android:id="@id/expand_collapse"          android:layout_width="wrap_content"          android:layout_height="wrap_content"          android:padding="16dp"          android:layout_gravity="right|bottom"          android:background="@android:color/transparent"/>  </com.ms.square.android.expandabletextview.ExpandableTextView>// sample code snippet to set the text content on the ExpandableTextViewExpandableTextView expTv1 = (ExpandableTextView) rootView.findViewById(R.id.sample1)                    .findViewById(R.id.expand_text_view);// IMPORTANT - call setText on the ExpandableTextView to set the text content to displayexpTv1.setText(getString(R.string.dummy_text1));

需要注意的是,设置文本内容时候我们用的是ExpandableTextView 而不是Textview。

看效果**展开前:**

这里写图片描述

展开后

这里写图片描述

。。。。。。。。。。。。。。

后续,老板觉得不好看,就自定义了个。

attrs里面

 <declare-styleable name="ExpandTextView">        <!-- 文本颜色 -->        <attr name="textColor" format="color|reference"/>        <!-- 最大显示文本行数 -->        <attr name="My_maxLines" format="integer|reference"/>        <!-- 文本字体大小 -->        <attr name="textSize" format="dimension|reference"/>        <!-- 动画显示时间-->        <attr name="animDuration" format="integer|reference"/>        <!-- 提示图标的宽度 -->        <attr name="drawableWidth" format="dimension|reference"/>        <!-- 提示图标的高度 -->        <attr name="drawableHeight" format="dimension|reference"/>        <!-- 展开时候的提示图标 -->        <attr name="expandDrawable" format="color|reference"/>        <!-- 收缩收起时候的提示图标 -->        <attr name="shrinkDrawable" format="color|reference"/>    </declare-styleable>

自定义:

package com.toolbar;import android.animation.ObjectAnimator;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.PixelFormat;import android.graphics.drawable.Drawable;import android.text.Layout;import android.text.StaticLayout;import android.text.TextPaint;import android.text.TextUtils;import android.util.AttributeSet;import android.view.View;import java.util.ArrayList;import java.util.List;/** * 缩放展开的动画简单Textview * * Created by igeek on 2016/9/1. * @author igeek2014@hotmail.com */public class ExpandTextView extends View implements View.OnClickListener {    //行文本记录集    private List<LineText> lineTexts = new ArrayList<LineText>();    //最大显示文本行数    private int My_maxLines;    //目标文本行    private int targetLine;    //收缩收起时候的提示图标    private Drawable expandDrawable;    //展开时候的提示图标    private Drawable shrinkDrawable;    //提示图标的宽度    private int drawableWidth;    //提示图标的高度    private int drawableHeight;    //最大显示文本行对应的本视图高度    private int maxLinesHeight;    //展开时候的视图高度    private int expandHeight;    //当前视图的高度    private int viewHeight;    //收缩行结尾提示语文本宽度    private float ellipsizWidth;    //收缩行结尾提示语文本绘制水平起点    private float ellipsizStartX;    //文本字体大小    private int textSize;    //文本颜色    private int textColor;    //当前文本    private String text;    private String ellipsizText = "...";    //收缩行文本    private String shrinkLineText;    //动画显示时间    private int animDuration;    //是否能够显示 ellipsizText 【需要收缩行当前文本的宽度】    private boolean showEllipsizText = false;    private boolean showTipDrawalbe = false;    private boolean needMeasure = true;    private StaticLayout layout;    private TextPaint textPaint;    public ExpandTextView(Context context) {        this(context, null);    }    public ExpandTextView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public ExpandTextView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ExpandTextView);        My_maxLines = ta.getInt(R.styleable.ExpandTextView_My_maxLines, -1);        animDuration = ta.getInt(R.styleable.ExpandTextView_animDuration, 300);        textSize = ta.getDimensionPixelSize(R.styleable.ExpandTextView_textSize, 14);        textColor = ta.getColor(R.styleable.ExpandTextView_textColor, 14);        drawableWidth = ta.getDimensionPixelSize(R.styleable.ExpandTextView_drawableWidth, 14);        drawableHeight = ta.getDimensionPixelSize(R.styleable.ExpandTextView_drawableHeight, 14);        expandDrawable = ta.getDrawable(R.styleable.ExpandTextView_expandDrawable);        shrinkDrawable = ta.getDrawable(R.styleable.ExpandTextView_shrinkDrawable);        ta.recycle();        textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);        textPaint.density = context.getResources().getDisplayMetrics().density;        textPaint.setColor(textColor);        textPaint.setStyle(Paint.Style.FILL_AND_STROKE);        textPaint.setTextSize(textSize);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        int width = MeasureSpec.getSize(widthMeasureSpec);        if (needMeasure && (!TextUtils.isEmpty(text))) {            needMeasure = false;            measureHeightState(text, width);            startDrawAnim(0, viewHeight);        }else{            heightMeasureSpec = MeasureSpec.makeMeasureSpec(viewHeight, MeasureSpec.EXACTLY);            setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);        }    }    public void updateText(String text) {        if (!TextUtils.isEmpty(text)) {            this.text = text;            needMeasure = true;            requestLayout();        }    }    private synchronized void measureHeightState(String text, int width) {        layout = new StaticLayout(text, textPaint, width - getPaddingLeft() - getPaddingRight(), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0f, true);        final int lineCount = layout.getLineCount();        My_maxLines = (My_maxLines == -1 || My_maxLines > lineCount) ? lineCount : My_maxLines;        int text_Height = 0;        List<LineText> tempLines = new ArrayList<LineText>();        for (int index = 0; index < lineCount; index++) {            int start = layout.getLineStart(index);            int end = layout.getLineEnd(index);            LineText lineText = new LineText();            lineText.setStartIndex(start);            lineText.setEndIndex(end - 1);            lineText.setText(text.substring(start, end));            lineText.setTopOffset(layout.getLineTop(index));            lineText.setBottomOffset(layout.getLineBottom(index));            lineText.setBaseLine(layout.getLineBaseline(index)+getPaddingTop());            lineText.setWidth(layout.getLineWidth(index));            lineText.setHeight(lineText.getBottomOffset() - lineText.getTopOffset());            tempLines.add(lineText);            if (index < My_maxLines) {                maxLinesHeight += lineText.getHeight();            }            text_Height += lineText.getHeight();        }        maxLinesHeight+=getPaddingTop()+getPaddingBottom();        expandHeight+=getPaddingTop()+getPaddingBottom();        ellipsizWidth = textPaint.measureText(ellipsizText);        if (My_maxLines < lineCount) {            showTipDrawalbe = expandDrawable != null && shrinkDrawable != null;            float textWidth = tempLines.get(My_maxLines - 1).getWidth();            float contentWidth = width - getPaddingLeft() - getPaddingRight();            float toMarginRight = ellipsizWidth + (showTipDrawalbe ? drawableWidth : 0);            String ellipsizLineText = tempLines.get(My_maxLines - 1).getText();            if (contentWidth - textWidth < toMarginRight) {                showEllipsizText = true;                String subString = null;                for (int index = ellipsizLineText.length() - 1; index > 0; index--) {                    subString = ellipsizLineText.substring(0, index);                    float subStrWidth = textPaint.measureText(subString);                    if (contentWidth - subStrWidth >= toMarginRight) {                        ellipsizStartX = subStrWidth + getPaddingLeft();                        shrinkLineText = subString;                        break;                    }                }            } else {                shrinkLineText = ellipsizLineText;                showEllipsizText = false;            }        } else {            showTipDrawalbe = false;            showEllipsizText = false;        }        expandHeight += text_Height + ((expandDrawable != null && showTipDrawalbe) ? drawableHeight : 0);        viewHeight = My_maxLines == lineCount ? expandHeight : maxLinesHeight;        targetLine = My_maxLines;        lineTexts = tempLines;        if (viewHeight < expandHeight) {            setClickable(true);            setOnClickListener(this);        } else {            setClickable(false);        }    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        if (lineTexts.size() == 0) return;        for (int index = 0; index < targetLine; index++) {            LineText lineText = lineTexts.get(index);            if (index < targetLine - 1) {                canvas.drawText(lineText.getText(), getPaddingLeft(), lineText.getBaseLine(), textPaint);            } else {                if (targetLine == My_maxLines && My_maxLines < lineTexts.size()) {                    //收缩转态                    if (showEllipsizText)                        canvas.drawText(ellipsizText, ellipsizStartX, lineText.getBaseLine(), textPaint);                    canvas.drawText(shrinkLineText, getPaddingLeft(), lineText.getBaseLine(), textPaint);                    if (showTipDrawalbe){                        int left=getWidth() - drawableWidth - getPaddingRight();                        int top=getHeight() - drawableHeight-getPaddingBottom();                        canvas.drawBitmap(drawabletoZoomBitmap(shrinkDrawable, drawableWidth, drawableHeight), left, top, null);                    }                } else if (targetLine == lineTexts.size()) {                    //展开状态                    canvas.drawText(lineText.getText(), getPaddingLeft(), lineText.getBaseLine(), textPaint);                    if (showTipDrawalbe){                        int left=getWidth() - drawableWidth - getPaddingRight();                        int top=getHeight() - drawableHeight-getPaddingBottom();                        canvas.drawBitmap(drawabletoZoomBitmap(expandDrawable, drawableWidth, drawableHeight), left, top, null);                    }                }            }        }    }    @Override    public void onClick(View view) {        if (My_maxLines == lineTexts.size())            return;        if (targetLine == My_maxLines) {            targetLine = lineTexts.size();            startDrawAnim(maxLinesHeight, expandHeight);        } else if (targetLine == lineTexts.size()) {            targetLine = My_maxLines;            startDrawAnim(expandHeight, maxLinesHeight);        }    }    private void startDrawAnim(int startHeight, int endHeight) {        ObjectAnimator animator = ObjectAnimator.ofInt(this, "viewHeight", startHeight, endHeight);        animator.setDuration(animDuration);//        animator.setInterpolator(new AccelerateDecelerateInterpolator());        animator.start();    }    public  int getViewHeight() {        return viewHeight;    }    public  void setViewHeight(int viewHeight) {        this.viewHeight = viewHeight;        requestLayout();    }    public String getText() {        return text;    }    public void setText(String text) {        this.text = text;    }    /**     * drawlable 缩放     *     * @return     */    public static Bitmap drawabletoZoomBitmap(Drawable drawable, int w, int h) {        // 取 drawable 的长宽        int width = drawable.getIntrinsicWidth();        int height = drawable.getIntrinsicHeight();        // drawable转换成bitmap        Bitmap oldbmp = drawabletoBitmap(drawable);        // 创建操作图片用的Matrix对象        Matrix matrix = new Matrix();        // 计算缩放比例        float sx = ((float) w / width);        float sy = ((float) h / height);        // 设置缩放比例        matrix.postScale(sx, sy);        // 建立新的bitmap,其内容是对原bitmap的缩放后的图        Bitmap newbmp = Bitmap.createBitmap(oldbmp, 0, 0, width, height,                matrix, true);        return newbmp;    }    /**     * Drawable转换成Bitmap     */    public static Bitmap drawabletoBitmap(Drawable drawable) {        // 取 drawable 的长宽        int width = drawable.getIntrinsicWidth();        int height = drawable.getIntrinsicHeight();        // 取 drawable 的颜色格式        Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888                : Bitmap.Config.RGB_565;        Bitmap bitmap = Bitmap.createBitmap(width, height, config);        Canvas canvas = new Canvas(bitmap);        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),                drawable.getIntrinsicHeight());        drawable.draw(canvas);        return bitmap;    }}

lineText.java

package com.toolbar;/** * Created by igeek on 2016/9/1. * @author igeek2014@hotmail.com */public class LineText {    private String text;    private int startIndex;    private int endIndex;    private int lineIndex;    private int topOffset;    private int bottomOffset;    private int paddingTop;    private int paddingBottom;    private float width;    private int height;    private int baseLine;    public String getText() {        return text;    }    public void setText(String text) {        this.text = text;    }    public int getStartIndex() {        return startIndex;    }    public void setStartIndex(int startIndex) {        this.startIndex = startIndex;    }    public int getEndIndex() {        return endIndex;    }    public void setEndIndex(int endIndex) {        this.endIndex = endIndex;    }    public int getLineIndex() {        return lineIndex;    }    public void setLineIndex(int lineIndex) {        this.lineIndex = lineIndex;    }    public int getTopOffset() {        return topOffset;    }    public void setTopOffset(int topOffset) {        this.topOffset = topOffset;    }    public int getPaddingTop() {        return paddingTop;    }    public void setPaddingTop(int paddingTop) {        this.paddingTop = paddingTop;    }    public int getPaddingBottom() {        return paddingBottom;    }    public void setPaddingBottom(int paddingBottom) {        this.paddingBottom = paddingBottom;    }    public float getWidth() {        return width;    }    public void setWidth(float width) {        this.width = width;    }    public int getHeight() {        return height;    }    public void setHeight(int height) {        this.height = height;    }    public int getBaseLine() {        return baseLine;    }    public void setBaseLine(int baseLine) {        this.baseLine = baseLine;    }    public int getBottomOffset() {        return bottomOffset;    }    public void setBottomOffset(int bottomOffset) {        this.bottomOffset = bottomOffset;    }}
  <com.toolbar.ExpandTextView                android:id="@+id/collapsing_text"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:layout_marginTop="12dp"                android:paddingLeft="8dp"                android:paddingRight="8dp"                android:paddingBottom="8dp"                android:paddingTop="8dp"                app:drawableHeight="12dp"                app:drawableWidth="14dp"                app:expandDrawable="@mipmap/up"                app:My_maxLines="2"                app:shrinkDrawable="@mipmap/down"                app:textColor="@color/colorAccent"                app:textSize="14sp" />
阅读全文
0 0
原创粉丝点击