[Java for Android App Development] vamsiampolu:
I would like to select text from a textview,partially that is for Gingerbread as well as higher platforms,I find that android:textIsSelectable is not available and the WebView workaround only does it for complete text,I have tried to use pre-baked code to do this by extending a TextView:

public class SelectableTextView extends TextView {

final String TAG="SelectableTextView";

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 SelectableTextView(Context context,AttributeSet attrs)

{

super(context,attrs);

}

public SelectableTextView(Context context,AttributeSet attrs,int defStyle)

{

super(context,attrs,defStyle);

}

[MENTION=5448622]Suppress[/MENTION]Lint("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());

}

}

private OnLongClickListener getSelectableLongClick() {

return new OnLongClickListener() {

[MENTION=439709]override[/MENTION]

public boolean onLongClick(View v) {

longCliked = true;

if (lastOnLongClick != null) {

lastOnLongClick.onLongClick(v);

}

return true;

}

};

}

[MENTION=439709]override[/MENTION]

public void setOnTouchListener(OnTouchListener listener) {

super.setOnTouchListener(listener);

this.lastOnTouch = listener;

}

[MENTION=439709]override[/MENTION]

public void setOnLongClickListener(OnLongClickListener listener) {

super.setOnLongClickListener(listener);

Log.d(TAG, "Setting touch listener in long click");

this.lastOnLongClick = listener;

// this.setOnTouchListener(getSelectableOnTouch());

}

private OnTouchListener getSelectableOnTouch() {

return new OnTouchListener() {

[MENTION=439709]override[/MENTION]

public boolean onTouch(View v, MotionEvent event) {

Log.d(TAG, "In SelectableTextView OnTouchListener");

int action = event.getAction();

if (action == MotionEvent.ACTION_DOWN) {

Log.d(TAG, "Finger down on the TextView");

if (lastInstance == null)

lastInstance = SelectableTextView.this;

if (lastInstance != null && lastInstance != SelectableTextView.this) {

lastInstance.clean();

lastInstance = SelectableTextView.this;

}

int offset = getOffset(event);

Log.d(TAG, "Selection starts at: "+offset);

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

Log.d(TAG, "Selecting text");

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

Log.d(TAG, "Selection text on ACTION_MOVE");

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;

Log.d(TAG,"Start: "+start+"and End: "+end);

if (start > end) {

int temp = start;

start = end;

end = temp;

Log.d(TAG, "Interchanging Start: "+start+" and End: "+end);

}

int[] curectStartEnd = curectStartEnd(text, start, end);

start = curectStartEnd[0];

end = curectStartEnd[1];

Log.d(TAG, "Corrected start and end,Start: "+start+" and End: "+end+".These values are final");

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

this.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) {

Log.d(TAG,"Get offset method");

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

Log.d(TAG, "Obtaining line "+line);

int offset = layout.getOffsetForHorizontal(line, x);

return offset;

}

protected void clean() {

String gotText=this.getText().toString();

if (gotText != null) {

this.setText(gotText);

textSelectedStart = 0;

textSelectedEnd = 0;

}

}

[MENTION=439709]override[/MENTION]

public int getSelectionStart() {

return textSelectedStart;

}

[MENTION=439709]override[/MENTION]

public int getSelectionEnd() {

return textSelectedEnd;

}

}

This is how I am using it:

txt_copyFrom.setClickable(false);

txt_copyFrom.setCursorVisible(true);

txt_copyFrom.setEnabled(true);

txt_copyFrom.setTextIsSelectable(true);

txt_copyFrom.setOnLongClickListener(new OnLongClickListener(){

[MENTION=439709]override[/MENTION]

public boolean onLongClick(View v) {

Log.d(TAG, "On LongClick Listener");

int start=txt_copyFrom.getSelectionStart();

int end=txt_copyFrom.getSelectionEnd();

if(start>end)

{

//I guess the SelectableTextView fixes this:

start=start+end;

end=start=end;

start=start-end;

}

mSelectedText=txt_copyFrom.getText().toString().substring(start, end);

Log.d(TAG, "Selected text: "+mSelectedText);

return true;

}});

I get a StackOverflowError:

It repeatedly prints the message:

SelectableTextView(12712): In SelectableTextView OnTouchListener

SelectableTextView(12712): Finger down on the TextView

SelectableTextView(12712): Get offset method

SelectableTextView(12712): Obtaining line 4

SelectableTextView(12712): Selection starts at: 205

Followed by:

AndroidRuntime(12712): FATAL EXCEPTION: main

AndroidRuntime(12712): java.lang.StackOverflowError

AndroidRuntime(12712): at android.text.MeasuredText.addStyleRun(MeasuredText.java:164)

AndroidRuntime(12712): at android.text.MeasuredText.addStyleRun(MeasuredText.java:204)

at android.text.StaticLayout.generate(StaticLayout.java:281)

AndroidRuntime(12712): at android.text.DynamicLayout.reflow(DynamicLayout.java:284)

AndroidRuntime(12712): at android.text.DynamicLayout.<init>(DynamicLayout.java:170)

AndroidRuntime(12712): at android.widget.TextView.makeSingleLayout(TextView.java:6044)

AndroidRuntime(12712): at android.widget.TextView.makeNewLayout(TextView.java:5942)

AndroidRuntime(12712): at android.widget.TextView.checkForRelayout(TextView.java:6481)

AndroidRuntime(12712): at android.widget.TextView.setText(TextView.java:3764)

AndroidRuntime(12712): at android.widget.TextView.setText(TextView.java:3622)

AndroidRuntime(12712): at android.widget.TextView.setText(TextView.java:3597)

AndroidRuntime(12712): at com.example.clipboardtest.SelectableTextView.clean(SelectableTextView.java:185)

This happens to be:this.setText(this.getText().toString());

This is followed by:

AndroidRuntime(12712): at com.example.clipboardtest.SelectableTextView$2.onTouch(SelectableTextView.java:108)

This is,as expected: clean();

Then this occurs repeatedly:

AndroidRuntime(12712): at com.example.clipboardtest.SelectableTextView$2.onTouch(SelectableTextView.java:120)

which is `lastOnTouch.onTouch(v, event);`

I guess this is because we retain the OnLongClick and OnTouchListener.

Also the code calls for selection of stuff using a background colour and foreground color:

SpannableStringBuilder sb = new SpannableStringBuilder(text);

BackgroundColorSpan bgc = new BackgroundColorSpan(_SelectedBackgroundColor);

ForegroundColorSpan textColor = new ForegroundColorSpan(_SelectedTextColor);

sb.setSpan(bgc, start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);

sb.setSpan(textColor, start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);

setText(this);

I do not understand why this implementation does not chain to the superclass implementation like I specifically asked it to.Is there anything else I can do,any approach I can follow to make it work,is there a pre-implemented version I can use.If there is nothing can you guide me through implementing a custom TextView for Android