Android仿微信朋友圈全文蚜退、收起功能

前言

一般在社交APP中都有類似朋友圈的功能,其中發(fā)表的動(dòng)態(tài)內(nèi)容很長的時(shí)候不可能讓它全部顯示彪笼。這里就需要做一個(gè)仿微信朋友圈全文钻注、收起功能來解決該問題。在網(wǎng)上看到一個(gè)例子--> http://blog.csdn.net/e042kuuw/article/details/55107537 配猫,寫的很不錯(cuò)幅恋,但是有個(gè)bug,他這個(gè)Demo只有在條目固定的時(shí)候才正常泵肄,當(dāng)增加捆交、刪除條目的時(shí)候會(huì)出現(xiàn)全文、收起顯示混亂的問題腐巢。原因是他使用了固定的position作為key來保存當(dāng)前顯示的狀態(tài)零渐。這篇文章在他的基礎(chǔ)上進(jìn)行優(yōu)化。

效果圖

具體代碼

(詳細(xì)解釋在代碼注釋中都有系忙,這里就省略了)
MainActivity.java

package com.wildma.wildmaexpandfoldtext;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

import java.util.ArrayList;
import java.util.List;

/**
 * Author     wildma
 * DATE       2017/8/3
 * Des        ${TODO}
 */
public class MainActivity extends AppCompatActivity {
    private RecyclerView mRecyclerView;
    List<ExpandFoldTextBean> mList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initData();
        ExpandFoldTextAdapter adapter = new ExpandFoldTextAdapter(mList, this);
        mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
        mRecyclerView.setAdapter(adapter);
    }

    /**
     * 初始化數(shù)據(jù)
     */
    private void initData() {
        String longContent = "-->游泳诵盼、快走、慢跑银还、騎自行車风宁,及一切有氧運(yùn)動(dòng)都能鍛煉心臟。有氧運(yùn)動(dòng)好處多:能鍛煉心肺蛹疯、增強(qiáng)循環(huán)系統(tǒng)功能戒财、燃燒脂肪、加大肺活量捺弦、降低血壓饮寞,甚至能預(yù)防糖尿病,減少心臟病的發(fā)生列吼。美國運(yùn)動(dòng)醫(yī)學(xué)院建議幽崩,想知道有氧運(yùn)動(dòng)強(qiáng)度是否合適,可在運(yùn)動(dòng)后測試心率寞钥,以達(dá)到最高心率的60%—90%為宜慌申。如果想通過有氧運(yùn)動(dòng)來減肥,可以選擇低度到中度的運(yùn)動(dòng)強(qiáng)度理郑,同時(shí)延長運(yùn)動(dòng)時(shí)間蹄溉,這種方法消耗的熱量更多咨油。運(yùn)動(dòng)頻率每周3—5次,每次20—60分鐘柒爵。想要鍛煉肌肉役电,可以練舉重、做體操以及其他重復(fù)伸棉胀、屈肌肉的運(yùn)動(dòng)宴霸。肌肉鍛煉可以燃燒熱量、增強(qiáng)骨密度膏蚓、減少受傷,尤其是關(guān)節(jié)受傷的幾率畸写,還能預(yù)防骨質(zhì)疏松驮瞧。 在做舉重運(yùn)動(dòng)前,先測一下枯芬,如果連續(xù)舉8次你最多能舉多重的東西论笔,就從這個(gè)重量開始練習(xí)。當(dāng)你可以連續(xù)12次舉起這個(gè)重量時(shí)千所,試試增加5%的重量狂魔。注意每次練習(xí)時(shí),要連續(xù)舉8—12次淫痰,這樣可以達(dá)到肌肉最大耐力的70%—80%最楷,鍛煉效果較好。每周2—3次待错,但要避免連續(xù)兩天鍛煉同一組肌肉群籽孙, 以便讓肌肉有充分的恢復(fù)時(shí)間。";
        String shortContent = "-->健身是一種體育項(xiàng)目火俄,如各種徒手健美操犯建、韻律操、形體操以及各種自抗力動(dòng)作瓜客。";
        for (int i = 0; i < 20; i++) {
            ExpandFoldTextBean bean = new ExpandFoldTextBean();
            if (i % 2 == 0) {
                bean.setContent(i + shortContent);
                bean.setId(i);
            } else {
                bean.setContent(i + longContent);
                bean.setId(i);
            }
            mList.add(bean);
        }
    }
}

ExpandFoldTextAdapter.java

package com.wildma.wildmaexpandfoldtext;

import android.app.Activity;
import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.TextView;

import java.util.List;

/**
 * Author     wildma
 * DATE       2017/8/3
 * Des        ${展開折疊文本適配器}
 */
public class ExpandFoldTextAdapter extends RecyclerView.Adapter<ExpandFoldTextAdapter.MyViewHolder> {
    private Activity mContent;

    private final int MAX_LINE_COUNT = 3;//最大顯示行數(shù)

    private final int STATE_UNKNOW = -1;//未知狀態(tài)

    private final int STATE_NOT_OVERFLOW = 1;//文本行數(shù)小于最大可顯示行數(shù)

    private final int STATE_COLLAPSED = 2;//折疊狀態(tài)

    private final int STATE_EXPANDED = 3;//展開狀態(tài)

    /**
     * 注意:保存文本狀態(tài)集合的key一定要是唯一的适瓦,如果用position。
     * 如果使用position作為key谱仪,則刪除玻熙、增加條目的時(shí)候會(huì)出現(xiàn)顯示錯(cuò)亂
     */
    private SparseArray<Integer> mTextStateList;//保存文本狀態(tài)集合

    List<ExpandFoldTextBean> mList;

    public ExpandFoldTextAdapter(List<ExpandFoldTextBean> list, Activity context) {
        mContent = context;
        this.mList = list;
        mTextStateList = new SparseArray<>();
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new MyViewHolder(mContent.getLayoutInflater().inflate(R.layout.item_expand_fold_text, parent, false));
    }

    @Override
    public void onBindViewHolder(final MyViewHolder holder, final int position) {
        int state = mTextStateList.get(mList.get(position).getId(), STATE_UNKNOW);
        //第一次初始化,未知狀態(tài)
        if (state == STATE_UNKNOW) {
            holder.content.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                @Override
                public boolean onPreDraw() {
                    //這個(gè)回掉會(huì)調(diào)用多次疯攒,獲取完行數(shù)后記得注銷監(jiān)聽
                    holder.content.getViewTreeObserver().removeOnPreDrawListener(this);
                    //holder.content.getViewTreeObserver().addOnPreDrawListener(null);
                    //如果內(nèi)容顯示的行數(shù)大于最大顯示行數(shù)
                    if (holder.content.getLineCount() > MAX_LINE_COUNT) {
                        holder.content.setMaxLines(MAX_LINE_COUNT);//設(shè)置最大顯示行數(shù)
                        holder.expandOrFold.setVisibility(View.VISIBLE);//顯示“全文”
                        holder.expandOrFold.setText("全文");
                        mTextStateList.put(mList.get(position).getId(), STATE_COLLAPSED);//保存狀態(tài)
                    } else {
                        holder.expandOrFold.setVisibility(View.GONE);
                        mTextStateList.put(mList.get(position).getId(), STATE_NOT_OVERFLOW);
                    }
                    return true;
                }
            });

            holder.content.setMaxLines(Integer.MAX_VALUE);//設(shè)置文本的最大行數(shù)揭芍,為整數(shù)的最大數(shù)值
            holder.content.setText(mList.get(position).getContent());
        } else {
            //如果之前已經(jīng)初始化過了,則使用保存的狀態(tài)卸例。
            switch (state) {
                case STATE_NOT_OVERFLOW:
                    holder.expandOrFold.setVisibility(View.GONE);
                    break;
                case STATE_COLLAPSED:
                    holder.content.setMaxLines(MAX_LINE_COUNT);
                    holder.expandOrFold.setVisibility(View.VISIBLE);
                    holder.expandOrFold.setText("全文");
                    break;
                case STATE_EXPANDED:
                    holder.content.setMaxLines(Integer.MAX_VALUE);
                    holder.expandOrFold.setVisibility(View.VISIBLE);
                    holder.expandOrFold.setText("收起");
                    break;
            }
            holder.content.setText(mList.get(position).getContent());
        }

        //全文和收起的點(diǎn)擊事件
        holder.expandOrFold.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int state = mTextStateList.get(mList.get(position).getId(), STATE_UNKNOW);
                if (state == STATE_COLLAPSED) {
                    holder.content.setMaxLines(Integer.MAX_VALUE);
                    holder.expandOrFold.setText("收起");
                    mTextStateList.put(mList.get(position).getId(), STATE_EXPANDED);
                } else if (state == STATE_EXPANDED) {
                    holder.content.setMaxLines(MAX_LINE_COUNT);
                    holder.expandOrFold.setText("全文");
                    mTextStateList.put(mList.get(position).getId(), STATE_COLLAPSED);
                }
            }
        });

        //刪除點(diǎn)擊事件
        holder.delete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mList.remove(position);
                notifyDataSetChanged();
            }
        });
    }

    @Override
    public int getItemCount() {
        return mList.size();
    }


    public class MyViewHolder extends RecyclerView.ViewHolder {
        public TextView nickname;
        public TextView content;
        public TextView delete;
        public TextView expandOrFold;

        public MyViewHolder(View itemView) {
            super(itemView);
            nickname = (TextView) itemView.findViewById(R.id.tv_nickname);
            content = (TextView) itemView.findViewById(R.id.tv_content);
            delete = (TextView) itemView.findViewById(R.id.tv_delete);
            expandOrFold = (TextView) itemView.findViewById(R.id.tv_expand_or_fold);
        }
    }
}

ExpandFoldTextBean.java

package com.wildma.wildmaexpandfoldtext;

/**
 * Author     wildma
 * DATE       2017/8/3
 * Des        ${TODO}
 */
public class ExpandFoldTextBean {

    private String content;//內(nèi)容

    private int id;//該條數(shù)據(jù)的id

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    android:id="@+id/activity_main"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </android.support.v7.widget.RecyclerView>

</RelativeLayout>

item_expand_fold_text.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:orientation="vertical"
              android:paddingBottom="@dimen/activity_vertical_margin"
              android:paddingLeft="@dimen/activity_horizontal_margin"
              android:paddingRight="@dimen/activity_horizontal_margin"
              android:paddingTop="@dimen/activity_vertical_margin">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:orientation="horizontal">

        <ImageView
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_marginRight="16dp"
            android:gravity="center"
            android:scaleType="centerCrop"
            android:src="@mipmap/ic_launcher"/>

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <TextView
                android:id="@+id/tv_nickname"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="wildma"
                android:textColor="@android:color/black"
                android:textSize="14sp"/>

            <TextView
                android:id="@+id/tv_delete"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_marginLeft="12dp"
                android:paddingLeft="5dp"
                android:paddingRight="5dp"
                android:text="刪除"
                android:textColor="@android:color/holo_red_dark"
                android:textSize="14sp"/>
        </RelativeLayout>

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="56dp"
        android:orientation="vertical"
        android:paddingBottom="8dp">

        <TextView
            android:id="@+id/tv_content"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:alpha="0.85"
            android:ellipsize="end"
            android:text="內(nèi)容"
            android:textColor="@android:color/black"
            android:textSize="14sp"/>

        <TextView
            android:id="@+id/tv_expand_or_fold"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="全文"
            android:textColor="@color/colorPrimaryDark"
            android:textSize="14sp"/>
    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="0.5dp"
        android:background="@android:color/black"/>
</LinearLayout>

源碼地址:https://github.com/wildma/WildmaExpandFoldText 歡迎star !
參考:http://blog.csdn.net/e042kuuw/article/details/55107537

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末称杨,一起剝皮案震驚了整個(gè)濱河市肌毅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌姑原,老刑警劉巖悬而,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異锭汛,居然都是意外死亡笨奠,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門唤殴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來般婆,“玉大人,你說我怎么就攤上這事朵逝∥蹬郏” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵配名,是天一觀的道長啤咽。 經(jīng)常有香客問我,道長渠脉,這世上最難降的妖魔是什么宇整? 我笑而不...
    開封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮芋膘,結(jié)果婚禮上鳞青,老公的妹妹穿的比我還像新娘。我一直安慰自己为朋,他們只是感情好盼玄,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著潜腻,像睡著了一般埃儿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上融涣,一...
    開封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天童番,我揣著相機(jī)與錄音,去河邊找鬼威鹿。 笑死剃斧,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的忽你。 我是一名探鬼主播幼东,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了根蟹?” 一聲冷哼從身側(cè)響起脓杉,我...
    開封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎简逮,沒想到半個(gè)月后球散,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡散庶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年蕉堰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片悲龟。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡屋讶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出须教,到底是詐尸還是另有隱情皿渗,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布没卸,位于F島的核電站,受9級(jí)特大地震影響秒旋,放射性物質(zhì)發(fā)生泄漏约计。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一迁筛、第九天 我趴在偏房一處隱蔽的房頂上張望煤蚌。 院中可真熱鬧,春花似錦细卧、人聲如沸尉桩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蜘犁。三九已至,卻和暖如春止邮,著一層夾襖步出監(jiān)牢的瞬間这橙,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來泰國打工导披, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留屈扎,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓撩匕,卻偏偏與公主長得像鹰晨,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,133評(píng)論 25 707
  • 在此特此聲明:一下所有鏈接均來自互聯(lián)網(wǎng)模蜡,在此記錄下我的查閱學(xué)習(xí)歷程漠趁,感謝各位原創(chuàng)作者的無私奉獻(xiàn) ! 技術(shù)一點(diǎn)一點(diǎn)積...
    遠(yuǎn)航的移動(dòng)開發(fā)歷程閱讀 11,118評(píng)論 12 197
  • 這個(gè)主題的內(nèi)容之前分三個(gè)篇幅分享過哩牍,導(dǎo)致網(wǎng)絡(luò)上傳播的比較分散棚潦,所以本篇做了一個(gè)匯總,同時(shí)對(duì)部分內(nèi)容及答案做了修改膝昆,...
    JavaQ閱讀 23,673評(píng)論 9 264
  • 點(diǎn)擊文章標(biāo)題即可閱讀文章 1丸边、吸霾八個(gè)月后,我回到食物森林 |【美國務(wù)農(nóng)日記】(2) 2荚孵、【農(nóng)場案例】關(guān)于一個(gè)家庭...
    青春實(shí)驗(yàn)室閱讀 136評(píng)論 0 0
  • 摘要:大學(xué)假期歸來妹窖,通過對(duì)家鄉(xiāng)的調(diào)查研究,了解鄉(xiāng)的生活風(fēng)貌收叶,和近年來家鄉(xiāng)的變化和發(fā)展骄呼,以及家鄉(xiāng)的社會(huì)主義新農(nóng)村建設(shè)...
    梅之韻閱讀 35,275評(píng)論 1 32