最近開發需求中要模仿微信朋友圈文章的展開收起功能,網上找了找,發現都有問題,於是乎自己在前輩的基礎上進行了一定量的修改,下邊將源碼貼出來供大家參考:
1.主Activity佈局文件就不粘貼了,很簡單,就一個ListView.
2.主Activity功能實現:
package com.example.textviewdemo;
import java.util.HashMap;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.TextView.BufferType;
public class MainActivity extends Activity {
String mStr;
int type;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Globl.map = new HashMap<Integer, Boolean>();
ListView listview = (ListView) findViewById(R.id.listview);
mStr = "手指在ListView上下滾動時,ListViewItem背景變黑,因爲在滾動的時候爲了提升性能做了優化,爲提高滾動的性能,Android 框架在ListView中引入CacheColorHint屬性。如果該值爲非0,則說明該ListView繪製在單色不透明的背景上,在默認情況下該值 爲#191919,也就是黑色主題中的黑色背景顏色值,這樣當ListView滾動的時候";
listview.setAdapter(new MyListAdpter(this));
}
class MyListAdpter extends BaseAdapter {
Context con;
CollapsibleTextView tv;
public MyListAdpter(Context con) {
this.con = con;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return 10;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
HashMap<Integer, View> hashM = new HashMap<Integer, View>();
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Holder holder = null;
View view;
if (hashM.get(position) == null) {
holder = new Holder();
view = LayoutInflater.from(con).inflate(R.layout.item_list,
null);
holder.tv = (CollapsibleTextView) view
.findViewById(R.id.tv_text);
holder.tvcount = (TextView) view.findViewById(R.id.tvcount);
view.setTag(holder);
hashM.put(position, view);
} else {
view = hashM.get(position);
holder = (Holder) view.getTag();
}
// if (Globl.map.get(position) == false) {
// Globl.map.put(position, false);
// type = 2;
// } else {
// type = 1;
// }
// tv.setNowType(type);
// int typeNow = tv.getNowType();
holder.tvcount.setText(position + "");
holder.tv.setDesc(mStr, holder.tv, BufferType.NORMAL);
return view;
}
class Holder {
CollapsibleTextView tv;
TextView tvcount;
}
}
}
3.自定義控件CollapsibleTextView 源碼:
/**
* @Explain: Text過長收起 帶有查看全文/收起功能控件;
* @Author:LYl
* @Time:2014-11-27 下午4:33:05
* @Version V2.1.54
*/
public class CollapsibleTextView extends LinearLayout implements
OnClickListener {
/** 最大顯示的行數 */
private static final int DEFAULT_MAX_LINE_COUNT = 8;
/** 實際展示的行數 */
private static final int DEFAULT_SHOW_LINE_COUNT = 6;
private static final int COLLAPSIBLE_STATE_NONE = 0;
/** View處於展開狀態 **/
private static final int COLLAPSIBLE_STATE_SHRINKUP = 1;
/** view收縮時狀態 **/
private static final int COLLAPSIBLE_STATE_SPREAD = 2;
/** 顯示內容的View */
private TextView tv_context;
/** 展開/收起按鈕 */
private TextView bt_spread;
private String shrinkup;
private String spread;
/** 當前正處於的狀態 */
// private int mState;
private boolean flag;
private int nowType;
private CollapsibleTextView coTextView;
/** 判斷是不是點擊了查看更多、收起 */
private boolean isClicke = false;
private int lookCount = 0;
public CollapsibleTextView(Context context, AttributeSet attrs) {
super(context, attrs);
shrinkup = "收起";
spread = "查看全文";
View view = inflate(context, R.layout.collapsible_textview, this);
view.setPadding(0, -1, 0, 0);
tv_context = (TextView) view.findViewById(R.id.tv_context);
bt_spread = (TextView) view.findViewById(R.id.bt_spread);
bt_spread.setOnClickListener(this);
}
public CollapsibleTextView(Context context) {
this(context, null);
}
/**
* 賦值
*/
public final void setDesc(CharSequence charSequence,
CollapsibleTextView tv, BufferType bufferType) {
this.coTextView = tv;
// 對內容中的網址進行處理;
tv_context.setAutoLinkMask(Linkify.WEB_URLS);
tv_context.setMovementMethod(LinkMovementMethod.getInstance());
tv_context.setText(charSequence, bufferType);
// 初始類型
if (lookCount == 0) {
coTextView.setNowType(COLLAPSIBLE_STATE_SPREAD);
}
lookCount += 1;
// TODO LYL 放到ListView中需要加下句:falg=false;一般情況去掉就可
flag = false;
requestLayout();
}
@Override
public void onClick(View v) {
flag = false;
isClicke = true;
requestLayout();
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (!flag) {
flag = true;
if (tv_context.getLineCount() <= DEFAULT_MAX_LINE_COUNT) {
bt_spread.setVisibility(View.GONE);
tv_context.setMaxLines(DEFAULT_MAX_LINE_COUNT + 1);
coTextView.setNowType(COLLAPSIBLE_STATE_NONE);
} else {
post(new InnerRunnable());
}
}
}
class InnerRunnable implements Runnable {
@Override
public void run() {
int zType = 0;
// 第一次進入操作(沒有點擊並且是第一次進入);
System.out.println("lookCount:" + lookCount);
if (!isClicke && lookCount == 1) {
if (coTextView.getNowType() == COLLAPSIBLE_STATE_SPREAD) {
tv_context.setMaxLines(DEFAULT_SHOW_LINE_COUNT);
bt_spread.setVisibility(View.VISIBLE);
bt_spread.setText(spread);
zType = COLLAPSIBLE_STATE_SHRINKUP;
} else if (coTextView.getNowType() == COLLAPSIBLE_STATE_SHRINKUP) {
tv_context.setMaxLines(Integer.MAX_VALUE);
bt_spread.setVisibility(View.VISIBLE);
bt_spread.setText(shrinkup);
zType = COLLAPSIBLE_STATE_SPREAD;
}
coTextView.setNowType(zType);
// 點擊了查看更多、收起轉換狀態;
} else if (isClicke) {
isClicke = false;
if (coTextView.getNowType() == COLLAPSIBLE_STATE_SPREAD) {
tv_context.setMaxLines(DEFAULT_SHOW_LINE_COUNT);
bt_spread.setVisibility(View.VISIBLE);
bt_spread.setText(spread);
coTextView.setNowType(COLLAPSIBLE_STATE_SHRINKUP);
} else if (coTextView.getNowType() == COLLAPSIBLE_STATE_SHRINKUP) {
tv_context.setMaxLines(Integer.MAX_VALUE);
bt_spread.setVisibility(View.VISIBLE);
bt_spread.setText(shrinkup);
coTextView.setNowType(COLLAPSIBLE_STATE_SPREAD);
}
// 滑動listView 從新載入到可見界面 不做操作,保持原有狀態;(爲了後面看得人能夠更理解寫上)
} else if (!isClicke && lookCount != 1) {
}
}
}
public int getNowType() {
return nowType;
}
public void setNowType(int nowType) {
this.nowType = nowType;
}
}
4.自定義控件加載的Layout:
<?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="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/tv_context"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4.0dip"
android:gravity="center_vertical"
android:textColor="#ff000000"
android:textSize="14.0dip" />
<TextView
android:id="@+id/bt_spread"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="4.0dip"
android:gravity="center"
android:singleLine="true"
android:textColor="#ff576b95"
android:textSize="18.0dip"
android:visibility="gone" />
</LinearLayout>
現在經過修改後其實還是有點小問題的,如果按照上邊的寫的話,偶爾點擊收起/展開按鈕會失效,但是一滑動整體ListView就會執行操作;如果,將getView()方法中的HashMap判斷換成ConvertView判斷,點擊就沒問題了,但是展開一個item後慢慢的滑出屏幕,您會發現,下邊剛剛出現的Item會處於打開狀態,本人才疏學淺,猜測可能是複用了,目前沒想到什麼好的方法解決,希望能有大神指點一下,這是目的之一,同時也希望能幫助初學者!
下邊是運行後的結果: