I have a problem with an EditText where gravity is set to center. Because of that I had to put the attribute android:ellipsize="start" for the hint to appear in the center.
However, the hint appears before the cursor, which gives a rather ugly appearance to the application:
What I want to do is display the cursor before the text. Any suggestions for this?
I have 3 solution,infact that are 2 way.One side when text is empty that need to dispay hint,we hide the hint either show,Another side is adjust cursor(widgit) location.precondition is EditText put in a layout,adjust edittext's layout gravity not it's self gravity.But my demand is before hint,you just gravity to right.
like this pic:
enter image description here
#Override
public void onFocusChange(View v, boolean hasFocus) {
adjustCursorPosition(etInput.getText());
}
#Override
public void afterTextChanged(Editable s) {
adjustCursorPosition(etInput.getText());
}
private void adjustCursorPosition(CharSequence text){
if (!TextUtils.isEmpty(etInput.getHint())){
adjustGravityForCursor(text);
//adjustCursorVisible(text);
//adjustHintContent(hasFocus(),text);
}
}
private void adjustHintContent(boolean hasFocus, CharSequence text){
if (TextUtils.isEmpty(text)) {
etInput.setHint(hasFocus ? "" : mHint);
}
}
private void adjustCursorVisible(CharSequence text){
etInput.setCursorVisible(!TextUtils.isEmpty(text));
}
private void adjustGravityForCursor(CharSequence text) {
LayoutParams lp = (LayoutParams) etInput.getLayoutParams();
if (mSpaceWidth <= 0) mSpaceWidth = lp.width;
if (!TextUtils.isEmpty(text)) {
etInput.setGravity(Gravity.CENTER);
lp.leftMargin = 0;
} else {
etInput.setGravity(Gravity.LEFT);
lp.leftMargin = (mSpaceWidth - measureText(etInput,mHint)) / 2;
}
etInput.setLayoutParams(lp);
}
I think you can use the setSelection method of the EditText, as per this thread.
The quickest solution will be to clear hint on editText Touch: (I have assumed this edittext to be MYET).
First, set an onTouch listener for MYET.
Then , onTouch, return TRUE(instread of false).
After that, onTouch, use MYET.setHint(""); This will clear the hint.
Here is the code :
MYET.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
MYET.setHint("");
return true;
}
});
note:
If the setHint("") does not work, you can use MYET.setText("");
Related
I have this code:
final ViewTreeObserver[] viewTreeObserver = {myAcco
viewTreeObserver[0].addOnPreDrawListener(
new OnPreDrawListener() {
#Override
public boolean onPreDraw() {
int chipWidth =
myAccountView.getMeasuredWidth()
- myAccountView.getPaddingLeft()
- myAccountView.getPaddingRight();
if (chipWidth > 0) {
myAccountView.setText(
setChipTextWithCorrectLength(
getContext().getString(R.string.og_my_account_desc_long_length),
getContext().getString(R.string.og_my_account_desc_meduim_length),
getContext().getString(R.string.og_my_account_desc_short_length),
chipWidth));
viewTreeObserver[0] = myAccountView.getViewTreeObserver();
if (viewTreeObserver[0].isAlive()) {
viewTreeObserver[0].removeOnPreDrawListener(this);
}
}
return true;
}
});
}
#VisibleForTesting
String setChipTextWithCorrectLength(
String longDesc, String mediumDesc, String shortDesc, int clipWidth) {
if (!isTextEllipsized(longDesc, clipWidth)) {
return longDesc;
}
if (!isTextEllipsized(mediumDesc, clipWidth)) {
return mediumDesc;
}
return shortDesc;
}
private boolean isTextEllipsized(String text, int clipWidth) {
TextPaint textPaint = myAccountView.getPaint();
Toast.makeText(this.getContext(), "textPaint.measureText(text) = "+textPaint.measureText(text)+" clipWidth ="+ clipWidth,
Toast.LENGTH_LONG).show();
return textPaint.measureText(text) > clipWidth;
}
The code should change the text in a textView dynamically when ellipsize is needed.
However, when i run the application I see sometimes the view (clip) width == the long text width and there is still ellipsize in the UI.
I see that happens when the textView is not visible and toggeled to be visible.
Should I calculate the vlip (view) width differently?
Any special way to measure textView before becomes visible?
You should check with
getEllipsisCount()
to see the source of the problem.
Definition : Returns the number of characters to be ellipsized away, or 0 if no ellipsis is to take place.
Yes you can use textView.getLayout().getEllipsisStart(0) ,make sure your textView is singleline , you can do this by adding android:maxLines="1" to your texView. It return the index from which the text gets truncated else returns 0.
Depending on your observation , it might be that the view is not recalculating after changing the visibility to visible again, try to use textView.setVisibility(View.GONE) instead of textView.setVisibility(View.INVISIBLE); .This might cause the preDraw() to be called again.
You might also consider using addOnGlobalLayoutListener() to keep the track of visibilty changes of your view, for reference.
I am new to android development, so please excuse the naivety of the post. I have a table layout in which i am dynamically adding text view to each cell. I wish to add a swipe detection on the cells and perform an action on the basis of which cell was swiped. I tried adding a onSwipeTouchListener on each of the cell.
TextView txtviewCell = new TextView(getActivity());
TableRow.LayoutParams paramsExample = new TableRow.LayoutParams(60, 60);
txtviewCell.setBackgroundColor(0xfffaf8ef);
txtviewCell.setGravity(Gravity.CENTER);
paramsExample.setMargins(5, 5, 5, 5);
txtviewCell.setLayoutParams(paramsExample);
final int currRow = i;
final int currCol = j;
txtviewCell.setOnTouchListener(new OnSwipeTouchListener(
getActivity()) {
public void onSwipeTop() {
handleSwipe(currRow, currCol);
}
public void onSwipeRight() {
handleSwipe(currRow, currCol);
}
public void onSwipeLeft() {
handleSwipe(currRow, currCol);
}
public void onSwipeBottom() {
handleSwipe(currRow, currCol);
}
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
});
allCells[i][j] = txtviewCell;
Now when i swipe i get the control in onSwipe function, but i do not get the correct row number and col number. Is there a specific way to attach a swipe event on a textview and get the row number and col number of that cell?
I guess every textview has different ID, so try getting the id and making a control flow with it.
I want to to have some validation for my EditText wherein I want to show "" icon (that comes when you put editText.setError("blah blah")) but don't want the text in the popup displaying that "blah blah".
Is there any way to do it? One way is to create a custom layout which will show the image icon in the EditText. But is there any better solution?
Problem solved after a lot of research and permutations- (Also thanks to #van)
Create a new class that will extend EditText something like this-
public class MyEditText extends EditText {
public MyEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public void setError(CharSequence error, Drawable icon) {
setCompoundDrawables(null, null, icon, null);
}
}
Use this class as a view in your xml like this-
<com.raj.poc.MyEditText
android:id="#+id/et_test"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
Now in the third step, just set a TextWatcher to your custom text view like this-
et = (MyEditText) findViewById(R.id.et_test);
errorIcon = getResources().getDrawable(R.drawable.ic_error);
errorIcon.setBounds(new Rect(0, 0, errorIcon.getIntrinsicWidth(), errorIcon.getIntrinsicHeight()));
et.setError(null,errorIcon);
et.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable s) {
if(s.toString().length()>6){
et.setError("", null);
}else{
et.setError("", errorIcon);
}
}
});
where R.drawable.ic_error =
Keeping text null solves the problem
But if we keep only null in setError(null), this won't show the validation error; it should be null along with second param.
You dont need to create a new EditText class or change xml. The solution is very simple:
Edittext editText= (EditText) rootView.findViewById(R.id.email);
String str= editText.getText().toString();
if(str.equalsIgnoreCase("") ){
Drawable dr = getResources().getDrawable(R.drawable.error);
//add an error icon to yur drawable files
dr.setBounds(0, 0, dr.getIntrinsicWidth(), dr.getIntrinsicHeight());
editText.setCompoundDrawables(null,null,dr,null);
}
Sorry Rajkiran, but your solution is not working on Android 4.2 version. If I am trying to set null value for error, it is not even displayed. The solution I came up was to extend EditText and override setError method. No I have only error indicator without popup.
#Override
public void setError(CharSequence pError, Drawable pIcon) {
setCompoundDrawables(null, null, pIcon, null);
}
I have been dealing with the same problem. I wanted to use .setError() to my EditText when user insert null input. But I think the pop-out message is annoying, especially when you have more EditTexts.
My solution was naive and simple, but it worked on all devices I've tried so far.
I created my own class myEditText and just #Override this method:
#Override
public void setError(CharSequence error, Drawable icon) {
setCompoundDrawables(null, null, icon, null);
}
then use in layout.xml
<cz.project.myEditText
...
/>
and finally in my code
I put onFocusChangeListener to myEditText, so when someone clicks-in, the icon disappears.
myEditText input = (myEditText) findViewById(R.id.input);
input.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
input.setError(null);
});
if(val == null) input.setError("");
It works Exactly how I want = no pop-up message when .setError() is called on EditText.
To get only the error-icon without an error-message-popup only when setError("") is called (i.e. set an empty String as error-message) I use a custom EditText-class where I override setError(CharSequence, Drawable) like this:
#Override
public void setError(CharSequence error, Drawable icon) {
if (error == null) {
super.setError(null, icon);
setCompoundDrawables(null, null, null, null);
}
else if (error.toString().equals("")) setCompoundDrawables(null, null, icon, null);
else super.setError(error, icon);
}
Everything else stays the same:
Use setError(null) to get neither the icon nor the message-popup.
Use setError(errorMessage), where errorMessage is a String with length 1 at least, to get the icon and message-popup.
This is the very useful when you want to show the error messages for the edittext field when the user enter wrong information.this is very simply program only you have to use serError() method in the edittext.
Step 1:
Create button and implement onclickListener.
btnLogin.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
});
Step 2:
Validate the input fields and set the error in the input field.
if(edName.length()>3){
if(edNumber.length()>3){
Toast.makeText(getApplicationContext(), "Login success", Toast.LENGTH_SHORT).show();
}else{
edNumber.setError("Number Mininum length is 4");
}
}else{
edName.setError("Name Mininum length is 4");
}
Refer this link for more:http://velmuruganandroidcoding.blogspot.in/2014/08/set-error-message-in-edittext-android.html
I want to make a read-only EditText view. The XML to do this code seems to be android:editable="false", but I want to do this in code.
How can I do this?
Please use this code..
Edittext.setEnabled(false);
If you setEnabled(false) then your editText would look disabled (gray, etc). You may not want to change the visual aspect of your editor.
A less intrusive way would be to use setFocusable(false).
I believe that this answers your question closer to your initial intent.
In XML use:
android:editable="false"
As an example:
<EditText
android:id="#+id/EditText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:editable="false" />
This works for me:
EditText.setKeyListener(null);
editText.setInputType(InputType.TYPE_NULL);
As per the docs this prevents the soft keyboard from being displayed. It also prevents pasting, allows scrolling and doesn't alter the visual aspect of the view. However, this also prevents selecting and copying of the text within the view.
From my tests setting setInputType to TYPE_NULL seems to be functionally equivalent to the depreciated android:editable="false". Additionally, android:inputType="none" seems to have no noticeable effect.
android:editable="false" has been deprecated. Therefore you cant use it to make the edit text readonly.
I have done this using the bellow solution. Here I have used
android:inputType="none"
android:textIsSelectable="true"
android:focusable="false"
Give it try :)
<EditText
android:id="#+id/et_newsgpa_university"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:hint="#string/hint_educational_institute"
android:textSize="#dimen/regular_text"
android:inputType="none"
android:textIsSelectable="true"
android:focusable="false"
android:maxLines="1"
android:imeOptions="actionNext"/>
The best is by using TextView instead.
editText.setEnabled(false);
editText.setFilters(new InputFilter[] { new InputFilter() {
public CharSequence filter(CharSequence src, int start, int end,
Spanned dst, int dstart, int dend) {
return src.length() < 1 ? dst.subSequence(dstart, dend) : "";
}
} });
This will give you uneditable EditText filter. you first need to put the text you want on the editText field and then apply this filter.
writing this two line is more than enough for your work.
yourEditText.setKeyListener(null);
yourEditText.setEnabled(false);
set in XML
android:inputType="none"
Try using
editText.setEnabled(false);
editText.setClickable(false);
Try overriding the onLongClick listener of the edit text to remove context menu:
EditText myTextField = (EditText)findViewById(R.id.my_edit_text_id);
myTextField.setOnLongClickListener(new OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
return true;
}
});
android:editable
If set, specifies that this TextView has an input method. It will be a textual one unless it has otherwise been specified. For TextView, this is false by default. For EditText, it is true by default.
Must be a boolean value, either true or false.
This may also be a reference to a resource (in the form #[package:]type:name) or theme attribute (in the form ?[package:][type:]name) containing a value of this type.
This corresponds to the global attribute resource symbol editable.
Related Methods
If you just want to be able to copy text from the control but not be able to edit it you might want to use a TextView instead and set text is selectable.
code:
myTextView.setTextIsSelectable(true);
myTextView.setFocusable(true);
myTextView.setFocusableInTouchMode(true);
// myTextView.setSelectAllOnFocus(true);
xml:
<TextView
android:textIsSelectable="true"
android:focusable="true"
android:focusableInTouchMode="true"
...
/>
<!--android:selectAllOnFocus="true"-->
The documentation of setTextIsSelectable says:
When you call this method to set the value of textIsSelectable, it sets the flags focusable, focusableInTouchMode, clickable, and longClickable to the same value...
However I had to explicitly set focusable and focusableInTouchMode to true to make it work with touch input.
Use this code:
editText.setEnabled(false);
editText.setTextColor(ContextCompat.getColor(context, R.color.black);
Disabling editText gives a read-only look and behavior but also changes the text-color to gray so setting its text color is needed.
this is my implementation (a little long, but useful to me!):
With this code you can make EditView Read-only or Normal. even in read-only state, the text can be copied by user. you can change the backgroud to make it look different from a normal EditText.
public static TextWatcher setReadOnly(final EditText edt, final boolean readOnlyState, TextWatcher remove) {
edt.setCursorVisible(!readOnlyState);
TextWatcher tw = null;
final String text = edt.getText().toString();
if (readOnlyState) {
tw = new TextWatcher();
#Override
public void afterTextChanged(Editable s) {
}
#Override
//saving the text before change
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
// and replace it with content if it is about to change
public void onTextChanged(CharSequence s, int start,int before, int count) {
edt.removeTextChangedListener(this);
edt.setText(text);
edt.addTextChangedListener(this);
}
};
edt.addTextChangedListener(tw);
return tw;
} else {
edt.removeTextChangedListener(remove);
return remove;
}
}
the benefit of this code is that, the EditText is displayed as normal EditText but the content is not changeable. The return value should be kept as a variable to one be able revert back from read-only state to normal.
to make an EditText read-only, just put it as:
TextWatcher tw = setReadOnly(editText, true, null);
and to make it normal use tw from previous statement:
setReadOnly(editText, false, tw);
This worked for me, taking several of the suggestions above into account. Makes the TextEdit focusable, but if user clicks or focuses, we show a list of selections in a PopupWindow. (We are replacing the wacky Spinner widget). TextEdit xml is very generic...
public void onCreate(Bundle savedInstanceState) {
....
fEditState = (EditText) findViewById(R.id.state_edit);
fEditState.setLongClickable(false);
fEditState.setKeyListener(null);
fEditState.setFocusable(true);
fEditState.setOnFocusChangeListener(new View.OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus)
{
if (hasFocus)
{
showStatesPopup();
}
}
});
fEditState.setOnClickListener(new Button.OnClickListener(){
public void onClick(View arg0)
{
showStatesPopup();
}
});
....
}
private void showStatesPopup()
{
// fPopupWindowStates instantiated in OnCreate()
if (!fPopupWindowStates.isShowing()) {
// show the list view as dropdown
fPopupWindowStates.showAsDropDown(fEditState, -5, 0);
}
}
This was the only full simple solution for me.
editText.setEnabled(false); // Prevents data entry
editText.setFocusable(false); // Prevents being able to tab to it from keyboard
As android:editable="" is deprecated,
Setting
android:clickable="false"
android:focusable="false"
android:inputType="none"
android:cursorVisible="false"
will make it "read-only". However, users will still be able to paste into the field or perform any other long click actions. To disable this, simply override onLongClickListener().
In Kotlin:
myEditText.setOnLongClickListener { true }
suffices.
My approach to this has been creating a custom TextWatcher class as follows:
class ReadOnlyTextWatcher implements TextWatcher {
private final EditText textEdit;
private String originalText;
private boolean mustUndo = true;
public ReadOnlyTextWatcher(EditText textEdit) {
this.textEdit = textEdit;
}
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if (mustUndo) {
originalText = charSequence.toString();
}
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
if (mustUndo) {
mustUndo = false;
textEdit.setText(originalText);
} else {
mustUndo = true;
}
}
}
Then you just add that watcher to any field you want to be read only despite being enabled:
editText.addTextChangedListener(new ReadOnlyTextWatcher(editText));
I had no problem making EditTextPreference read-only, by using:
editTextPref.setSelectable(false);
This works well when coupled with using the 'summary' field to display read-only fields (useful for displaying account info, for example). Updating the summary fields dynamically snatched from http://gmariotti.blogspot.com/2013/01/preferenceactivity-preferencefragment.html
private static final List<String> keyList;
static {
keyList = new ArrayList<String>();
keyList.add("field1");
keyList.add("field2");
keyList.add("field3");
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
for(int i=0;i<getPreferenceScreen().getPreferenceCount();i++){
initSummary(getPreferenceScreen().getPreference(i));
}
}
private void initSummary(Preference p) {
if (p instanceof PreferenceCategory) {
PreferenceCategory pCat = (PreferenceCategory) p;
for (int i = 0; i < pCat.getPreferenceCount(); i++) {
initSummary(pCat.getPreference(i));
}
} else {
updatePrefSummary(p);
}
}
private void updatePrefSummary(Preference p) {
if (p instanceof ListPreference) {
ListPreference listPref = (ListPreference) p;
p.setSummary(listPref.getEntry());
}
if (p instanceof EditTextPreference) {
EditTextPreference editTextPref = (EditTextPreference) p;
//editTextPref.setEnabled(false); // this can be used to 'gray out' as well
editTextPref.setSelectable(false);
if (keyList.contains(p.getKey())) {
p.setSummary(editTextPref.getText());
}
}
}
Set this in EdiTextView xml file
android:focusable="false"
in java file:
Edittext.setEnabled(false);
in xml file:
android:editable="false"
These 2 lines makes ur edittext selectable and at the same time not editable (it doesn't even show the soft keyboard):
editText.setInputType(InputType.TYPE_NULL);
editText.setTextIsSelectable(true);
I am using a TextView for which I have set autolink="web" property in XML file. I have also implemented the onClickListener for this TextView. The problem is, when the text in TextView contains a hyperlink, and if I touch that link, the link opens in browser but simultaneously the onClickListener triggers too. I don't want that.
What I want is, if I touch the hyperlink the clickListener should not fire. It should only fire if I touch the part of the text that is not hyperlinked. Any suggestion?
You can achieve this using a work around in getSelectionStart() and getSelectionEnd() functions of the Textview class,
tv.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ClassroomLog.log(TAG, "Textview Click listener ");
if (tv.getSelectionStart() == -1 && tv.getSelectionEnd() == -1) {
//This condition will satisfy only when it is not an autolinked text
//Fired only when you touch the part of the text that is not hyperlinked
}
}
});
It may be a late reply, but may be useful to those who are searching for a solution.
one of the #CommonsWare post helps to intercept autolink OnClick event.
private void fixTextView(TextView tv) {
SpannableString current = (SpannableString) tv.getText();
URLSpan[] spans =
current.getSpans(0, current.length(), URLSpan.class);
for (URLSpan span : spans) {
int start = current.getSpanStart(span);
int end = current.getSpanEnd(span);
current.removeSpan(span);
current.setSpan(new DefensiveURLSpan(span.getURL()), start, end,
0);
}
}
public static class DefensiveURLSpan extends URLSpan {
private String mUrl;
public DefensiveURLSpan(String url) {
super(url);
mUrl = url;
}
#Override
public void onClick(View widget) {
// openInWebView(widget.getContext(), mUrl); // intercept click event and do something.
// super.onClick(widget); // or it will do as it is.
}
}
Apply above code simply as below. It will go through all linkable texts and replace click events to above event handler.
fixTextView(textViewContent);
You can set the property android:linksClickable="false" in your TextView, in conjuction with android:autoLink="web"; this makes the links visible, but not clickable.
if you wish, you can use the next code which allows to customize the clickable links within the string ( based on this post ) :
usage:
final TextView textView = (TextView) findViewById(R.id.textView);
final Spanned text = Html.fromHtml(getString(...));
textView.setText(text);
textView.setMovementMethod(new LinkMovementMethodExt());
LinkMovementMethodExt.java
public class LinkMovementMethodExt extends LinkMovementMethod {
private static LinkMovementMethod sInstance;
public static MovementMethod getInstance() {
if (sInstance == null)
sInstance = new LinkMovementMethodExt();
return sInstance;
}
#Override
public boolean onTouchEvent(final TextView widget, final Spannable buffer, final MotionEvent event) {
final int action = event.getAction();
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {
final int x = (int) event.getX() - widget.getTotalPaddingLeft() + widget.getScrollX();
final int y = (int) event.getY() - widget.getTotalPaddingTop() + widget.getScrollY();
final Layout layout = widget.getLayout();
final int line = layout.getLineForVertical(y);
final int off = layout.getOffsetForHorizontal(line, x);
final ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
if (link.length != 0) {
//do something with the clicked item...
return true;
}
}
return super.onTouchEvent(widget, buffer, event);
}
}
Kotlin version:
Similar to older answers in Java. Simply:
In Layout Editor/XML, add the types of things you'd like to hyperlink via the autoLink property.
<TextView
...
android:autoLink="web|phone|email" />
Add an onClickListener to your TextView in Kotlin code to handle clicks on the plain text part. Check to make sure the person didn't click on a link by checking selectionStart and selectionEnd.
binding.messageText.setOnClickListener { view ->
if (binding.messageText.selectionStart == -1 && binding.messageText.selectionEnd == -1) {
// do whatever you want when they click on the plain text part
}
}
Use textView.getSelectionStart() and textView.getSelectionEnd().If u click any text other than link textView.getSelectionStart() and textView.getSelectionEnd() will be -1 .So by using a if condition in onClickListner you can block the onClick action when link is clicked .
//inside onClickListner
if(textView.getSelectionStart()==-1&&textView.getSlectionEnd==-1){
//onClick action
}
private void fixTextView(TextView tv) {
SpannableString current = (SpannableString) tv.getText();
URLSpan[] spans =
current.getSpans(0, current.length(), URLSpan.class);
for (URLSpan span : spans) {
int start = current.getSpanStart(span);
int end = current.getSpanEnd(span);
current.removeSpan(span);
current.setSpan(new DefensiveURLSpan(span.getURL()), start, end,
0);
}
}
public static class DefensiveURLSpan extends URLSpan {
public final static Parcelable.Creator<DefensiveURLSpan> CREATOR =
new Parcelable.Creator<DefensiveURLSpan>() {
#Override
public DefensiveURLSpan createFromParcel(Parcel source) {
return new DefensiveURLSpan(source.readString());
}
#Override
public DefensiveURLSpan[] newArray(int size) {
return new DefensiveURLSpan[size];
}
};
private String mUrl;
public DefensiveURLSpan(String url) {
super(url);
mUrl = url;
}
#Override
public void onClick(View widget) {
// openInWebView(widget.getContext(), mUrl); // intercept click event and do something.
// super.onClick(widget); // or it will do as it is.
}
}
You would then call fixTextView(textViewContent); on the view after it is declared (via inflation or findViewById) or added to the window (via addView)
This includes the missing requirement to set a CREATOR when extending a Parcelable.
It was proposed as an edit, but rejected. Unfortunately, now future users will have to find out the original one is incomplete first. Nice one, reviewers!
Instead of using a onClickListener, you can try this.
private void addLink() {
tvLink = (TextView) findViewById(R.id.tvInfo2);
String strURL = UrlLoader.getCodeUrl();
// Make the url string clicable and take action in its onclick
SpannableString spanUrl = SpannableString.valueOf(strURL);
spanUrl.setSpan(new InternalURLSpan(new OnClickListener() {
public void onClick(View v) {
//Do Some action
}
}), 0, spanUrl.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tvLink.setText(spanUrl);
// We probably also want the user to jump to your link by moving the
// focus (e.g. using the trackball), which we can do by setting the
// proper movement method:
MovementMethod m = tvLink.getMovementMethod();
if ((m == null) || !(m instanceof LinkMovementMethod)) {
if (tvLink.getLinksClickable()) {
tvLink.setMovementMethod(LinkMovementMethod.getInstance());
}
}
}
Also in the layout XML file , dont forget to add
<TextView android:layout_width="wrap_content" android:linksClickable="true"
android:layout_height="wrap_content" android:id="#+id/tvInfo2" android:text="#string/url_link" />
Just adding
textView.setMovementMethod(CustomLinkMovementMethod.getInstance());
to #binary's answer for those whose the method did not work with them