Как включить кликабельный текст в staticlayout и SurfaceView

Я разрабатываю интерактивную детскую книгу. Я использую холст для просмотра поверхности, так как мне нужна анимация, которая, по моему мнению, лучше всего подходит для просмотра поверхности.

Я хочу сделать каждое слово осязаемым и прочитать это слово вслух. Это отлично работало, когда я использовал обычное представление с текстовым представлением внутри. Затем я попробовал холст для анимации и не знаю, как это сделать.

Я использовал статический макет на холсте для хранения растягиваемого текста. Я не знаю, как я могу активировать onTouchListener.

Здесь я настроил staticlayout

public class OurView extends SurfaceView implements Runnable, Callback {
    public OurView(Context context, AttributeSet attribs) {
    super(context, attribs);
    init(context);
}

private void init(Context context) {
    ball = BitmapFactory.decodeResource(getResources(), R.drawable.ball);

    text = context.getString(R.string.para1);
    tpaint = new TextPaint();
    tpaint.setColor(Color.WHITE);
    tpaint.setStyle(Style.FILL);
    tpaint.setTextSize(40F);
    TextView tv = splitWords(text);

    staticLayout = new StaticLayout(??????????, tpaint, 1000F,
            Layout.Alignment.ALIGN_NORMAL, 1, 0, false);

    holder = getHolder();
    holder.addCallback(this);
}

Это было мое разделение текста на слова и создание прослушивателя касания для каждого слова. В настоящее время он возвращает Textview, я пытался вернуть spaanablestring, но не смог активировать прослушиватель. Я хочу изменить его в соответствии со своими потребностями. Я не знаю, как сделать tv.setMovementMethod(new LinkTouchMovementMethod()) без текстового просмотра.

public TextView splitWords(final String text) {
    TextView tv = new TextView(getContext());
    final SpannableString ssText = new SpannableString(text);
    Pattern pattern;
    String regex = "\\w+";
    pattern = Pattern.compile(regex);
    Matcher matcher = pattern.matcher(text);
    while (matcher.find()) {
        final int begin = matcher.start();
        final int end = matcher.end();
        ClickableSpan clickableSpan = new ClickableSpan() {

            @Override
            public void onClick(View widget) {
                String word = (String) text.subSequence(begin, end)
                        .toString();
                Toast.makeText(getContext(), word, Toast.LENGTH_SHORT)
                        .show();
                return;                 
            }
        };
        ssText.setSpan(clickableSpan, begin, end, 0);
    }
    tv.setMovementMethod(new LinkMovementMethod());
    tv.setText(text, BufferType.SPANNABLE);
    return tv;
}

Для полноты моего DoDraw

private void doDraw(Canvas canvas) {
    canvas.drawBitmap(ball, x, 100, null);
    incrementX();
    canvas.save();
    canvas.translate(100.0f, 350.0f);
    staticLayout.draw(canvas);
    canvas.restore();
}

Я хочу либо добавить текстовое представление в staticlayout, либо добавить spannableString и активировать слушателей.


person Ryan Heitner    schedule 20.02.2013    source источник
comment
ты решил это с staticlayout?   -  person user924    schedule 27.10.2017


Ответы (1)


Вам нужно переопределить метод onTouch в вашем пользовательском представлении. Обратитесь к следующему коду, большинство из них скопировано из LinkTouchMovementMethod.onTouchEvent().

private boolean updateSelection(MotionEvent event, Spannable buffer,Layout layout) {
    int action = event.getAction();

    if (action == MotionEvent.ACTION_UP ||
        action == MotionEvent.ACTION_DOWN) {
      int x = (int) event.getX();
      int y = (int) event.getY();

      x -= getPaddingLeft();
      y -= getPaddingTop();

      x += getScrollX();
      y += getScrollY();

      int line = layout.getLineForVertical(y);
      int off = layout.getOffsetForHorizontal(line, x);

      ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);

      if (link.length != 0) {
        if (action == MotionEvent.ACTION_UP) {
          link[0].onClick(this);
        } else {
          Selection.setSelection(buffer,
                                 buffer.getSpanStart(link[0]),
                                 buffer.getSpanEnd(link[0]));
        }

        return true;
      } else {
        Selection.removeSelection(buffer);
      }
    }

    return false;

Вызовите метод updateSelection в вашем методе View.onTouchEvent().

@Override
public boolean onTouchEvent(MotionEvent event) {
   return updateSelection(event, layout.getText(), layout);
}

См. Weex RichText, чтобы увидеть реальную демонстрацию.

person York    schedule 20.12.2016
comment
Я собираюсь отметить этот правильный тон добросовестно. Я не могу проверить это, так как не работаю с Android в эти дни. Однако это выглядит как хорошо проработанный и исследованный качественный ответ. - person Ryan Heitner; 20.12.2016
comment
staticlayout не имеет буфера Spannable - person user924; 27.10.2017
comment
автор имел в виду staticlayout, но, похоже, ваш пример для TextView, верно? - person user924; 27.10.2017