Android TextView多文本折疊展開效果
最近做項(xiàng)目,效果圖要用到TextView的折疊,超過一定行數(shù)的時(shí)候,就會(huì)折疊起來,點(diǎn)擊可以展開。網(wǎng)上找了一些效果,自己也稍作了修改。便拿來與網(wǎng)友分享分享。
參考文獻(xiàn):Android UI實(shí)現(xiàn)多行文本折疊展開效果
第一種:通過多個(gè)布局組合實(shí)現(xiàn)
大概步驟:
- 定義布局,垂直的線性LinearLayout布局、TextView和ImageView。 在layout中定義基本組件。
- 設(shè)置TextView的高度為指定行數(shù)*行高。 不使用maxLine的原因是maxLine會(huì)控制顯示文本的行數(shù),不方便后邊使用動(dòng)畫展開全部?jī)?nèi)容。因此這里TextView的高度也因該為wrap_content。
- 給整個(gè)布局添加點(diǎn)擊事件,綁定動(dòng)畫。 點(diǎn)擊時(shí),若TextView未展開則展開至其實(shí)際高度,imageView 旋轉(zhuǎn);否則回縮至 指定行數(shù)*行高 , imageView 旋轉(zhuǎn)縮回。
布局文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:more="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.example.my.textviewdemotest.MainActivity"> <TextView android:id="@+id/textView1" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="@android:color/black" android:textSize="18sp"> </TextView> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/expand_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="更多" android:textSize="18sp" android:visibility="gone"/> <ImageView android:id="@+id/expand_view1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:paddingBottom="5dip" android:paddingLeft="5dip" android:paddingRight="5dip" android:paddingTop="5dip" android:src="@drawable/ic_expand_more_red_700_24dp" android:visibility="gone" /> </RelativeLayout> <!-- 第二種方法 --> <com.example.my.textviewdemotest.TextMoreTextView android:layout_width="match_parent" android:layout_height="wrap_content" android:ellipsize="end" more:maxLine="2" more:text="@string/text" more:textColor="@android:color/black" more:textSize="18dip"> </com.example.my.textviewdemotest.TextMoreTextView> </LinearLayout>
核心代碼:
package com.example.my.textviewdemotest;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.view.animation.Transformation;
import android.widget.ImageView;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
TextView text1;
ImageView mImageView1;
TextView expandText;
//TextMoreTextView text2;
boolean isExpand;//是否已展開的狀態(tài)
private int maxDescripLine = 3; //TextView默認(rèn)最大展示行數(shù)
private int deltaValue;//默認(rèn)高度,即前邊由maxLine確定的高度
private int startValue;//起始高度
private int durationMillis = 350;//動(dòng)畫持續(xù)時(shí)間
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text1 = (TextView) findViewById(R.id.textView1);
// text2= (TextMoreTextView) findViewById(R.id.text_textView);
expandText = (TextView) findViewById(R.id.expand_text);
mImageView1 = (ImageView) findViewById(R.id.expand_view1);
mImageView1.setOnClickListener(this);
text1.setText(getText(R.string.text));
//第二種可以在這里直接設(shè)置文字
// text2.setText(getText(R.string.text));
//這里大家可以根據(jù)實(shí)際情況來設(shè)置文字的高度,做個(gè)判斷(可能會(huì)文字只有一行,也會(huì)占據(jù)maxDescripLine行)
text1.setHeight(text1.getLineHeight() * maxDescripLine);
text1.post(new Runnable() {
@Override
public void run() {
mImageView1.setVisibility(text1.getLineCount() > maxDescripLine ? View.VISIBLE : View.GONE);
expandText.setVisibility(text1.getLineCount() > maxDescripLine ? View.VISIBLE : View.GONE);
}
});
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.expand_view1:
zheDie(text1, mImageView1);
break;
}
}
private void zheDie(final TextView text, ImageView imageView) {
isExpand = !isExpand;
text.clearAnimation();
startValue = text.getHeight();
if (isExpand) {
/**
* 折疊動(dòng)畫
* 從實(shí)際高度縮回起始高度
*/
deltaValue = text.getLineHeight() * text.getLineCount() - startValue;
RotateAnimation animation = new RotateAnimation(0, 180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
animation.setDuration(durationMillis);
animation.setFillAfter(true);
imageView.startAnimation(animation);
expandText.setText("收起");
} else {
/**
* 展開動(dòng)畫
* 從起始高度增長(zhǎng)至實(shí)際高度
*/
deltaValue = text.getLineHeight() * maxDescripLine - startValue;
RotateAnimation animation = new RotateAnimation(180, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
animation.setDuration(durationMillis);
animation.setFillAfter(true);
imageView.startAnimation(animation);
expandText.setText("更多");
}
Animation animation = new Animation() {
protected void applyTransformation(float interpolatedTime, Transformation t) { //根據(jù)ImageView旋轉(zhuǎn)動(dòng)畫的百分比來顯示textview高度,達(dá)到動(dòng)畫效果
text.setHeight((int) (startValue + deltaValue * interpolatedTime));
}
};
animation.setDuration(durationMillis);
text.startAnimation(animation);
}
}
第二種方法,如果用的地方多可以省去很多冗余代碼:具體步驟就不直接分析。
核心代碼:
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="MoreTextStyle"> <attr name="textSize" format="dimension"/> <attr name="textColor" format="color"/> <attr name="maxLine" format="integer" /> <attr name="text" format="string" /> </declare-styleable> </resources>
package com.example.my.textviewdemotest;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.view.animation.Transformation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
public class TextMoreTextView extends LinearLayout {
protected TextView contentView;
protected ImageView expandView;
protected int textColor;
protected float textSize;
protected int maxLine;
protected String text;
public int defaultTextColor = Color.BLACK;//默認(rèn)文字顏色
public int defaultTextSize = 12; //默認(rèn)文字大小
public int defaultLine = 3; //默認(rèn)行數(shù)
public TextMoreTextView(Context context, AttributeSet attrs) {
super(context, attrs);
initalize();
initWithAttrs(context, attrs);
// bindListener();
}
protected void initWithAttrs(Context context, AttributeSet attrs) {
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.MoreTextStyle);
int textColor = a.getColor(R.styleable.MoreTextStyle_textColor,
defaultTextColor);
textSize = a.getDimensionPixelSize(R.styleable.MoreTextStyle_textSize, defaultTextSize);
maxLine = a.getInt(R.styleable.MoreTextStyle_maxLine, defaultLine);
text = a.getString(R.styleable.MoreTextStyle_text);
bindTextView(textColor, textSize, maxLine, text);
a.recycle();
}
protected void initalize() {
setOrientation(VERTICAL);
setGravity(Gravity.RIGHT);
contentView = new TextView(getContext());
addView(contentView, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
expandView = new ImageView(getContext());
int padding = dip2px(getContext(), 5);
expandView.setPadding(padding, padding, padding, padding);
expandView.setImageResource(R.drawable.ic_expand_more_red_700_24dp);
LayoutParams llp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
addView(expandView, llp);
}
protected void bindTextView(int color, float size, final int line, String text) {
contentView.setTextColor(color);
contentView.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);
contentView.setText(text);
ViewTreeObserver observer = contentView.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
//判斷寫在這個(gè)方法里面能拿到contentView.getLineCount(),否則返回時(shí)0;
@Override
public void onGlobalLayout() {
ViewTreeObserver obs = contentView.getViewTreeObserver();
obs.removeGlobalOnLayoutListener(this);
if (contentView.getLineCount() < line) {
contentView.setHeight(contentView.getLineHeight() * contentView.getLineCount());
} else {
contentView.setHeight(contentView.getLineHeight() * line);
bindListener();//只有在行數(shù)大于設(shè)定行數(shù)才會(huì)執(zhí)行這個(gè)方法,做了調(diào)整否則會(huì)有bug。
}
//Log.e("aaa", "bindTextView111: " + contentView.getLineCount());//返回0,為什么
}
});
post(new Runnable() {
@Override
public void run() {
expandView.setVisibility(contentView.getLineCount() > line ? View.VISIBLE : View.GONE);
//Log.e("aaa", "run: "+contentView.getLineCount() );
}
});
}
protected void bindListener() {
setOnClickListener(new OnClickListener() {
boolean isExpand;
@Override
public void onClick(View v) {
isExpand = !isExpand;
contentView.clearAnimation();
final int deltaValue;
final int startValue = contentView.getHeight();
int durationMillis = 350;
if (isExpand) {
deltaValue = contentView.getLineHeight() * contentView.getLineCount() - startValue;
RotateAnimation animation = new RotateAnimation(0, 180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
animation.setDuration(durationMillis);
animation.setFillAfter(true);
expandView.startAnimation(animation);
} else {
deltaValue = contentView.getLineHeight() * maxLine - startValue;
RotateAnimation animation = new RotateAnimation(180, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
animation.setDuration(durationMillis);
animation.setFillAfter(true);
expandView.startAnimation(animation);
}
Animation animation = new Animation() {
protected void applyTransformation(float interpolatedTime, Transformation t) {
contentView.setHeight((int) (startValue + deltaValue * interpolatedTime));
}
};
animation.setDuration(durationMillis);
contentView.startAnimation(animation);
}
});
}
public TextView getTextView() {
return contentView;
}
public void setText(CharSequence charSequence) {
contentView.setText(charSequence);
}
public static int dip2px(Context context, float dipValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
}
這個(gè)類這樣就寫好了。調(diào)用直接在布局文件中引用就行了。
源碼下載:http://xiazai.jb51.net/201610/yuanma/Androidtextview(jb51.net).rar
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android UI實(shí)現(xiàn)多行文本折疊展開效果
- Android TextView實(shí)現(xiàn)多文本折疊、展開效果
- Android中RecyclerView實(shí)現(xiàn)多級(jí)折疊列表效果(二)
- Android中RecyclerView實(shí)現(xiàn)多級(jí)折疊列表效果(TreeRecyclerView)
- Android折疊式Toolbar使用完全解析(CollapsingToolbarLayout)
- android給RecyclerView加上折疊的效果示例
- Android中FoldingLayout折疊布局的用法及實(shí)戰(zhàn)全攻略
- Android TextView仿微信可折疊效果
- Android顯示全文折疊控件使用方法詳解
- Android開發(fā)實(shí)現(xiàn)的文本折疊點(diǎn)擊展開功能示例
相關(guān)文章
Android仿QQ滑動(dòng)彈出菜單標(biāo)記已讀、未讀消息
這篇文章主要介紹了Android仿QQ滑動(dòng)彈出菜單標(biāo)記已讀、未讀消息的相關(guān)資料,需要的朋友可以參考下2016-01-01
Android 優(yōu)化Handler防止內(nèi)存泄露
這篇文章主要介紹了Android 優(yōu)化Handler防止內(nèi)存泄露的相關(guān)資料,這里提供實(shí)例幫助大家理解掌握這樣的內(nèi)容,需要的朋友可以參考下2017-09-09
Android人臉識(shí)別Demo豎屏YUV方向調(diào)整和圖片保存(分享)
下面小編就為大家分享一篇Android人臉識(shí)別Demo實(shí)現(xiàn)豎屏YUV方向調(diào)整和圖片保存的方法。具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2017-12-12
android頂部(toolbar)搜索框?qū)崿F(xiàn)代碼
這篇文章主要介紹了android頂部(toolbar)搜索框?qū)崿F(xiàn)代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-01-01
Android保存的文件顯示到文件管理的最近文件和下載列表中的方法
這篇記錄的是Android中如何把我們往存儲(chǔ)中寫入的文件,如何顯示到文件管理的下載列表、最近文件列表中,需要的朋友可以參考下2020-01-01
Android使用getIdentifier()獲取資源Id的方法
這篇文章主要介紹了Android使用getIdentifier()獲取資源Id的方法,涉及Android針對(duì)控件資源的相關(guān)操作技巧,需要的朋友可以參考下2016-08-08
Kotlin實(shí)現(xiàn)在類里面創(chuàng)建main函數(shù)
這篇文章主要介紹了Kotlin實(shí)現(xiàn)在類里面創(chuàng)建main函數(shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-03-03
Android中ACTION_CANCEL的觸發(fā)機(jī)制與滑出子view的情況
這篇文章主要介紹了Android中ACTION_CANCEL的觸發(fā)機(jī)制與滑出子view的情況,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09
Android實(shí)現(xiàn)Activities之間進(jìn)行數(shù)據(jù)傳遞的方法
這篇文章主要介紹了Android實(shí)現(xiàn)Activities之間進(jìn)行數(shù)據(jù)傳遞的方法,涉及Android中Activities的使用技巧,需要的朋友可以參考下2015-04-04

