Android仿微信朋友圈全文、收起功能的實(shí)例代碼
前言
一般在社交APP中都有類似朋友圈的功能,其中發(fā)表的動(dòng)態(tài)內(nèi)容很長(zhǎng)的時(shí)候不可能讓它全部顯示。這里就需要做一個(gè)仿微信朋友圈全文、收起功能來解決該問題。在網(wǎng)上看到一個(gè)例子-->http://www.dhdzp.com/article/105251.htm ,寫的很不錯(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ā)生。美國(guó)運(yùn)動(dòng)醫(yī)學(xué)院建議,想知道有氧運(yùn)動(dòng)強(qiáng)度是否合適,可在運(yùn)動(dòng)后測(cè)試心率,以達(dá)到最高心率的60%—90%為宜。如果想通過有氧運(yùn)動(dòng)來減肥,可以選擇低度到中度的運(yùn)動(dòng)強(qiáng)度,同時(shí)延長(zhǎng)運(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)前,先測(cè)一下,如果連續(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
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Kotlin協(xié)程啟動(dòng)createCoroutine及創(chuàng)建startCoroutine原理
這篇文章主要為大家介紹了Kotlin協(xié)程啟動(dòng)createCoroutine及創(chuàng)建startCoroutine原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
Android組件創(chuàng)建DrawerLayout導(dǎo)航
這篇文章主要為大家詳細(xì)介紹了Android組件創(chuàng)建DrawerLayout導(dǎo)航的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-01-01
Android 動(dòng)畫之RotateAnimation應(yīng)用詳解
本節(jié)講解旋轉(zhuǎn)動(dòng)畫效果RotateAnimation方法的應(yīng)用,有需要的朋友可以參考下2012-12-12
詳解Android App中創(chuàng)建ViewPager組件的方法
這篇文章主要介紹了詳解Android App中創(chuàng)建ViewPager組件的方法,ViewPager最基本的功能就是可以使視圖滑動(dòng),需要的朋友可以參考下2016-03-03
Android編程之SQLite數(shù)據(jù)庫(kù)操作方法詳解
這篇文章主要介紹了Android編程之SQLite數(shù)據(jù)庫(kù)操作方法,簡(jiǎn)單介紹了SQLite數(shù)據(jù)庫(kù)及Android操作SQLite數(shù)據(jù)庫(kù)的步驟與相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-08-08
Android中實(shí)現(xiàn)視差滾動(dòng)示例介紹
大家好,本篇文章主要講的是Android中實(shí)現(xiàn)視差滾動(dòng)示例介紹,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽2021-12-12
Android 6.0以上權(quán)限拒絕打開權(quán)限設(shè)置界面的解決方法
今天小編就為大家分享一篇Android 6.0以上權(quán)限拒絕打開權(quán)限設(shè)置界面的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-07-07
Android嵌套滾動(dòng)和協(xié)調(diào)滾動(dòng)的多種實(shí)現(xiàn)方法
嵌套的滾動(dòng)主要方式就是這些,這些簡(jiǎn)單的效果我們用協(xié)調(diào)滾動(dòng),如?CoordinatorLayout?也能實(shí)現(xiàn)同樣的效果,這篇文章主要介紹了Android嵌套滾動(dòng)和協(xié)調(diào)滾動(dòng)的多種實(shí)現(xiàn)方法,需要的朋友可以參考下2022-06-06

