標籤:android textview高亮 ui編程 自訂 正則匹配
概述:
如果你想要在一個TextView顯示一個被高亮顯示的子字串。例如,我想讓"123456789"中的"345"被高亮顯示。注意,我這裡指的只高亮一部分,而不是全部高亮。你會怎麼做?我不知道會不會有一些初學者會想到的是,讓這些子字串分部於不同的TextView,再對每個TextView進行單獨處理。當然,如果你已經是一個已經有一些經驗的開發人員,那我想,你應該就不會再這樣去思考了。因為,Android已經給我封裝好了——SpannableStringBuilder。下面我就學習Android中對控制項的一些封裝來封裝一個我們自己的TextView(既可在xml中設定也可在Java代碼中設定)。
執行個體:
這裡其實有兩個LightTextView。第一個是匹配所有的郵箱,第二個是匹配所有的數字。具體細節,大家可以在部落格的最後下載源碼進行查看。
執行個體功能介紹:
1.設定常值內容
2.設定需要進行匹配的Regex
3.設定匹配出來的子字串的前景色彩
4.設定匹配出來的子字串的背景色
5.設定是否顯示前景色彩
6.設定是否顯示背景色
7.設定是否部署以上設定
執行個體示範講解:1.在Java代碼中去實現控制項屬性的設定
其實使用Java代碼來設定控制項的屬性,無疑是簡單的。因為它,只是需要對外封裝出一些可用的介面即可。例如下面這樣:
/** * 設定背景色 * 2015-3-12 */ private int mBackColor; public void setBackColor(int color) { mBackColor = color; }是不是很簡單?
當前,Java代碼在這方面與attrs相比,的確是要簡單一些。不過,程式的關鍵還是要依靠Java代碼來支撐的。例如下面這個程式碼片段:
private void showForeBackground() { SpannableStringBuilder styleBuilder = new SpannableStringBuilder(mText); // 封裝字型內容 if (mDecbackground) { for (int i = 0; i < matchedText.size(); i++) { styleBuilder.setSpan(new BackgroundColorSpan(mBackColor), matchedText.get(i).getStart(), matchedText.get(i).getEnd(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } } if (mDecForeground) { for (int i = 0; i < matchedText.size(); i++) { styleBuilder.setSpan(new ForegroundColorSpan(mForeColor), matchedText.get(i).getStart(), matchedText.get(i).getEnd(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } } setText(styleBuilder); }可能大家看到一些變數和函數名的時候已經猜測到了這個程式碼片段的功能了。它就是設定我們需要對子字串高亮的部分。這裡有一個變數需要注意matchedText,它在代碼中的定義如下:
private List<SubMatchModel> matchedText = null;
是的,這是一個List,那裡面的SubMatchModel是什麼呢?這是一個我們自己封裝好了的Model。它的功能是記錄我們在匹配字串的過程中,遇到的字元集(當前一個Model也就只對記錄一個子字元了,所以這裡才會是List)。好了,那現在就讓我們看看它裡面的內容吧:
public class SubMatchModel { private String subString; private int start; private int end; public String getSubString() { return subString; } public void setSubString(String subString) { this.subString = subString; } public int getStart() { return start; } public void setStart(int start) { this.start = start; } public int getEnd() { return end; } public void setEnd(int end) { this.end = end; } }這裡只有三個成員變數
subString:記錄匹配到的子字串
start:這個子字串的開始位置
end:這個子字串的結束位置
下面就是一個基本匹配的過程,並使用List<SubMatchModel>來記錄它:
/** * 獲得一個字串中匹配正則的子字元集 * @author Q-WHai * 2015-3-12 */ public static List<SubMatchModel> getMatchString(String str, String exp) { Pattern p = Pattern.compile(exp); // 在這裡,編譯 成一個正則 Matcher m; m = p.matcher(str); // 獲得匹配 List<SubMatchModel> models = new ArrayList<SubMatchModel>(); SubMatchModel model = null; while(m.find()) { model = new SubMatchModel(); model.setSubString(m.group()); model.setStart(m.start()); model.setEnd(m.end()); models.add(model); } return models; }
使用示範:
private LightTextView mShowLightTextView = null;
private void resetWidgets() { mShowLightTextView.setIsMatchOrNot(true); mShowLightTextView.setText("我的郵箱地址是:[email protected],你的郵箱地址是:[email protected]"); mShowLightTextView.setRegularExp(Utils.getMatchEmailString()); mShowLightTextView.setBackColor(Color.BLUE); mShowLightTextView.setForeColor(Color.RED); mShowLightTextView.setDecbackground(true); mShowLightTextView.setDecForeground(true); mShowLightTextView.show(); }大家可以看到上面最後一個方法,show(),是不是顯示這個LigthTextView呢?不是的,它只是把之前對LightTextView的一些設定部署到這個LightTextView上來而已。
2.自訂屬性attrs的使用
看了上面對LightTextView的一些屬性設定和部署,是不是感覺有一點複雜?當然,這裡要說它複雜和之前我說Java來寫比較簡單的說法不矛盾,因為這兩者之間沒有什麼關係。如果非要說上一些關係,我想應該是得失平衡吧。就像我們要把程式寫得簡單了,那麼使用者那邊可能就會比較複雜,如果想要讓使用者使用起來簡單,那程式中就會使用以一些比較複雜的邏輯。這裡也是這樣的。如果想要讓外部對其調用時比較簡單,那麼裡面的設定肯定是比較繁瑣的,如果想要讓內部的代碼簡單一些,那麼對外的內容就會比較繁瑣了。說了這麼多,那麼使用attrs究竟是怎麼樣的呢?
例如My Code就是這樣的:
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="LightTextView"> <attr name="text" format="string" /> <attr name="isMatch" format="boolean" /> <attr name="decForeground" format="boolean" /> <attr name="decbackground" format="boolean" /> <attr name="backgroundColor" format="reference|color" /> <attr name="foregroundColor" format="reference|color" /> </declare-styleable></resources>
注意事項:
這裡有一些地方需要我們注意一下。
1.在Java代碼的構造器中去實現以下方法:
private void init(TypedArray array) { mText = array.getString(R.styleable.LightTextView_text); mIsMatch = array.getBoolean(R.styleable.LightTextView_isMatch, true); mDecForeground = array.getBoolean(R.styleable.LightTextView_decForeground, false); mDecbackground = array.getBoolean(R.styleable.LightTextView_decbackground, false); mForeColor = array.getColor(R.styleable.LightTextView_foregroundColor, Color.BLACK); mBackColor = array.getColor(R.styleable.LightTextView_backgroundColor, Color.WHITE); }
在構造器中調用示範:
public LightTextView(Context context, AttributeSet attrs) { super(context, attrs); TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.LightTextView); init(mTypedArray); }
2.在xml檔案中需要包含程式名:
一定要有上面的被紅色框框出來的兩個部分。在紅色框中又被框出來兩個部分也是需要注意的。前者為你後面要使用的自訂屬性的名稱,後者為你目前的程式包名,而不能使用你自訂控制項所在的包。
源碼下載:
以上就是全部的講解,如果大家還有什麼不太明白的地方,歡迎移步到我的源碼地址進行下載。
http://download.csdn.net/detail/u013761665/8496945
Android UI編程之自訂控制項——可高亮顯示的TextView