سؤال

انا املك TextView مع ال OnTouchListener. ما أريده هو فهرس الحرف الذي يشير إليه المستخدم عندما أحصل على MotionEvent. هل هناك أي طريقة للوصول إلى مقاييس الخطوط الأساسية لـ TextView?

هل كانت مفيدة؟

المحلول

لست على دراية بالطريقة المباشرة البسيطة للقيام بذلك ، لكن يجب أن تكون قادرًا على تجميع شيء ما باستخدام رسم كائن من TextView عبر مكالمة إلى TextView.getPaint ()

بمجرد حصولك على كائن الطلاء ، ستتمكن من الوصول إلى fontmetrices الأساسية عبر مكالمة إلى paint.getFontMetrics () والوصول إلى وظائف أخرى مثل paint.measureText () paint.getTextBounds () ، و paint.gettextwidths () للوصول إلى الحجم الفعلي للنص المعروض.

نصائح أخرى

هل حاولت شيء من هذا القبيل:

Layout layout = this.getLayout();
if (layout != null)
{
    int line = layout.getLineForVertical(y);
    int offset = layout.getOffsetForHorizontal(line, x);

    // At this point, "offset" should be what you want - the character index
}

أتمنى أن يساعدك هذا...

في حين أنه يعمل عمومًا ، واجهت بعض المشكلات في الإجابة من توني بلوز.

أولاً getOffsetForhorizontal إرجاع الإزاحة حتى لو كان إحداثيات X هو أبعد من الطابع الأخير للخط.

ثانياً ، ينتمي إزاحة الحرف التي تم إرجاعها في بعض الأحيان إلى الحرف التالي ، وليس الحرف أسفل المؤشر مباشرة. يبدو أن الطريقة تُرجع إزاحة أقرب موضع المؤشر. قد يكون هذا إلى اليسار أو إلى يمين الشخصية اعتمادًا على ما هو أقرب.

يستخدم الحل getPrimaryhorizontal بدلاً من ذلك ، لتحديد موضع المؤشر لإزاحة معينة ويستخدم البحث الثنائي للعثور على الإزاحة أسفل إحداثيات المؤشر X.

public static int getCharacterOffset(TextView textView, int x, int y) {
    x += textView.getScrollX() - textView.getTotalPaddingLeft();
    y += textView.getScrollY() - textView.getTotalPaddingTop();

    final Layout layout = textView.getLayout();

    final int lineCount = layout.getLineCount();
    if (lineCount == 0 || y < layout.getLineTop(0) || y >= layout.getLineBottom(lineCount - 1))
        return -1;

    final int line = layout.getLineForVertical(y);
    if (x < layout.getLineLeft(line) || x >= layout.getLineRight(line))
        return -1;

    int start = layout.getLineStart(line);
    int end = layout.getLineEnd(line);

    while (end > start + 1) {
        int middle = start + (end - start) / 2;

        if (x >= layout.getPrimaryHorizontal(middle)) {
            start = middle;
        }
        else {
            end = middle;
        }
    }

    return start;
}

تحرير: يعمل هذا الإصدار المحدث بشكل أفضل مع فواصل الخط غير الطبيعية ، عندما لا تتناسب كلمة طويلة في خط وتتم تقسيمها في مكان ما في الوسط.

تحذيرات: في النصوص الواصلة ، النقر على الواصلة في نهاية السطر ، إرجاع فهرس الحرف المجاور له. أيضا هذه الطريقة لا تعمل بشكل جيد مع نصوص RTL.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top