Здесь есть замечательные ответы на эти вопросы, которые вовлекают во всевозможные подробные сведения о интерфейсах и слабосвязанный код, инверсию управления и т. д. Есть несколько довольно острых дискуссий, поэтому я хотел бы воспользоваться возможностью немного разобраться в том, почему интерфейс полезен.
Когда я впервые начал работать с интерфейсами, я тоже был смущен об их значимости. Я не понимал, зачем вам это нужно. Если мы используем такой язык, как Java или C #, у нас уже есть наследование, и я рассматривал интерфейсы как более слабую форму наследования и мысли «зачем беспокоиться»? В некотором смысле я был прав, вы можете думать о интерфейсах как о какой-то слабой форме наследования, но помимо этого я, наконец, понял их использование в качестве языковой конструкции, считая их как средство классификации общих черт или моделей поведения, которые были представлены потенциально много несвязанных классов объектов.
Например, скажем, у вас есть игра с SIM-картой, и у вас есть следующие классы:
class HouseFly inherits Insect {
void FlyAroundYourHead(){}
void LandOnThings(){}
}
class Telemarketer inherits Person {
void CallDuringDinner(){}
void ContinueTalkingWhenYouSayNo(){}
}
Очевидно, что эти два объекта не имеют ничего в общий с точки зрения прямого наследования. Но вы могли бы сказать, что они оба раздражают.
Предположим, что в нашей игре должно быть какое-то случайное вещь , которая раздражает игрока, когда они едят обед. Это могут быть HouseFly
или Telemarketer
или оба, но как вы можете использовать обе функции с одной функцией? И как вы просите каждый из разных типов объектов «делать свою раздражающую вещь» таким же образом?
Ключом к пониманию является то, что как Telemarketer
, так и HouseFly
имеют общее слабо интерпретируемое поведение даже несмотря на то, что они не имеют ничего общего с их моделированием. Итак, давайте создадим интерфейс, который оба могут реализовать:
interface IPest {
void BeAnnoying();
}
class HouseFly inherits Insect implements IPest {
void FlyAroundYourHead(){}
void LandOnThings(){}
void BeAnnoying() {
FlyAroundYourHead();
LandOnThings();
}
}
class Telemarketer inherits Person implements IPest {
void CallDuringDinner(){}
void ContinueTalkingWhenYouSayNo(){}
void BeAnnoying() {
CallDuringDinner();
ContinueTalkingWhenYouSayNo();
}
}
Теперь у нас есть два класса, каждый из которых может раздражать по-своему. И им не нужно выводить из одного базового класса и обладать общими присущими характеристиками - им просто нужно удовлетворить контракт IPest
- этот контракт прост. Вам просто нужно BeAnnoying
. В этой связи мы можем моделировать следующее:
class DiningRoom {
DiningRoom(Person[] diningPeople, IPest[] pests) { ... }
void ServeDinner() {
when diningPeople are eating,
foreach pest in pests
pest.BeAnnoying();
}
}
Здесь у нас есть столовая, в которой принимают несколько посетителей и несколько вредителей - обратите внимание на использование интерфейса. Это означает, что в нашем маленьком мире членом массива pests
может быть объект Telemarketer
или объект HouseFly
.
Метод ServeDinner
вызывается при подаче обеда и наши люди в столовой должны есть. В нашей маленькой игре, вот когда наши вредители выполняют свою работу - каждый вредитель инструктируется быть раздражающим через интерфейс IPest
. Таким образом, мы с легкостью можем раздражать как Telemarketers
, так и HouseFlys
в каждом из своих способов - мы заботимся только о том, что у нас есть что-то в объекте DiningRoom
, являющемся вредителем, нам все равно что это такое, и они не могли иметь ничего общего с другими.
Этот очень надуманный пример псевдокода (который тянулся намного дольше, чем я ожидал) просто предназначен для иллюстрации того, что, наконец, включило свет для меня с точки зрения того, когда мы могли бы использовать интерфейс. Я заранее извиняюсь за глупость примера, но надеюсь, что это поможет в вашем понимании. И, конечно же, другие опубликованные ответы, которые вы получили здесь, действительно охватывают диапазон использования интерфейсов сегодня в шаблонах проектирования и методологиях разработки.
Последний код, pls см. link form github
blockquote>message.setSpan(span, start, end, flags);
Вам нужно удалить начальный интервал перед установкой нового интервала. См. Ниже Функция onClick () для ClickableSpan не работает для URLSpan?
РЕДАКТИРОВАТЬ Вы можете захватить любое событие клика по диапазону
extends LinkMovementMethod
import android.os.Handler; import android.os.Message; import android.text.Layout; import android.text.Selection; import android.text.Spannable; import android.text.method.LinkMovementMethod; import android.text.method.MovementMethod; import android.view.KeyEvent; import android.view.MotionEvent; import android.widget.TextView; import java.lang.ref.WeakReference; public class LinkMovementMethodExt extends LinkMovementMethod { public static final int LinkMovementMethod_Down = 1001; public static final int LinkMovementMethod_Up = 2002; private static LinkMovementMethod sInstance; private Class mSpanClass = null; private WeakReference<Handler> mWeakReference = null; public static MovementMethod getInstance(Handler handler, Class spanClass) { if (sInstance == null) { sInstance = new LinkMovementMethodExt(); ((LinkMovementMethodExt) sInstance).mWeakReference = new WeakReference<>(handler); ((LinkMovementMethodExt) sInstance).mSpanClass = spanClass; } return sInstance; } @Override public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) { int action = event.getAction(); if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) { int x = (int) event.getX(); int y = (int) event.getY(); x -= widget.getTotalPaddingLeft(); y -= widget.getTotalPaddingTop(); x += widget.getScrollX(); y += widget.getScrollY(); Layout layout = widget.getLayout(); int line = layout.getLineForVertical(y); int off = layout.getOffsetForHorizontal(line, x); /** * get you interest span */ Object[] spans = buffer.getSpans(off, off, mSpanClass); if (spans.length != 0) { if (action == MotionEvent.ACTION_DOWN) { Selection.setSelection(buffer, buffer.getSpanStart(spans[0]), buffer.getSpanEnd(spans[0])); MessageSpan obj = new MessageSpan(); obj.setObj(spans); obj.setView(widget); Handler handler = mWeakReference.get(); if (handler != null) { Message message = handler.obtainMessage(); message.obj = obj; message.what = LinkMovementMethod_Down; message.sendToTarget(); return true; } return false; } else if (action == MotionEvent.ACTION_UP) { Handler handler = mWeakReference.get(); if (handler != null) { MessageSpan obj = new MessageSpan(); obj.setView(widget); Message message = handler.obtainMessage(); message.obj = obj; message.what = LinkMovementMethod_Up; message.sendToTarget(); return true; } return false; } } } return super.onTouchEvent(widget, buffer, event); } public boolean canSelectArbitrarily() { return true; } public boolean onKeyUp(TextView widget, Spannable buffer, int keyCode, KeyEvent event) { return false; }
textView.setMovementMethod (LinkMovementMethodExt.getInstance ());
Изменить для «разработчика Android». Это лучший способ добавить свойство Handler для класса LinkMovementMethodExt. Вы можете захватить все Spanned, которые поставляются как объект Message. Снайперский код в методе onTouchEvent:
Message message = Handler.obtainMessage(); message.obj = buffer.getSpans(off, off, Spanned.class);//get all spanned message.what = 111;//which value ,it is up to you message.sendToTarget(); //send message to you target handler
Вы можете обработать ожидаемое в вашем классе обработчика. Возможно, это гибкий способ обработки. Надеюсь помочь вам.
[/g3]
Над текстом textview
<a href='/a'>aaaa</a>123456<a href='/b'>bbbb</b>7890
Я понимаю ваше требование: нажмите «aaaa», вы хотите получить егоs href value '/a', click 'bbbb',get it
s href '/ b'; Не запускайте действие по умолчанию, которое открывается в веб-браузере. Если я правильно понимаю, вы можете сделать следующее:
- Установить LinkMovementMethod для текстового просмотра и т. Д .:
textview.setMovementMethod(LinkMovementMethodExt.getInstance(handler, URLSpan.class));
- Получить процентный охват, вот URLSpan. В методе handler handleMessage вы можете сделать следующее:
blockquote>private Handler handler = new Handler() { public void handleMessage(Message msg) { int what = msg.what; if (what == 100) { Object[] spans = (Object[])msg.obj; for (Object span : spans) { if (span instanceof URLSpan) { System.out.println(((URLSpan) span).getURL()); } } } }; };
Загрузить демонстрационный код
- Функция MainActivity имеет свойство цвета, которое вы можете назначить, какое значение цвета вы хотите.
Как это сделать?
- Шаг1, получить текущий
- Шаг 2, установите BackgroundColorSpan для текущего диапазона кликов
Предполагая, что вы хотите щелкнуть отдельные слова в текстовом виде ?. Я не понимаю, как конвертирует все буквы в слова в вашем комментарии.
Ниже можно использовать щелчок по отдельным работам, и он отображается в тосте.
public class MainActivity extends Activity {
TextView _tv;
String[] each;
SpannableString ss1;
Button b;
EditText et;
String s;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
b= (Button) findViewById(R.id.button1);
et = (EditText) findViewById(R.id.ed);
_tv = (TextView) findViewById( R.id.tv );
b.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
s=et.getText().toString();
_tv.setText("");
for(int i=0;i<s.length();i++)
{
each = s.split("\\s+");
}
for(int i=0;i<each.length;i++)
{
System.out.println("................"+each[i]);
ss1= new SpannableString(each[i]);
//StyleSpan boldSpan = new StyleSpan( Typeface.BOLD );
//spannable.setSpan( boldSpan, 41, 52, Spannable.SPAN_INCLUSIVE_INCLUSIVE );
ss1.setSpan(new MyClickableSpan(each[i]), 0, ss1.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
_tv.append(ss1);
_tv.append(" ");
}
_tv.setMovementMethod(LinkMovementMethod.getInstance());
}
});
}
class MyClickableSpan extends ClickableSpan{
String clicked;
public MyClickableSpan(String string) {
// TODO Auto-generated constructor stub
clicked =string;
}
//clickable span
public void onClick(View textView) {
//do something
Toast.makeText(MainActivity.this,clicked ,
Toast.LENGTH_SHORT).show();
}
@Override
public void updateDrawState(TextPaint ds) {
ds.setColor(Color.BLACK);//set text color
ds.setUnderlineText(false); // set to false to remove underline
}
}
}