Новый выбираемый TextView в Android 3 (API <=11) компонент

После долгого и трудоемкого поиска я не могу найти компонент, который может выделять текст в textview для уровня Android API <=11. Я написал этот компонент, который может быть вам полезен:

public class SelectableTextView extends TextView {

public static int _SelectedBackgroundColor = 0xffA6D4E1;
public static int _SelectedTextColor = 0xff000000;
private OnTouchListener lastOnTouch;
protected int textOffsetStart;
protected int textOffsetEnd;
private OnLongClickListener lastOnLongClick;
protected boolean longCliked;
protected boolean isDowned;
protected int textSelectedEnd;
protected int textSelectedStart;
private static SelectableTextView lastInstance;

public SelectableTextView(Context context) {
    super(context);
}

public void setTextIsSelectable(boolean selectable) {
    // TODO:ANDROID3
    // if:androidversion>=3
    // super.setTextIsSelectable(selectable);
    // else
    super.setLongClickable(true);
    super.setOnLongClickListener(getSelectableLongClick());
    super.setOnTouchListener(getSelectableOnTouch());
}

private OnLongClickListener getSelectableLongClick() {
    return new OnLongClickListener() {

        @Override
        public boolean onLongClick(View v) {
            longCliked = true;
            if (lastOnLongClick != null) {
                lastOnLongClick.onLongClick(v);
            }
            return true;
        }
    };
}

@Override
public void setOnTouchListener(OnTouchListener l) {
    super.setOnTouchListener(l);
    this.lastOnTouch = l;
}

@Override
public void setOnLongClickListener(OnLongClickListener l) {
    super.setOnLongClickListener(l);
    this.lastOnLongClick = l;
}

private OnTouchListener getSelectableOnTouch() {
    return new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            int action = event.getAction();

            if (action == MotionEvent.ACTION_DOWN) {
                if (lastInstance == null)
                    lastInstance = SelectableTextView.this;
                if (lastInstance != null && lastInstance != SelectableTextView.this) {
                    lastInstance.clean();
                    lastInstance = SelectableTextView.this;
                }

                int offset = getOffset(event);
                if ((offset < textOffsetEnd && offset > textOffsetStart)
                        || (offset > textOffsetEnd && offset < textOffsetStart)) {
                    if (textOffsetEnd - offset > offset - textOffsetStart)
                        textOffsetStart = textOffsetEnd;
                } else {
                    clean();
                    textOffsetStart = offset;
                }
                isDowned = true;
            } else if (isDowned && longCliked && action == MotionEvent.ACTION_MOVE) {
                selectTextOnMove(event);
            } else if (action == MotionEvent.ACTION_UP) {
                isDowned = false;
                longCliked = false;
            }
            if (lastOnTouch != null)
                lastOnTouch.onTouch(v, event);
            return false;
        }

    };
}

private void selectTextOnMove(MotionEvent event) {
    int offset = getOffset(event);
    if (offset != Integer.MIN_VALUE) {
        String text = getText().toString();
        SpannableStringBuilder sb = new SpannableStringBuilder(text);
        BackgroundColorSpan bgc = new BackgroundColorSpan(_SelectedBackgroundColor);
        ForegroundColorSpan textColor = new ForegroundColorSpan(_SelectedTextColor);

        int start = textOffsetStart;
        textOffsetEnd = offset;
        int end = offset;
        if (start > end) {
            int temp = start;
            start = end;
            end = temp;
        }
        int[] curectStartEnd = curectStartEnd(text, start, end);
        start = curectStartEnd[0];
        end = curectStartEnd[1];
        SelectableTextView.this.textSelectedStart = start;
        SelectableTextView.this.textSelectedEnd = end;
        sb.setSpan(bgc, start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
        sb.setSpan(textColor, start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);

        setText(sb);
    }
}

private int[] curectStartEnd(String text, int start, int end) {
    int length = text.length();

    while (start < length && start > 0 && text.charAt(start) != ' ') {
        start--;
    }
    while (end < length && text.charAt(end) != ' ') {
        end++;
    }
    return new int[] { start, end };
}

private int getOffset(MotionEvent event) {
    Layout layout = getLayout();
    if (layout == null)
        return Integer.MIN_VALUE;
    float x = event.getX() + getScrollX();
    float y = event.getY() + getScrollY();
    int line = layout.getLineForVertical((int) y);
    int offset = layout.getOffsetForHorizontal(line, x);
    return offset;
}

protected void clean() {
    if (this.getText() != null) {
        this.setText(this.getText().toString());
        textSelectedStart = 0;
        textSelectedEnd = 0;
    }
}

@Override
public int getSelectionStart() {
    return textSelectedStart;
}

@Override
public int getSelectionEnd() {
    return textSelectedEnd;
}

}

getOffset получить выбранное смещение текста, который пользователь Touched для использования этого компонента устанавливает эти атрибуты:

        SelectableTextView textView1 = new SelectableTextView(context);
    textView1.setClickable(false);
    textView1.setCursorVisible(false);
    textView1.setOnTouchListener(getOnTextTouch());//new after text select touch
    textView1.setEnabled(this.selectable);
    textView1.setTextIsSelectable(this.selectable);

Кто-нибудь может обновить этот компонент?

Это код в git hub

1 ответ

Также добавьте следующие два конструктора из-за этого

    public SelectableTextView(Context context,AttributeSet attrs)
{
    super(context,attrs);
}

public SelectableTextView(Context context,AttributeSet attrs,int defStyle)
{
    super(context,attrs,defStyle);
}

Я также добавил следующее в код:

    @SuppressLint("NewApi")
public void setTextIsSelectable(boolean selectable) {
    if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB)
        super.setTextIsSelectable(true);
    else
    {   
        super.setLongClickable(true);
        super.setOnLongClickListener(getSelectableLongClick());
        super.setOnTouchListener(getSelectableOnTouch());
    }
}

Я использовал это так, без OnTouchListener:

txt_copyFrom.setClickable(false);
txt_copyFrom.setCursorVisible(false);
txt_copyFrom.setEnabled(true);
txt_copyFrom.setTextIsSelectable(true);
txt_copyFrom.setOnLongClickListener(new OnLongClickListener(){

    @Override
    public boolean onLongClick(View v) {
        int start=txt_copyFrom.getSelectionStart();
        int end=txt_copyFrom.getSelectionEnd();

        mSelectedText=txt_copyFrom.getText().toString().substring(start, end);
        Log.d(TAG, "Selected text: "+mSelectedText);
        return true;
    }

});

с XML:

<com.example.clipboardtest.SelectableTextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Old Buccaneer1The Old Sea-dog at the Admiral BenbowSquire Trelawney, Dr. Livesey, and the rest of these gentlemen having asked me to write down the whole particulars about Treasure Island, from the beginning to the end, keeping nothing back but the bearings of the island, and that only because there is still treasure not yet lifted, I take up my pen in the year of grace 17--and go back to the time when my father kept the Admiral Benbow inn and the brown old seaman with the sabre cut first took up his lodging under our roof."
    android:id="@+id/txt_copyfrom"
/>         

Я думаю, я должен установить OnTouchListener в пределах OnLongClickListener для TextView в самой деятельности.

Попытка поместить журналы повсюду в SelectableTextView, он, кажется, не работает... Я обнаружил, что LongClickListener вызывается, но TouchListener даже не вызывается...

Установка OnTouchListener внутри OnLongClickListener сделала это

Другие вопросы по тегам