2012-07-22 1 views
19

基本的には、テキストのパス(実際にはかなり長いテキスト)を表示し、ユーザーが任意の単語をクリックできるようにします。その時点で、私は彼らがクリックした単語を決定したいと思う。私はまた、単語が出現する文全体を取得したい(これは、単語がテキスト内のどの位置にあるかを判断できると仮定すると、これはかなり簡単です)。アンドロイドのテキストビューでどの単語をクリックするか決定する

理想的には、私はちょうど、onTouchイベントをリッスンXとYを取得し、textView.wordAt(event.x, event.y)またはtextView.cursorPositionNearest(event.x, event.y)のようなものを言うが、それは

私の現在の最善の努力を使用することを伴うので、簡単に:-)ではないと思われるでしょうTextViewと1つ作成するClickableSpan 1語につき。それは動作しますが、それはまったくエレガントではありません。長い文章で使うとメモリを食べ始めるでしょう。

private final String text = "This is the text"; 
private TextView textView; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_text_view); 

    textView = (TextView) findViewById(R.id.text_view); 

    SpannableString ss = new SpannableString(text); 
    // create spans for "this", "is", "the" and "text" 
    ss.setSpan(new IndexedClickableSpan(0, 4), 0, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 
    ss.setSpan(new IndexedClickableSpan(5, 7), 5, 7, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 
    ss.setSpan(new IndexedClickableSpan(8, 11), 8, 11, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 
    ss.setSpan(new IndexedClickableSpan(12, 16), 12, 16, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 

    textView.setText(ss); 
} 

private final class IndexedClickableSpan extends ClickableSpan { 

    int startIndex, endIndex; 

    public IndexedClickableSpan(int startIndex, int endIndex) { 
     this.startIndex = startIndex; 
     this.endIndex = endIndex; 
    } 

    @Override 
    public void onClick(View widget) { 
     String word = TextViewActivity.this.text.substring(startIndex, endIndex); 
     Toast.makeText(TextViewActivity.this, "You clicked on " + word, Toast.LENGTH_SHORT).show(); 
    } 
} 

もっと良いアイデアがあれば、私はそれを聞いてみたいです。事前に

おかげで、 デイブ

ない私は本当にstackoverflowの上の質問に答えることになってんだけど、私はAndroidの15 APIのうち、いくつかのコードをリッピングして行うことは非常にわずかにそれを修正することができたかどうかはわかり私は必要なもの。 Dheerajに提案していただきありがとうございます。

新しいコードは、私が感動した言葉を得ることができる必要があり、そこから私は、タッチイベントの位置に基づいて、キャレット位置を取得することができ、それがコードで表示される文章が添付:。

public int getOffsetForPosition(TextView textView, float x, float y) { 
    if (textView.getLayout() == null) { 
     return -1; 
    } 
    final int line = getLineAtCoordinate(textView, y); 
    final int offset = getOffsetAtCoordinate(textView, line, x); 
    return offset; 
} 

private int getOffsetAtCoordinate(TextView textView2, int line, float x) { 
    x = convertToLocalHorizontalCoordinate(textView2, x); 
    return textView2.getLayout().getOffsetForHorizontal(line, x); 
} 

private float convertToLocalHorizontalCoordinate(TextView textView2, float x) { 
    x -= textView2.getTotalPaddingLeft(); 
    // Clamp the position to inside of the view. 
    x = Math.max(0.0f, x); 
    x = Math.min(textView2.getWidth() - textView2.getTotalPaddingRight() - 1, x); 
    x += textView2.getScrollX(); 
    return x; 
} 

private int getLineAtCoordinate(TextView textView2, float y) { 
    y -= textView2.getTotalPaddingTop(); 
    // Clamp the position to inside of the view. 
    y = Math.max(0.0f, y); 
    y = Math.min(textView2.getHeight() - textView2.getTotalPaddingBottom() - 1, y); 
    y += textView2.getScrollY(); 
    return textView2.getLayout().getLineForVertical((int) y); 
} 

答えて

10

APIレベル14+をターゲティングする場合は、getOffsetForPosition()を使用できます。

以前のAndroidバージョンの場合、このメソッドのコードをAndroidソースからコピーして独自のTextViewを拡張できるかどうかを確認してください。

+0

有望な音。私はAPI 14以前ですが、うまくいけばコードからそれを得ることができるはずです。ありがとうDheeraj –

+2

ありがとうDheeraj。私はコードを外して、それは非常にうまく動作します。 –

関連する問題