您的位置:首页 > 其它

开源项目MultiActionTextView解析

2015-05-31 10:17 288 查看
        MultiActionTextView是GitHub一个热门的开源项目(项目地址:https://github.com/ajaysahani/MultiActionTextView),主要功能是可以方便地可以分别给TextView中的某几个字设置点击事件,最近分析了源代码,觉得也不复杂,就有了写博客的想法,用一个小demo来简单解析下这个开源项目。

        这个小demo的效果是给一个TextView1中的一个字符串“中国到英格兰看球”中的“中国”和“英格兰”添加点击事件,类似链接的功能(实际上也可以为字符串中的额有效地址做成链接),点击“中国”之后则在另一个TextView2中显示“中国”,点击“英格兰”则在TextView2中显示“英格兰”。

 
   利用MultiActionTextView给这段字符串添加两个链接,点击“中国”:

 
     


 
   

     点击“英格兰”:

 
   


 
  

    首选是实体类InputObject,携带我们设置的数据:

   

public class InputObject {

/**
* start index
*/
private int startSpan;
/**
* end index
*/
private int endSpan;
/**
* append entire sub text into SpannableStringBuilder
*/
private SpannableStringBuilder stringBuilder;
/**
* Call back to handle click event
*/
private MultiActionTextviewClickListener multiActionTextviewClickListener;
/**
* input object which we want when click event occur.
*/
private Object inputObject;
/**
* uniquely identify on which part of text view click.
*/
private int OperationType;

public Object getInputObject() {
return inputObject;
}

public void setInputObject(Object inputObject) {
this.inputObject = inputObject;
}

public int getOperationType() {
return OperationType;
}

public void setOperationType(int operationType) {
OperationType = operationType;
}

public int getStartSpan() {
return startSpan;
}

public void setStartSpan(int startSpan) {
this.startSpan = startSpan;
}

public int getEndSpan() {
return endSpan;
}

public void setEndSpan(int endSpan) {
this.endSpan = endSpan;
}

public SpannableStringBuilder getStringBuilder() {
return stringBuilder;
}

public void setStringBuilder(SpannableStringBuilder stringBuilder) {
this.stringBuilder = stringBuilder;
}

public MultiActionTextviewClickListener getMultiActionTextviewClickListener() {
return multiActionTextviewClickListener;
}

public void setMultiActionTextviewClickListener(
MultiActionTextviewClickListener multiActionTextviewClickListener) {
this.multiActionTextviewClickListener = multiActionTextviewClickListener;
}

}


   SpannableStringBuilder和String差不多,但是它可以能给这些存储的String添加各种格式或者称样式(Span),将原来的String以不同的样式显示出来,比如在原来String上加下划线、加背景色、改变字体颜色、用图片把指定的文字给替换掉,等等。

    setStartSpan是为字符串设置的添加链接的文段的起始位置,同样setEndSpan是给其设置结束位置。

    

    setMultiActionTextviewClickListener是添加监听器,监听器MultiActionTextviewClickListener如下:

 
  

public interface MultiActionTextviewClickListener {

/**
*
* @param inputObject
*            : Object which we had sent in request getting back when click
*            operation occur basically use to identify which part of Text
*            clicked. User operation type variable to identify for which
*            section of text clicked.
*/
public void onTextClick(InputObject inputObject);
}


   非常简单,只有一个方法,在后面的业务类将被回调。

   

   核心的类MultiActionTextView:

 
  

public class MultiActionTextView {

public static void setSpannableText(TextView textView,
SpannableStringBuilder stringBuilder, int highLightTextColor) {
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setText(stringBuilder, BufferType.SPANNABLE);
textView.setLinkTextColor(highLightTextColor);
}

public static void addActionOnTextViewWithLink(final InputObject inputObject) {
inputObject.getStringBuilder().setSpan(
new MultiActionTextViewClickableSpan(true) {
@Override
public void onClick(View widget) {
inputObject.getMultiActionTextviewClickListener()
.onTextClick(inputObject);
}
}, inputObject.getStartSpan(), inputObject.getEndSpan(),Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}

/**
*
* @param inputObject
*            :should not null Method responsible for creating click able
*            part in TextView with hyper link.
*/
public static void addActionOnTextViewWithoutLink(
final InputObject inputObject) {
inputObject.getStringBuilder().setSpan(
new MultiActionTextViewClickableSpan(false) {
@Override
public void onClick(View widget) {
inputObject.getMultiActionTextviewClickListener()
.onTextClick(inputObject);
}
}, inputObject.getStartSpan(), inputObject.getEndSpan(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}

}


      addActionOnTextViewWithLink是为相应的文本添加链接,首先inputObject.getStringBuilder().setSpan是将inputObject存储的SpannableStringBuilder对象取出,调用其setSpan方法,这个是程序的重点,先看安卓api文档的

对该方法的解释:

 
  public void setSpan(Object what,
int start, int end, int flags)

    Mark the specified range of text with the specified object. The flags determine how the span will behave when text is inserted at the start or end of the span's range.

    就是为特定范围的文本添加链接的意思,参数what通常传入一个ClickableSpan对象,start和end分别对应链接文本的始终点,flags是指定是否包括始终点,即传入的范围是开区间还是闭区间。

   ClickableSpan又是什么呢?安卓官方文档:

  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 
onClick(View)
 method
will be called.

   就是当一个设置了LinkMovementMethod的TextView的字符串设置了ClickableSpan对象,则该字符串可以被点击并回调ClickableSpan对象的onClick(View)方法,这就是实现链接的核心。

    

 
  而在我们的setSpan方法中,传入的是MultiActionTextViewClickableSpan,它是我们自己写的继承ClickableSpan的类,扩展了一个链接文本选择是否下划线的方法:

 
 

public abstract class MultiActionTextViewClickableSpan extends ClickableSpan {

private boolean isUnderLineRequired;

public MultiActionTextViewClickableSpan(boolean isUnderLineRequired) {
this.isUnderLineRequired = isUnderLineRequired;
}

@Override
public void updateDrawState(TextPaint ds) {
ds.setColor(ds.linkColor);
ds.setUnderlineText(isUnderLineRequired);
}

}
      

 
 在程序中重写ClickableSpan的onClick方法:

public
void onClick(View widget) {
inputObject.getMultiActionTextviewClickListener()
.onTextClick(inputObject);
}     

  

 
  实质调用的是inputObject中设置的监听器的onTextClick方法,而这个方法会在客户端程序实现。

 
  而setSpan方法传入的后三个参数inputObject.getStartSpan(),inputObject.getEndSpan(),Spannable.SPAN_EXCLUSIVE_EXCLUSIVE,前两个是我们在程序中设置好的确定链接文本范围的,最后一个是决定范围是开区间。

 
 而setSpannableText方法则是封装我们之前设置好链接的那段SpannableStringBuilder文本所在的TextView的一些设置,这样之前设置好的SpannableStringBuilder链接才可以生效。   

 
  说了这么多,看下客户端怎么写吧,经过这样的封装,在客户端中只需设置好InputObject需要的值,再调用addActionOnTextViewWithLink方法,最后调用setSpannableText方法将文本添加到TextView中且使得TextView具有链接文本功能。

 
   客户端程序:

 
   

public class MainActivity extends Activity {

private String str = "中国到英格兰看球";
private TextView tv1;
private TextView tv2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv1 = (TextView) findViewById(R.id.tv1);
tv2 = (TextView) findViewById(R.id.tv2);
SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
stringBuilder.append(str);
InputObject chinaClick = new InputObject();
chinaClick.setStartSpan(0);
chinaClick.setEndSpan(2);
chinaClick.setStringBuilder(stringBuilder);
chinaClick.setMultiActionTextviewClickListener(new MultiActionTextviewClickListener() {

@Override
public void onTextClick(InputObject inputObject) {
tv2.setText("中国");

}
});

MultiActionTextView.addActionOnTextViewWithLink(chinaClick);

InputObject englishClick = new InputObject();
englishClick.setStartSpan(3);
englishClick.setEndSpan(6);
englishClick.setStringBuilder(stringBuilder);
englishClick.setMultiActionTextviewClickListener(new MultiActionTextviewClickListener() {

@Override
public void onTextClick(InputObject inputObject) {
tv2.setText("英格兰");

}
});

MultiActionTextView.addActionOnTextViewWithLink(englishClick);

MultiActionTextView.setSpannableText(tv1, stringBuilder, Color.BLUE);
}

}


 
  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  安卓开源项目