標簽在文本里插入一個鏈接,點擊后跳轉;并且有標簽可以插入圖片。Android開發是否也支持呢?帶著這個疑問,我們去APIDemos探索一下。OK,在com.example.android.apis.text.link這個類里,官方演示了TextView支持的一些鏈接,上個圖:看來TextView是支持鏈接跳轉的,不過做An" />

欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

Textview加入Intent、表情,點擊跳轉Activity

系統 1609 0

?? ? ?( 第二屆 Google 暑期大學生博客分享大賽 - 2011 Android 成長篇

?? ? ?做過web開發的人應該都知道,在HTML里支持<a>標簽在文本里插入一個鏈接,點擊后跳轉;并且有<img>標簽可以插入圖片。Android開發是否也支持呢?帶著這個疑問,我們去APIDemos探索一下。OK,在com.example.android.apis.text.link這個類里,官方演示了TextView支持的一些鏈接,上個圖:


Textview加入Intent、表情,點擊跳轉Activity

?

?? ? ?看來TextView是支持鏈接跳轉的,不過做Android開發的應該都知道,android的View載體是Activity,能不能支持activity跳轉呢,很遺憾,不支持。

?? ? ?不過無所謂,Android很有愛,開源的,理解了原理后我們自己去做,這也是我寫本篇文章的主要目的,"授之以魚,不如授之以漁",希望大家在遇到相似問題時能像我這樣去分析源碼,然后找出解決辦法(或者大家可以提出更好的方法),另外,文中如有不妥的地方,也歡迎大家批評指正。先上效果圖:點擊左邊的鏈接后跳轉到右邊。



Textview加入Intent、表情,點擊跳轉Activity ?? Textview加入Intent、表情,點擊跳轉Activity

?

?? ?現在我們開始開發吧!第一步,研究相關的源代碼吧。通過跟蹤TextView的源碼,我們發現TextView支持的鏈接是由 android.text.style.URLSpan 這個類實現的,它重寫了一個onClick方法:

?

    public void onClick(View widget) {
        Uri uri = Uri.parse(getURL());
        Context context = widget.getContext();
        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
        intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
        context.startActivity(intent);
    }
  

?? ? ?大家看到了吧startActivity,多么熟悉的方法。既然它能實現,為什么我們不能呢,答案是可以的。我們接著跟蹤代碼,可以看到URLSpan其實繼承的是android.text.style.ClickableSpan,我們來看一下他的源碼:

?

    public abstract class ClickableSpan extends CharacterStyle implements UpdateAppearance {

    /**
     * Performs the click action associated with this span.
     */
    public abstract void onClick(View widget);
   
    /**
     * Makes the text underlined and in the link color.
     */
    @Override
    public void updateDrawState(TextPaint ds) {
        ds.setColor(ds.linkColor);
        ds.setUnderlineText(true);
    }
}
  

?是不是有點眉目了,我們直接繼承這個類,重寫他的方法不就可以了嗎?大膽假設,小心求證,我們新建一個類:

?

    import android.content.Context;
import android.content.Intent;
import android.text.TextPaint;
import android.text.style.ClickableSpan;
import android.view.View;

/**
 * If an object of this type is attached to the text of a TextView with a
 * movement method of LinkMovementMethod, the affected spans of text can be
 * selected. If clicked, the {@link #onClick} method will be called.
 * 
 * @author 張寧
 */
public class MyClickableSpan extends ClickableSpan {

	int color = -1;
	private Context context;
	private Intent intent;

	public MyClickableSpan(Context context, Intent intent) {
		this(-1, context, intent);
	}

	/**
	 * constructor
	 * @param color the link color
	 * @param context
	 * @param intent
	 */
	public MyClickableSpan(int color, Context context, Intent intent) {
		if (color!=-1) {
			this.color = color;
		}
		this.context = context;
		this.intent = intent;
	}

	/**
	 * Performs the click action associated with this span.
	 */
	public void onClick(View widget){
		context.startActivity(intent);
	};

	/**
	 * Makes the text without underline.
	 */
	@Override
	public void updateDrawState(TextPaint ds) {
		if (color == -1) {
			ds.setColor(ds.linkColor);
		} else {
			ds.setColor(color);
		}
		ds.setUnderlineText(false);
	}
}
  

?

?? ? ?在這個類里,我們重寫了onClick事件,實現了Activity的跳轉,并且去掉了下劃線。Ok,第一個目的就達到了,下面我們來看一下如何在TextView里加入表情。

?? ? ?這個就比較復雜了,因為TextView只能在其上下左右方向加入圖片,是由Drawables這個類實現的,而我們想要的效果是在中間也可以插入,看來這次TextView插入圖片源碼幫不了我們了。不過我們可以去android.text這個包里去找別的類,大家可以看到在這個包里有一個Html類,做過web開發的應該可以想到什么吧?在文章開頭已經提到了Html的<img>標簽可以插入圖片,那這個類是否提供這個功能呢?帶著這個疑問我們可以進去看看,其中有個接口:

?

     /**
     * Retrieves images for HTML &lt;img&gt; tags.
     */
    public static interface ImageGetter {
        /**
         * This methos is called when the HTML parser encounters an
         * &lt;img&gt; tag.  The <code>source</code> argument is the
         * string from the "src" attribute; the return value should be
         * a Drawable representation of the image or <code>null</code>
         * for a generic replacement image.  Make sure you call
         * setBounds() on your Drawable if it doesn't already have
         * its bounds set.
         */
        public Drawable getDrawable(String source);
    }
  

?

?? ? 看到 <code>source</code>這個沒,熟悉吧,結合URLSpan的用法,我們是否可以配合Spanned實現一個

ImageSpan呢?OK,上代碼:

?

    import java.util.Map;
import java.util.Set;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.text.Html;
import android.text.Spanned;
import android.text.Html.ImageGetter;

/**
 * this is a class which defining a spanned with image
 * @author 張寧
 *
 */
public class ImageSpan {
	
	/**
	 * the map of face.
	 */
	private Map<String, String> faceMap;
	private Context context;
	
	public ImageSpan(Context context, Map<String, String> faceMap){
		this.context = context;
		this.faceMap = faceMap;
	} 

	/**
	 * get the image by the given key
	 */
	private ImageGetter imageGetter = new Html.ImageGetter() {
		@Override
		public Drawable getDrawable(String source) {
			Drawable drawable = null;
			String sourceName = context.getPackageName() + ":drawable/"
					+ source;
			int id = context.getResources().getIdentifier(sourceName, null, null);
			if (id != 0) {
				drawable = context.getResources().getDrawable(id);
				if (drawable != null) {
					drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),
							drawable.getIntrinsicHeight());
				}
			}
			return drawable;
		}
	};
	
	/**
	 * return a {@link Spanned} with image
	 * @param text
	 * @return
	 */
	public Spanned getImageSpan(CharSequence text){
		String cs = text.toString();
		if (faceMap != null) {
			Set<String> keys = faceMap.keySet();
			for (String key : keys) {
				if (cs.contains(key)) {
					cs = cs.replace(key, "<img src='" + faceMap.get(key) + "'>");
				}
			}
		}
		return Html.fromHtml(cs, imageGetter, null);
	}

}
  

?

?? ? ?到目前為止可以說關鍵代碼都已經實現了,但是會有人問,我該如何使用這兩個類呢?下面,我們在實現一個工具類來封裝這兩個類的方法,以方便調用:

?

    import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.content.Context;
import android.content.Intent;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.widget.EditText;
import android.widget.TextView;

/**
 * TextView with intent that can redirect to a new activity
 * 
 * @author 張寧
 * 
 */
public class CustomTextView {

	private static Map<String, String> faceMap;

	static {
		faceMap = new HashMap<String, String>();
		faceMap.put("[哭]", "face_1");
		faceMap.put("[怒]", "face_2");
	}

	/**
	 * make textview a clickable textview<br>
	 * Note: make true the order of textList and intentList are mapped
	 * 
	 * @param context
	 * @param textView
	 * @param textList
	 *            the text should be set to this textview,not null
	 * @param intentList
	 *            the intent map to the text, if the text have no intent mapped
	 *            to, please set a null value.Or it will happen some unknown
	 *            error.<br>
	 *            not null
	 */
	public static void setClickableTextView(Context context, TextView textView,
			List<String> textList, List<Intent> intentList) {
		if (textList == null || intentList == null) {
			return;
		}
		SpannableStringBuilder builder = new SpannableStringBuilder();
		int end = -1, length = -1;
		int size = textList.size();
		Intent intent;
		for (int i = 0; i < size; i++) {
			String text = textList.get(i);
			if (TextUtils.isEmpty(text)) {
				continue;
			}
			builder.append(textList.get(i));
			if ((intent = intentList.get(i)) != null) {
				end = builder.length();
				length = textList.get(i).length();
				builder.setSpan(getClickableSpan(context, intent),
						end - length, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
			}
			builder.append(" ");
		}
		textView.setText(builder);
		textView.setFocusable(true);
		textView.setMovementMethod(LinkMovementMethod.getInstance());
	}
	
	/**
	 *  make textview a clickable textview<br>
	 *  Note: make true the order of textList and intentList are mapped
	 * @param context
	 * @param textView
	 * @param text
	 * @param intent
	 */
	public static void setClickableTextView(Context context, TextView textView,
			String text, Intent intent) {
		SpannableStringBuilder builder = new SpannableStringBuilder(text);
		builder.setSpan(getClickableSpan(context, intent), 0, text.length(), 
				Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
		textView.setText(builder);
		textView.setMovementMethod(LinkMovementMethod.getInstance());
	}

	/**
	 * make TextView a View with image at any index  
	 * @param context
	 * @param textView
	 * @param textList
	 */
	public static void setImgTextView(Context context, TextView textView,
			List<String> textList) {
		StringBuilder builder = new StringBuilder();
		for (int i = 0; i < textList.size(); i++) {
			builder.append(textList.get(i)).append(" ");
		}
		setImgTextView(context, textView, builder.toString());

	}

	/**
	 * make TextView a View with image at any index  
	 * @param context
	 * @param textView
	 * @param text
	 */
	public static void setImgTextView(Context context, TextView textView,
			String text) {
		ImageSpan imageSpan = new ImageSpan(context, faceMap);
		Spanned spanned = imageSpan.getImageSpan(text);
		textView.setText(spanned);
	}
	
	/**
	 * make EditText a View with image at any index  
	 * @param context
	 * @param EditText
	 * @param text
	 */
	public static void setImgTextView(Context context, EditText editText,
			String text) {
		ImageSpan imageSpan = new ImageSpan(context, faceMap);
		Spanned spanned = imageSpan.getImageSpan(text);
		editText.setText(spanned);
	}

	/**
	 * return a custom ClickableSpan
	 * 
	 * @param context
	 * @param intent
	 * @return
	 */
	public static MyClickableSpan getClickableSpan(Context context,
			Intent intent) {
		return new MyClickableSpan(context, intent);
	}

	/**
	 * make textview a clickable textview with image<br>
	 * Note: make true the order of textList and intentList are mapped
	 * 
	 * @param context
	 *            not null
	 * @param haveImg
	 *            whether this is image in the text,not null
	 * @param textView
	 *            not null
	 * @param textList
	 *            the text should be set to this textview,not null
	 * @param intentList
	 *            the intent map to the text, if the text have no intent mapped
	 *            to, please set a null value.Or it will happen some unknown
	 *            error.<br>
	 *            allow null
	 */
	public static void setCustomText(Context context, Boolean haveImg,
			TextView textView, List<String> textList, List<Intent> intentList) {
		SpannableStringBuilder builder = new SpannableStringBuilder();
		int end = -1, length = -1;
		if (intentList != null) {
			int size = textList.size();
			Intent intent;
			for (int i = 0; i < size; i++) {
				String text = textList.get(i);
				if (TextUtils.isEmpty(text)) {
					continue;
				}
				builder.append(textList.get(i));
				if ((intent = intentList.get(i)) != null) {
					end = builder.length();
					length = textList.get(i).length();
					builder.setSpan(getClickableSpan(context, intent), end
							- length, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
				}
				builder.append(" ");
			}
		} else {
			for (String text : textList) {
				builder.append(text).append(" ");
			}
		}
		if (haveImg) {
			ImageSpan imageSpan = new ImageSpan(context, faceMap);
			Spanned spanned = imageSpan.getImageSpan(builder);
			textView.setText(spanned);
		} else {
			textView.setText(builder);
		}
		textView.setMovementMethod(LinkMovementMethod.getInstance());

	}

}
  

?

?? ?有了這個類,我們就可以方便的實現在TextView中插入Intent和表情了,甚至不用管底層是怎樣實現的,也降低了代碼的耦合度。但是又回到我寫這篇文章的目的:希望大家能得到“漁”而不僅僅是“魚”。

?? ?Ok,任務完成。源碼奉上。

注:原創作品,轉載請標明出處:

?

? http://zhangning290.iteye.com/blog/1134286

?

?

Textview加入Intent、表情,點擊跳轉Activity


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 亚洲高清一区二区三区 | 国产精品一区二区三区久久久 | 2022国产成人精彩在线视频 | 国产精品国产 | 理论片午午伦夜理片在线播放 | 色哟哟久久 | 欧美精品18videosex性俄罗斯 | 亚洲精品第一页 | 午夜电影通| 欧美日韩在线一区二区 | 成人免费在线视频网站 | 毛片毛片毛片毛片毛片 | 日韩在线观看视频免费 | 国产精品高清在线观看 | 亚洲伊人精品 | 成人片网址 | 日韩欧美一区二区三区不卡在线 | 美女被免费网站在线视频九色 | 污网站在线免费看 | 欧美无遮挡一区二区三区 | 热99久久| 国产精品久久福利新婚之夜 | 大陆黄色网 | 色在线看| 亚洲婷婷综合网 | 婷婷射丁香| 亚洲欧美一区二区三区在线 | 一区二区三区四区免费 | 一级啪啪片| 午夜专区 | 国产精品久久久久久搜索 | 91麻豆精品一二三区在线 | 久久免费播放视频 | 国产片翁熄系列乱在线视频 | 国产婷婷精品av在线 | 日韩免费视频播播 | a网站| 免费观看成年的网站 | 日韩在线观看免费 | 成人精品一区二区三区 | 九色91|