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:
parent
27bb707c93
commit
65178e5b5a
2 changed files with 68 additions and 7 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue