Android - Issue with clickableSpan and TextView
I'm trying to implement clickable hashtags in my TextView as below:
mTextView.setMovementMethod(LinkMovementMethod.getInstance());
Spannable s = (Spannable) mTextView.getText();
CharacterStyle clickableSpan = new MyClickableSpan();
s.setSpan(clickableSpan, startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
this handles onClick for my hashtags as I wanted, but it seems that the other part of the text also listens for onClick events and does nothing.
My question is how to make the non-spannable text parts, delegate the onClick event to the parent view as see in below image.
android
add a comment |
I'm trying to implement clickable hashtags in my TextView as below:
mTextView.setMovementMethod(LinkMovementMethod.getInstance());
Spannable s = (Spannable) mTextView.getText();
CharacterStyle clickableSpan = new MyClickableSpan();
s.setSpan(clickableSpan, startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
this handles onClick for my hashtags as I wanted, but it seems that the other part of the text also listens for onClick events and does nothing.
My question is how to make the non-spannable text parts, delegate the onClick event to the parent view as see in below image.
android
add a comment |
I'm trying to implement clickable hashtags in my TextView as below:
mTextView.setMovementMethod(LinkMovementMethod.getInstance());
Spannable s = (Spannable) mTextView.getText();
CharacterStyle clickableSpan = new MyClickableSpan();
s.setSpan(clickableSpan, startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
this handles onClick for my hashtags as I wanted, but it seems that the other part of the text also listens for onClick events and does nothing.
My question is how to make the non-spannable text parts, delegate the onClick event to the parent view as see in below image.
android
I'm trying to implement clickable hashtags in my TextView as below:
mTextView.setMovementMethod(LinkMovementMethod.getInstance());
Spannable s = (Spannable) mTextView.getText();
CharacterStyle clickableSpan = new MyClickableSpan();
s.setSpan(clickableSpan, startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
this handles onClick for my hashtags as I wanted, but it seems that the other part of the text also listens for onClick events and does nothing.
My question is how to make the non-spannable text parts, delegate the onClick event to the parent view as see in below image.
android
android
edited Nov 26 '18 at 10:36
M.SamiAzar
asked Nov 24 '18 at 14:26
M.SamiAzarM.SamiAzar
360315
360315
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
You can use something like this :
`SpannableString string = new SpannableString(getString(R.string.some_string));
ClickableSpan clickableSpan = new ClickableSpan() {
@Override
public void onClick(View textView) {
//do something
}`
@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
}
};
`string.setSpan(clickableSpan, string.length() - 20, string.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(string);
textView.setMovementMethod(LinkMovementMethod.getInstance());`
I'm sorry because I think I get bad to explain my issue. please relook to question and give another hint. Thank you!
– M.SamiAzar
Nov 26 '18 at 10:38
add a comment |
I use the next extension in Kotlin
fun SpannableString.withClickableSpan(
context: Context,
clickablePart: String,
onClickListener: () -> Unit
): SpannableString {
val clickableSpan = object : ClickableSpan() {
override fun onClick(widget: View?) {
onClickListener.invoke()
}
}
val clickablePartStart = indexOf(clickablePart)
this.setSpan(
clickableSpan,
clickablePartStart, clickablePartStart + clickablePart.length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
this.setSpan(
ForegroundColorSpan(ContextCompat.getColor(context, R.color.cyan)),
clickablePartStart, clickablePartStart + clickablePart.length,
Spanned.SPAN_INCLUSIVE_EXCLUSIVE
)
return this
}
And call it like:
val span = SpannableString(text).withClickableSpan(requireContext(), text) {
onRevisionDateClicked(view)
}
view.movementMethod = LinkMovementMethod.getInstance()
view.setText(span, TextView.BufferType.SPANNABLE)
view.isClickable = true
OR you can use something like that in Java:
SpannableString ss = new SpannableString("Hello World");
ClickableSpan spanText = new ClickableSpan() {
@Override
public void onClick(View textView) {
// do some thing
}
};
ss.setSpan(spanText, 0, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(ss);
textView.setMovementMethod(LinkMovementMethod.getInstance());
@M.SamiAzar Rate this answer if it was helpful
– Andrii Zhumela
Nov 29 '18 at 12:31
I think you did not understand my question. I already have done with the clickable span, but I want another part of the text that not hashtag to be no clickable and when I click that area perform parent onClick event
– M.SamiAzar
Dec 1 '18 at 7:47
add a comment |
I figured out my question with this solution but if anyone had a better solution please let me know.
I set OnClickListener for my TextView and in the onClick event I get the parent of my TextView and check if the parent is clickable then perform parent onClick event and if not I recursively get the parent of the parent until I achieve to clickable parent. In this way, hashtags still are clickable with own actions and when clicking another part of the text the onClick event of the parent is performed.
here is the code of how I recursively find clickable parent:
private View getParentClickable(View view) {
try {
if (((View) view.getParent()).isClickable()) {
return (View) view.getParent();
} else {
return getParentClickable(((View) view.getParent()));
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
and then setOnClickListener for my view:
mTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
View parent = getParentClickable(mTextView);
if (parent != null) parent.performClick();
}
});
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53459151%2fandroid-issue-with-clickablespan-and-textview%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
You can use something like this :
`SpannableString string = new SpannableString(getString(R.string.some_string));
ClickableSpan clickableSpan = new ClickableSpan() {
@Override
public void onClick(View textView) {
//do something
}`
@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
}
};
`string.setSpan(clickableSpan, string.length() - 20, string.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(string);
textView.setMovementMethod(LinkMovementMethod.getInstance());`
I'm sorry because I think I get bad to explain my issue. please relook to question and give another hint. Thank you!
– M.SamiAzar
Nov 26 '18 at 10:38
add a comment |
You can use something like this :
`SpannableString string = new SpannableString(getString(R.string.some_string));
ClickableSpan clickableSpan = new ClickableSpan() {
@Override
public void onClick(View textView) {
//do something
}`
@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
}
};
`string.setSpan(clickableSpan, string.length() - 20, string.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(string);
textView.setMovementMethod(LinkMovementMethod.getInstance());`
I'm sorry because I think I get bad to explain my issue. please relook to question and give another hint. Thank you!
– M.SamiAzar
Nov 26 '18 at 10:38
add a comment |
You can use something like this :
`SpannableString string = new SpannableString(getString(R.string.some_string));
ClickableSpan clickableSpan = new ClickableSpan() {
@Override
public void onClick(View textView) {
//do something
}`
@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
}
};
`string.setSpan(clickableSpan, string.length() - 20, string.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(string);
textView.setMovementMethod(LinkMovementMethod.getInstance());`
You can use something like this :
`SpannableString string = new SpannableString(getString(R.string.some_string));
ClickableSpan clickableSpan = new ClickableSpan() {
@Override
public void onClick(View textView) {
//do something
}`
@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
}
};
`string.setSpan(clickableSpan, string.length() - 20, string.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(string);
textView.setMovementMethod(LinkMovementMethod.getInstance());`
answered Nov 24 '18 at 14:54
The90sArtistThe90sArtist
4117
4117
I'm sorry because I think I get bad to explain my issue. please relook to question and give another hint. Thank you!
– M.SamiAzar
Nov 26 '18 at 10:38
add a comment |
I'm sorry because I think I get bad to explain my issue. please relook to question and give another hint. Thank you!
– M.SamiAzar
Nov 26 '18 at 10:38
I'm sorry because I think I get bad to explain my issue. please relook to question and give another hint. Thank you!
– M.SamiAzar
Nov 26 '18 at 10:38
I'm sorry because I think I get bad to explain my issue. please relook to question and give another hint. Thank you!
– M.SamiAzar
Nov 26 '18 at 10:38
add a comment |
I use the next extension in Kotlin
fun SpannableString.withClickableSpan(
context: Context,
clickablePart: String,
onClickListener: () -> Unit
): SpannableString {
val clickableSpan = object : ClickableSpan() {
override fun onClick(widget: View?) {
onClickListener.invoke()
}
}
val clickablePartStart = indexOf(clickablePart)
this.setSpan(
clickableSpan,
clickablePartStart, clickablePartStart + clickablePart.length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
this.setSpan(
ForegroundColorSpan(ContextCompat.getColor(context, R.color.cyan)),
clickablePartStart, clickablePartStart + clickablePart.length,
Spanned.SPAN_INCLUSIVE_EXCLUSIVE
)
return this
}
And call it like:
val span = SpannableString(text).withClickableSpan(requireContext(), text) {
onRevisionDateClicked(view)
}
view.movementMethod = LinkMovementMethod.getInstance()
view.setText(span, TextView.BufferType.SPANNABLE)
view.isClickable = true
OR you can use something like that in Java:
SpannableString ss = new SpannableString("Hello World");
ClickableSpan spanText = new ClickableSpan() {
@Override
public void onClick(View textView) {
// do some thing
}
};
ss.setSpan(spanText, 0, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(ss);
textView.setMovementMethod(LinkMovementMethod.getInstance());
@M.SamiAzar Rate this answer if it was helpful
– Andrii Zhumela
Nov 29 '18 at 12:31
I think you did not understand my question. I already have done with the clickable span, but I want another part of the text that not hashtag to be no clickable and when I click that area perform parent onClick event
– M.SamiAzar
Dec 1 '18 at 7:47
add a comment |
I use the next extension in Kotlin
fun SpannableString.withClickableSpan(
context: Context,
clickablePart: String,
onClickListener: () -> Unit
): SpannableString {
val clickableSpan = object : ClickableSpan() {
override fun onClick(widget: View?) {
onClickListener.invoke()
}
}
val clickablePartStart = indexOf(clickablePart)
this.setSpan(
clickableSpan,
clickablePartStart, clickablePartStart + clickablePart.length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
this.setSpan(
ForegroundColorSpan(ContextCompat.getColor(context, R.color.cyan)),
clickablePartStart, clickablePartStart + clickablePart.length,
Spanned.SPAN_INCLUSIVE_EXCLUSIVE
)
return this
}
And call it like:
val span = SpannableString(text).withClickableSpan(requireContext(), text) {
onRevisionDateClicked(view)
}
view.movementMethod = LinkMovementMethod.getInstance()
view.setText(span, TextView.BufferType.SPANNABLE)
view.isClickable = true
OR you can use something like that in Java:
SpannableString ss = new SpannableString("Hello World");
ClickableSpan spanText = new ClickableSpan() {
@Override
public void onClick(View textView) {
// do some thing
}
};
ss.setSpan(spanText, 0, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(ss);
textView.setMovementMethod(LinkMovementMethod.getInstance());
@M.SamiAzar Rate this answer if it was helpful
– Andrii Zhumela
Nov 29 '18 at 12:31
I think you did not understand my question. I already have done with the clickable span, but I want another part of the text that not hashtag to be no clickable and when I click that area perform parent onClick event
– M.SamiAzar
Dec 1 '18 at 7:47
add a comment |
I use the next extension in Kotlin
fun SpannableString.withClickableSpan(
context: Context,
clickablePart: String,
onClickListener: () -> Unit
): SpannableString {
val clickableSpan = object : ClickableSpan() {
override fun onClick(widget: View?) {
onClickListener.invoke()
}
}
val clickablePartStart = indexOf(clickablePart)
this.setSpan(
clickableSpan,
clickablePartStart, clickablePartStart + clickablePart.length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
this.setSpan(
ForegroundColorSpan(ContextCompat.getColor(context, R.color.cyan)),
clickablePartStart, clickablePartStart + clickablePart.length,
Spanned.SPAN_INCLUSIVE_EXCLUSIVE
)
return this
}
And call it like:
val span = SpannableString(text).withClickableSpan(requireContext(), text) {
onRevisionDateClicked(view)
}
view.movementMethod = LinkMovementMethod.getInstance()
view.setText(span, TextView.BufferType.SPANNABLE)
view.isClickable = true
OR you can use something like that in Java:
SpannableString ss = new SpannableString("Hello World");
ClickableSpan spanText = new ClickableSpan() {
@Override
public void onClick(View textView) {
// do some thing
}
};
ss.setSpan(spanText, 0, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(ss);
textView.setMovementMethod(LinkMovementMethod.getInstance());
I use the next extension in Kotlin
fun SpannableString.withClickableSpan(
context: Context,
clickablePart: String,
onClickListener: () -> Unit
): SpannableString {
val clickableSpan = object : ClickableSpan() {
override fun onClick(widget: View?) {
onClickListener.invoke()
}
}
val clickablePartStart = indexOf(clickablePart)
this.setSpan(
clickableSpan,
clickablePartStart, clickablePartStart + clickablePart.length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
this.setSpan(
ForegroundColorSpan(ContextCompat.getColor(context, R.color.cyan)),
clickablePartStart, clickablePartStart + clickablePart.length,
Spanned.SPAN_INCLUSIVE_EXCLUSIVE
)
return this
}
And call it like:
val span = SpannableString(text).withClickableSpan(requireContext(), text) {
onRevisionDateClicked(view)
}
view.movementMethod = LinkMovementMethod.getInstance()
view.setText(span, TextView.BufferType.SPANNABLE)
view.isClickable = true
OR you can use something like that in Java:
SpannableString ss = new SpannableString("Hello World");
ClickableSpan spanText = new ClickableSpan() {
@Override
public void onClick(View textView) {
// do some thing
}
};
ss.setSpan(spanText, 0, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(ss);
textView.setMovementMethod(LinkMovementMethod.getInstance());
edited Nov 29 '18 at 12:29
answered Nov 29 '18 at 12:21
Andrii ZhumelaAndrii Zhumela
343
343
@M.SamiAzar Rate this answer if it was helpful
– Andrii Zhumela
Nov 29 '18 at 12:31
I think you did not understand my question. I already have done with the clickable span, but I want another part of the text that not hashtag to be no clickable and when I click that area perform parent onClick event
– M.SamiAzar
Dec 1 '18 at 7:47
add a comment |
@M.SamiAzar Rate this answer if it was helpful
– Andrii Zhumela
Nov 29 '18 at 12:31
I think you did not understand my question. I already have done with the clickable span, but I want another part of the text that not hashtag to be no clickable and when I click that area perform parent onClick event
– M.SamiAzar
Dec 1 '18 at 7:47
@M.SamiAzar Rate this answer if it was helpful
– Andrii Zhumela
Nov 29 '18 at 12:31
@M.SamiAzar Rate this answer if it was helpful
– Andrii Zhumela
Nov 29 '18 at 12:31
I think you did not understand my question. I already have done with the clickable span, but I want another part of the text that not hashtag to be no clickable and when I click that area perform parent onClick event
– M.SamiAzar
Dec 1 '18 at 7:47
I think you did not understand my question. I already have done with the clickable span, but I want another part of the text that not hashtag to be no clickable and when I click that area perform parent onClick event
– M.SamiAzar
Dec 1 '18 at 7:47
add a comment |
I figured out my question with this solution but if anyone had a better solution please let me know.
I set OnClickListener for my TextView and in the onClick event I get the parent of my TextView and check if the parent is clickable then perform parent onClick event and if not I recursively get the parent of the parent until I achieve to clickable parent. In this way, hashtags still are clickable with own actions and when clicking another part of the text the onClick event of the parent is performed.
here is the code of how I recursively find clickable parent:
private View getParentClickable(View view) {
try {
if (((View) view.getParent()).isClickable()) {
return (View) view.getParent();
} else {
return getParentClickable(((View) view.getParent()));
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
and then setOnClickListener for my view:
mTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
View parent = getParentClickable(mTextView);
if (parent != null) parent.performClick();
}
});
add a comment |
I figured out my question with this solution but if anyone had a better solution please let me know.
I set OnClickListener for my TextView and in the onClick event I get the parent of my TextView and check if the parent is clickable then perform parent onClick event and if not I recursively get the parent of the parent until I achieve to clickable parent. In this way, hashtags still are clickable with own actions and when clicking another part of the text the onClick event of the parent is performed.
here is the code of how I recursively find clickable parent:
private View getParentClickable(View view) {
try {
if (((View) view.getParent()).isClickable()) {
return (View) view.getParent();
} else {
return getParentClickable(((View) view.getParent()));
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
and then setOnClickListener for my view:
mTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
View parent = getParentClickable(mTextView);
if (parent != null) parent.performClick();
}
});
add a comment |
I figured out my question with this solution but if anyone had a better solution please let me know.
I set OnClickListener for my TextView and in the onClick event I get the parent of my TextView and check if the parent is clickable then perform parent onClick event and if not I recursively get the parent of the parent until I achieve to clickable parent. In this way, hashtags still are clickable with own actions and when clicking another part of the text the onClick event of the parent is performed.
here is the code of how I recursively find clickable parent:
private View getParentClickable(View view) {
try {
if (((View) view.getParent()).isClickable()) {
return (View) view.getParent();
} else {
return getParentClickable(((View) view.getParent()));
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
and then setOnClickListener for my view:
mTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
View parent = getParentClickable(mTextView);
if (parent != null) parent.performClick();
}
});
I figured out my question with this solution but if anyone had a better solution please let me know.
I set OnClickListener for my TextView and in the onClick event I get the parent of my TextView and check if the parent is clickable then perform parent onClick event and if not I recursively get the parent of the parent until I achieve to clickable parent. In this way, hashtags still are clickable with own actions and when clicking another part of the text the onClick event of the parent is performed.
here is the code of how I recursively find clickable parent:
private View getParentClickable(View view) {
try {
if (((View) view.getParent()).isClickable()) {
return (View) view.getParent();
} else {
return getParentClickable(((View) view.getParent()));
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
and then setOnClickListener for my view:
mTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
View parent = getParentClickable(mTextView);
if (parent != null) parent.performClick();
}
});
answered Dec 1 '18 at 8:03
M.SamiAzarM.SamiAzar
360315
360315
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53459151%2fandroid-issue-with-clickablespan-and-textview%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown