繁体   English   中英

如何在android TextView中获取点击跨度的x,y位置?

[英]How to get x,y position of clicked span in android TextView?

我有一个可跨越的 Textview。 我想在TextView内的选定跨度顶部显示弹出窗口。 像这样:

在此处输入图片说明

我的代码是:

String definition = textView.getText().toString().trim();
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setText(definition, TextView.BufferType.SPANNABLE);

Spannable spans = (Spannable) textView.getText();
Integer[] indices = getIndices(
  textView.getText().toString(), ' ');
int start = 0;
int end = 0;

for (int i = 0; i <= indices.length; i++) {
  ClickableSpan clickSpan = getClickableSpan();
  end = (i < indices.length ? indices[i] : spans.length());
  spans.setSpan(clickSpan, start, end,
    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
  start = end + 1;
  }

private Integer[] getIndices(String s, char c) {
int           pos     = s.indexOf(c, 0);
List<Integer> indices = new ArrayList<Integer>();
while (pos != -1) {
  indices.add(pos);
  pos = s.indexOf(c, pos + 1);
}
return (Integer[]) indices.toArray(new Integer[0]);
}

private ClickableSpan getClickableSpan() {
return new ClickableSpan() {
  @SuppressLint("ClickableViewAccessibility")
  @Override
  public void onClick(View widget) {
    TextView tv = (TextView) widget;
    final String word = tv
            .getText()
            .subSequence(tv.getSelectionStart(),
                    tv.getSelectionEnd()).toString();

    tv.setOnTouchListener(new OnTouchListener() {
      @Override
      public boolean onTouch(View v, MotionEvent event) {
        popup(word, (int) event.getRawX(), (int) event.getRawY());
        return false;
      }
    });

  }

};
}

正如您在图像代码中看到的那样,但由于在 android 中的onClick之前调用了onTouch ,弹出窗口显示了在上一步中单击的单词。 抱歉可能英语不好。

        val parentTextViewRect = Rect()
        val textViewLayout = parentTextView.layout
        val startXCoordinatesOfClickedText = textViewLayout.getPrimaryHorizontal(spanStart).toDouble()
        val endXCoordinatesOfClickedText = textViewLayout.getPrimaryHorizontal(spanEnd).toDouble()

        val currentLineStartOffset = textViewLayout.getLineForOffset(spanStart)
        val currentLineEndOffset = textViewLayout.getLineForOffset(spanEnd)

        // 文本是否跨行
        val keywordIsInMultiLine = currentLineStartOffset != currentLineEndOffset
        textViewLayout.getLineBounds(currentLineStartOffset, parentTextViewRect)

        // 屏幕中的真实位置
        val parentTopAndBottomOffset = parentTextView.top + parentTextView.paddingTop
        parentTextViewRect.top += parentTopAndBottomOffset
        parentTextViewRect.bottom += parentTopAndBottomOffset

        val parentLeftOffset = parentTextView.left + parentTextView.paddingLeft
        parentTextViewRect.left += (parentLeftOffset + startXCoordinatesOfClickedText).toInt()
        parentTextViewRect.right = (parentTextViewRect.left + endXCoordinatesOfClickedText - startXCoordinatesOfClickedText).toInt()

        var spanTextLeft = if (keywordIsInMultiLine) {
            parentTextViewRect.left
        } else {
            (parentTextViewRect.left + parentTextViewRect.right) / 2
        }
        val spanTextTop = parentTextViewRect.top
        Log.d("MainActivity", "spanTextLeft = $spanTextLeft")
        Log.d("MainActivity", "spanTextTop = $spanTextTop")

要获得xy您可以设置OnTouchListener来注册点击事件

在 Java 中

private void setOnTouchListener() {
    textView.setOnTouchListener((view, event) -> {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            float clickedX = event.getX();
            float clickedY = event.getY();
        }

        return false;
    });
}

在科特林

private fun setOnTouchListener() {
    text_view.setOnTouchListener { view, event ->
        if (event?.action == MotionEvent.ACTION_DOWN) {
            val clickedX = event.x
            val clickedY = event.y
        }

        false
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM