轉(zhuǎn)載請標(biāo)明出處:1片楓葉的專欄
上1篇文章中我們講授了1個簡單,強大的廣告活動彈窗控件。很多App在打開的時候需要彈出1個廣告活動彈窗,點擊廣告活動彈窗中的圖片就會跳轉(zhuǎn)到1個H5頁面,加載顯示具體的活動內(nèi)容等,為了方便大家的操作,我將其做成了1個標(biāo)準(zhǔn)控件:android-adDialog。需要說明的是,雖然其名稱為android-adDialog,并且表現(xiàn)情勢也和Dialog類似,但是這里其實不是通過Dialog實現(xiàn)的,而是自定義的View。
本文我們將講授1個使用的多行文本顯示控件,在實際開發(fā)進程中我們經(jīng)常會遇到這類需求:有兩個TextView控件分行顯示,當(dāng)?shù)?個TextView的內(nèi)容過量1行顯示不下時,我們需要將第2個TextView在第1個TextView的第2行末尾顯示,當(dāng)?shù)?個TextView第2行也顯示不下時,第1個TextView的第2行結(jié)尾以“…”結(jié)束,第2個TextView顯示在第2行的最后段,而本文介紹的就是1個實現(xiàn)這類需求的自定義控件。
本項目的github地址:android-titleView,歡迎star和follow。
在介紹具體的使用說明之前,我們先看1下簡單的實現(xiàn)效果:
使用說明
當(dāng)大title文案顯示為1行的時候,大title和小title分行顯示;
當(dāng)大title文案顯示為兩行且不滿兩行的時候,小title在大title第2行顯示內(nèi)容以后顯示;
當(dāng)大title文案顯示滿兩行的時候,小title在第2行末尾顯示,大title第2行不占滿全行,切末尾以…結(jié)束;
支持對大title文案內(nèi)容,字體色彩,字體大小的設(shè)定,支持對小title文案內(nèi)容,字體色彩,字體大小的設(shè)定;
自定義屬性說明:
<!-- titleView自定義屬性 -->
<declare-styleable name="titleview" >
<!-- 用于設(shè)定大title的文案內(nèi)容 -->
<attr name="title_content" format="string"/>
<!-- 用于設(shè)定小title的文案內(nèi)容 -->
<attr name="count_content" format="string"/>
<!-- 用于設(shè)定大title文案文字大小 -->
<attr name="title_text_size" format="dimension"/>
<!-- 用于設(shè)定大title文案文字色彩 -->
<attr name="title_text_color" format="color"/>
<!-- 用于設(shè)定小title文案文字大小 -->
<attr name="count_text_size" format="dimension"/>
<!-- 用于設(shè)定小title文案文字色彩 -->
<attr name="count_text_color" format="color"/>
</declare-styleable>
使用方式:
compile 'cn.yipianfengye.android:mich-titleview:1.0'
<com.mich.titleview.TitleView
android:id="@+id/title_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:padding="10dp"
app:title_content="人魚線,狗公腰,剛果隊長真是太帥了"
app:count_content="15.3萬次播放"
app:title_text_size="18dp"
app:title_text_color="#334455"
app:count_text_size="12dp"
app:count_text_color="#666666"
/>
/**
* 初始化組件
*/
public void initView() {
titleView = (TitleView) findViewById(R.id.title_view);
btnAdd = (Button) findViewById(R.id.btn_add);
btnDel = (Button) findViewById(R.id.btn_del);
btnAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
titleView.setTitleContent(titleView.getTitleContent() + "人魚線,狗公腰,剛過隊長太帥了");
}
});
btnDel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (titleView.getTitleContent().length() > 15) {
titleView.setTitleContent(titleView.getTitleContent().substring(0, titleView.getTitleContent().length() - 15));
}
}
});
}
怎樣樣是否是很簡單?下面我們可以來看1下具體API。
實現(xiàn)原理:
下面是自定義組件的布局實現(xiàn)部份:
<?xml version="1.0" encoding="utf⑻"?>
<marge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:id="@+id/first_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18dp"
android:textColor="#334455"
android:maxLines="1"
/>
<LinearLayout
android:id="@+id/linear_inner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="8dp"
>
<TextView
android:id="@+id/second_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18dp"
android:textColor="#334455"
android:maxLines="1"
android:layout_gravity="center_vertical"
android:ellipsize="end"
/>
<TextView
android:id="@+id/count_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="15.2萬次播放"
android:textSize="12dp"
android:maxLines="1"
android:ellipsize="end"
android:layout_gravity="center_vertical"
/>
</LinearLayout>
</marge>
下面是自定義組件的核心代碼部份:
/**
* Created by aaron on 16/9/19.
* 自定義實現(xiàn)TitleView組件
*/
public class TitleView extends LinearLayout{
/**
* title TextView組件
*/
private TextView firstTitle = null;
/**
* title TextView組件
*/
private TextView secondTitle = null;
/**
* 播放次數(shù)TextView組件
*/
private TextView countView = null;
/**
* title組件
*/
private String titleContent = "";
private String countContent = "";
public TitleView(Context context) {
super(context);
init(context, null);
}
public TitleView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
/**
* 履行初始化操作
* @param context
*/
private void init(Context context, AttributeSet attrs) {
if (context == null) {
return;
}
View rootView = LayoutInflater.from(context).inflate(R.layout.view_titleview, null);
ViewGroup.LayoutParams lps = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
this.addView(rootView, lps);
/**
* 初始化組件
*/
initView(rootView);
/**
* 初始化自定義屬性
*/
if (attrs != null) {
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.titleview);
titleContent = ta.getString(R.styleable.titleview_title_content);
countContent = ta.getString(R.styleable.titleview_count_content);
firstTitle.setText(titleContent);
countView.setText(countContent);
float titleTextSize = ta.getDimension(R.styleable.titleview_title_text_size, firstTitle.getTextSize());
firstTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, titleTextSize);
secondTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, titleTextSize);
int titleTextColor = ta.getColor(R.styleable.titleview_title_text_color, firstTitle.getCurrentTextColor());
firstTitle.setTextColor(titleTextColor);
secondTitle.setTextColor(titleTextColor);
float countTextSize = ta.getDimension(R.styleable.titleview_count_text_size, countView.getTextSize());
countView.setTextSize(TypedValue.COMPLEX_UNIT_PX, countTextSize);
int countTextColor = ta.getColor(R.styleable.titleview_count_text_color, countView.getCurrentTextColor());
countView.setTextColor(countTextColor);
}
}
/**
* 履行組件的初始化操作
* @param rootView
*/
private void initView(View rootView) {
firstTitle = (TextView) rootView.findViewById(R.id.first_textview);
secondTitle = (TextView) rootView.findViewById(R.id.second_textview);
countView = (TextView) rootView.findViewById(R.id.count_textview);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
doUpdateUI();
}
/**
* 履行更新UI的操作
*/
private void doUpdateUI() {
if (firstTitle != null) {
firstTitle.post(new Runnable() {
@Override
public void run() {
/**
* 當(dāng)title只有1行時,不做任何操作,默許便可
*/
Paint paint = firstTitle.getPaint();
if (paint.measureText(titleContent) <= firstTitle.getWidth()) {
secondTitle.setVisibility(View.GONE);
}
/**
* 履行title顯示為兩行的處理邏輯
*/
else {
secondTitle.setVisibility(View.VISIBLE);
/**
* 獲得第1行顯示內(nèi)容,第2行顯示內(nèi)容
*/
int count = 1;
StringBuffer sb = new StringBuffer(titleContent.substring(0, 1));
while (paint.measureText(sb.toString()) < firstTitle.getWidth()) {
if (count >= titleContent.length()) {
break;
}
sb.append(titleContent.substring(count, count + 1));
count ++;
}
String firstLineContent = sb.toString();
String secondLineContent = titleContent.substring(count);
firstTitle.setText(firstLineContent);
secondTitle.setText(secondLineContent);
/**
* 獲得相干組件的寬高
*/
int titleWidth = firstTitle.getWidth();
int countWidth = countView.getWidth();
/**
* 獲得第2行文字的長度
*/
float secondLineWidth = secondTitle.getPaint().measureText(secondLineContent);
/**
* 判斷第2行文字長度是不是大于組件的長度-播放次數(shù)組件的長度
*/
if (secondLineWidth > titleWidth - countWidth) {
secondTitle.getLayoutParams().width = titleWidth - countWidth;
} else {
secondTitle.getLayoutParams().width = ViewGroup.LayoutParams.WRAP_CONTENT;
}
secondTitle.setText(secondLineContent);
}
}
});
}
}
// ###################### 組件的set get方法 #########################
public String getTitleContent() {
return new StringBuffer(firstTitle.getText().toString()).append(secondTitle.getText().toString()).toString();
}
public void setTitleContent(String titleContent) {
this.titleContent = titleContent;
firstTitle.setText(titleContent);
doUpdateUI();
}
public String getCountContent() {
return countView.getText().toString();
}
public void setCountContent(String countContent) {
this.countContent = countContent;
countView.setText(countContent);
doUpdateUI();
}
}
可以看到注釋的挺詳細的,其主要的實現(xiàn)思路是:通過3個TextView實現(xiàn)的:
首先判斷大title的內(nèi)容是不是占滿1行,若沒有的話,則大小title控件分行顯示;
其次截取大title第1行的顯示本文顯示在第1行的控件上,然后獲得剩余的顯示文本顯示在第2個控件上,若第2個控件也將占滿1行則重設(shè)其寬度,預(yù)留出可以顯示小title控件的位置;
固然更具體的關(guān)于控件的實現(xiàn)可以下載源碼參考。
總結(jié):
以上就是我實現(xiàn)的這個簡單的多行文本顯示控件。固然現(xiàn)在還很不完善,以后其還可以添加1些其他的API、自定義屬性等,歡迎提出,對源碼有興趣的同學(xué)可以到github上看1下具體實現(xiàn)。項目地址:android-titleview
另外對github項目,開源項目解析感興趣的同學(xué)可以參考我的:
Github項目解析(1)–>上傳Android項目至github
Github項目解析(2)–>將Android項目發(fā)布至JCenter代碼庫
Github項目解析(3)–>Android內(nèi)存泄漏監(jiān)測之leakcanary
Github項目解析(4)–>動態(tài)更改TextView的字體大小
Github項目解析(5)–>Android日志框架
Github項目解析(6)–>自定義實現(xiàn)ButterKnife框架
Github項目解析(7)–>避免按鈕重復(fù)點擊
Github項目解析(8)–>Activity啟動進程中獲得組件寬高的5種方式
Github項目解析(9)–>實現(xiàn)Activity跳轉(zhuǎn)動畫的5種方式
Github項目解析(10)–>幾行代碼快速集成2維碼掃描庫
Github項目解析(101)–>1個簡單,強大的自定義廣告活動彈窗