1
0
Fork 0
mirror of https://github.com/MatomoCamp/matomocamp-companion-android.git synced 2024-09-19 16:13:46 +02:00

Implement a custom MovementMethod to properly support clickable spans with text selection. Fixes #38

This commit is contained in:
Christophe Beyls 2018-06-08 23:13:29 +02:00
parent 27bb707c93
commit 65178e5b5a
2 changed files with 68 additions and 7 deletions

View file

@ -23,7 +23,6 @@ import android.text.SpannableStringBuilder;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.text.method.MovementMethod;
import android.text.style.ClickableSpan;
import android.view.LayoutInflater;
import android.view.Menu;
@ -47,6 +46,7 @@ import be.digitalia.fosdem.model.Event;
import be.digitalia.fosdem.model.Link;
import be.digitalia.fosdem.model.Person;
import be.digitalia.fosdem.model.RoomStatus;
import be.digitalia.fosdem.utils.ClickableArrowKeyMovementMethod;
import be.digitalia.fosdem.utils.DateUtils;
import be.digitalia.fosdem.utils.StringUtils;
import be.digitalia.fosdem.viewmodels.EventDetailsViewModel;
@ -115,8 +115,6 @@ public class EventDetailsFragment extends Fragment {
textView.setText(text);
}
MovementMethod linkMovementMethod = LinkMovementMethod.getInstance();
// Set the persons summary text first; replace it with the clickable text when the loader completes
holder.personsTextView = view.findViewById(R.id.persons);
String personsSummary = event.getPersonsSummary();
@ -124,7 +122,7 @@ public class EventDetailsFragment extends Fragment {
holder.personsTextView.setVisibility(View.GONE);
} else {
holder.personsTextView.setText(personsSummary);
holder.personsTextView.setMovementMethod(linkMovementMethod);
holder.personsTextView.setMovementMethod(LinkMovementMethod.getInstance());
holder.personsTextView.setVisibility(View.VISIBLE);
}
@ -163,7 +161,7 @@ public class EventDetailsFragment extends Fragment {
ds.setUnderlineText(false);
}
}, 0, roomText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setMovementMethod(linkMovementMethod);
textView.setMovementMethod(LinkMovementMethod.getInstance());
}
textView.setText(roomText);
textView.setContentDescription(getString(R.string.room_content_description, roomText));
@ -177,7 +175,7 @@ public class EventDetailsFragment extends Fragment {
textView.setVisibility(View.GONE);
} else {
textView.setText(StringUtils.parseHtml(text, getResources()));
textView.setMovementMethod(linkMovementMethod);
textView.setMovementMethod(ClickableArrowKeyMovementMethod.getInstance());
}
textView = view.findViewById(R.id.description);
text = event.getDescription();
@ -185,7 +183,7 @@ public class EventDetailsFragment extends Fragment {
textView.setVisibility(View.GONE);
} else {
textView.setText(StringUtils.parseHtml(text, getResources()));
textView.setMovementMethod(linkMovementMethod);
textView.setMovementMethod(ClickableArrowKeyMovementMethod.getInstance());
}
holder.linksHeader = view.findViewById(R.id.links_header);

View file

@ -0,0 +1,63 @@
package be.digitalia.fosdem.utils;
import android.graphics.RectF;
import android.text.Layout;
import android.text.Spannable;
import android.text.method.ArrowKeyMovementMethod;
import android.text.method.MovementMethod;
import android.text.style.ClickableSpan;
import android.view.MotionEvent;
import android.widget.TextView;
/**
* An extension of ArrowKeyMovementMethod supporting clickable spans as well.
*/
public class ClickableArrowKeyMovementMethod extends ArrowKeyMovementMethod {
private static ClickableArrowKeyMovementMethod instance;
private final RectF touchedLineBounds = new RectF();
public static MovementMethod getInstance() {
if (instance == null) {
instance = new ClickableArrowKeyMovementMethod();
}
return instance;
}
@Override
public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
// If action has finished
if (event.getAction() == MotionEvent.ACTION_UP) {
// Locate the area that was pressed
int x = (int) event.getX();
int y = (int) event.getY();
x -= widget.getTotalPaddingLeft();
y -= widget.getTotalPaddingTop();
x += widget.getScrollX();
y += widget.getScrollY();
// Locate the text line
Layout layout = widget.getLayout();
int line = layout.getLineForVertical(y);
// Check that the touch actually happened within the line bounds
touchedLineBounds.left = layout.getLineLeft(line);
touchedLineBounds.top = layout.getLineTop(line);
touchedLineBounds.right = layout.getLineWidth(line) + touchedLineBounds.left;
touchedLineBounds.bottom = layout.getLineBottom(line);
if (touchedLineBounds.contains(x, y)) {
int offset = layout.getOffsetForHorizontal(line, x);
// Find a clickable span at that text offset, if any
ClickableSpan[] link = buffer.getSpans(offset, offset, ClickableSpan.class);
if (link.length > 0) {
link[0].onClick(widget);
return true;
}
}
}
return super.onTouchEvent(widget, buffer, event);
}
}