2013-08-04 2 views
8

오랜 시간이 소요되는 검색 후 안드로이드 API 레벨 < = 11에 대한 textview에서 텍스트를 선택할 수있는 구성 요소를 찾을 수 없습니다.new 선택 가능한 TextView in android 3 (API <= 11) 구성 요소

 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); 

사람이 구성 요소를 업그레이드 할 수 있습니다

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이 설정 이러한 특성이 구성 요소를 사용하는 사용자를 감동 텍스트의 오프셋 (offset) 선택된 얻을 : 내가 당신에게 도움이 될 수도 있습니다 구성 요소를 작성했습니다 ? 없이

@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()); 
    } 
} 

내가 이런 식으로 그것을 사용 : 또한

This is the code in git hub

답변

3

때문에 this

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

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

의 다음과 같은 두 가지 생성자를 추가 나는 또한 코드에 다음을 추가 한 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" 
/>   

은 내가 활동 자체에 텍스트 뷰의 OnLongClickListenerOnTouchListener을 설정해야 할 것 같아요.

모든 SelectableTextView에서 여기 저기 로그를 넣어 시도, 그것은 ... 나는 ...

내부의 OnTouchListener를 설정 LongClickListener가 호출되지만 TouchListener도 호출되지 것을 발견 작동하는 보이지 않는 OnLongClickListener 않았다 this