I'm trying to implement a comment like list where you can mention other users in the comments, and then be able to click on that to go to their profile. For example, when posting a comment on reddit you can mention another user with /u/username.
The one problem i'm running into is how to make it so I can click on the text to load that user's profile.
For the comment list I essentially have a custom list of textviews. From googling around I saw that it is possible to be able to click on some text in a textview using a clickable span. However, I haven't been able to get this to work in a list of textviews. Can someone help?
This is the relevant sections of my code:
Clickable span I declared as a member variable:
ClickableSpan clickableSpan = new ClickableSpan() {
#Override
public void onClick(View widget) {
Intent intent = new Intent(context, ProfileActivity.class);
// ParseUser.getQuery().whereEqualTo(Constants.kQollegeUserPreferredUsernameKey, sta)
intent.putExtra("User", ParseUser.getCurrentUser().getObjectId());
context.startActivity(intent);
}
};
Inside getView:
TextView answer_text_view = answerView.getAnswerTextView();
String text = answer.getAnswerText();
if(text.contains("#")) {
text += " ";
final SpannableStringBuilder sb = new SpannableStringBuilder(text);
List<Integer> start = new ArrayList<>();
int index = text.indexOf("#");
while (index >= 0) {
start.add(index);
index = text.indexOf("#", index + 1);
}
for(int i = 0; i<start.size(); i++){
sb.setSpan(fcs, start.get(i), text.indexOf(" ", start.get(i)), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
sb.setSpan(clickableSpan, start.get(i), text.indexOf(" ", start.get(i)), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
answer_text_view.setText(sb);
}
I have applied following to the textview where clickable span is present to make it work
textView.setMovementMethod(LinkMovementMethod.getInstance());
Related
For my college project I am using this sample-code example, project worked successfully and now I want to highlight searched text, but I don't kn how to implement it ,some of spanned-string example tried but does not support so any one please help me (as like as image)
to highlight searched term try below code:
String m_filterVal = m_searchTerm;//Your search term suppose "p"
String m_originalItemValue = ... //Your original whole string suppose "paint";
int m_startPos = m_originalItemValue.toLowerCase(Locale.US).indexOf(m_filterVal.toLowerCase(Locale.US));
int m_endPos = m_startPos + m_filterVal.length();
if (m_startPos != -1) // This should always be true, just a sanity check
{
Spannable m_spannable = new SpannableString(m_originalItemValue);
ColorStateList m_blueColor = new ColorStateList(new int[][] { new int[] {} }, new int[] { Color.BLUE });
TextAppearanceSpan m_highlightSpan = new TextAppearanceSpan(null, Typeface.BOLD, -1, m_blueColor, null);
m_spannable.setSpan(m_highlightSpan, m_startPos, m_endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
m_tvCategoryItem.setText(m_spannable);//your textview name
}
else
{
m_tvCategoryItem.setText(m_originalItemValue);
}
I've been stuck at this problem for long. What I'm having is a simple string "This is a link and this is another link". I want to have both "link" words click-able, having different URLs to open in browser.
The simplest way I can do is to set Click-able Span on both "link"
words with different URLs, but the problem I'm facing is finding the
start and end positions of the span. The text is dynamic, and I have
to programmatically find the positions.
One approach would be to find the first occurrence of the word
'link', find the start and end positions and set the span, and then
the second occurrence. But that is not reliable. The text may contain
more than one kind of repeated words, like "This is a cat link and
this is another cat link". Here I have to link both "cat" and "link"
words with different URLs via Click-able Span. How do I go about it?
Try in this manner
String s="Cat link 1 Cat link 2 Cat link 3";
SpannableString ss = new SpannableString(s);
String first ="Cat link 1";
String second ="Cat link 2";
String third ="Cat link 3";
int firstIndex = s.toString().indexOf(first);
int secondIndex = s.toString().indexOf(second);
ClickableSpan firstwordClick = new ClickableSpan() {
#Override
public void onClick(View widget) {
///............
}
};
ClickableSpan secondwordClick = new ClickableSpan() {
#Override
public void onClick(View widget) {
///............
}
};
ss.setSpan(firstwordClick,firstIndex, firstIndex+first.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss.setSpan(secondwordClick,secondIndex, secondIndex+second.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setLinksClickable(true);
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setText(ss,BufferType.SPANNABLE);
If you cannot programmatically find the difference in the links, then you cannot expect anything else to be able to do it. As the developer, you need a system.
You need to be able to identify the clickable spans - since the links are unique, the text that identifies them must also be unique. This would be a problem for your users, most likely.
You can get an ordered list of URLs and then if the links are indistinguishable, simply use them in the order you receive. Or, you need to change the rules of creating the links or the order in which they are displayed.
One simple way to do this would be to include an identifier before the link say /*/ then using this find the start and end position for link. Once you have that first replace the identifier with a "" and then click away.
I have string something such "you order with orderId {b1j2gh4b} has been claimed by bla bla sotre with phone number (1234124124)"
I am using these braces so as to find out the index of of orderID and Phone number
String notificationMessage = mArrListNotification.get(position).getMessage();
boolean isPhoneNumberAvailable = false, isOrderIdAvailable = false;
int phoneStartIndex = 0, phoneEndIndex = 0, orderIdStartIndex = 0, orderIdEndIndex = 0;
//getting index on the basis of braces added to text
if (notificationMessage.contains("(")) {
isPhoneNumberAvailable = true;
phoneStartIndex = notificationMessage.indexOf("(");
phoneEndIndex = notificationMessage.indexOf(")");
}
if (notificationMessage.contains("{")) {
orderIdStartIndex = notificationMessage.indexOf("{");
orderIdEndIndex = notificationMessage.indexOf("}");
}
// we got the index so remove braces
notificationMessage = notificationMessage.replace("(", " ");
notificationMessage = notificationMessage.replace(")", " ");
notificationMessage = notificationMessage.replace("{", " ");
notificationMessage = notificationMessage.replace("}", " ");
viewHolder.txtNotificationMessage.setText(notificationMessage, TextView.BufferType.SPANNABLE);
Spannable mySpannablePhoneNumber = (Spannable) viewHolder.txtNotificationMessage.getText();
Spannable mySpannableOrderID = (Spannable) viewHolder.txtNotificationMessage.getText();
ClickableSpan mySpanPhoneClick = new ClickableSpan() {
#Override
public void onClick(View widget) {
currentPosition = (Integer) widget.getTag();
String message = mArrListNotification.get(currentPosition).getMessage();
int startIndex = message.indexOf("(");
int endIndex = message.indexOf(")");
phoneNumber = message.substring(startIndex + 1, endIndex);
Log.i("Phone Number", phoneNumber clicked)
}
};
ClickableSpan mySpanOrderClick = new ClickableSpan() {
#Override
public void onClick(View widget) {
currentPosition = (Integer) widget.getTag();
String message = mArrListNotification.get(currentPosition).getMessage();
int startIndex = message.indexOf("{");
int endIndex = message.indexOf("}");
String orderID = message.substring(startIndex + 1, endIndex);
// Log.i("Order id", orderID clicked)
}
};
if (isPhoneNumberAvailable) {
mySpannablePhoneNumber.setSpan(mySpanPhoneClick, phoneStartIndex + 1, phoneEndIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
if (isOrderIdAvailable) {
mySpannableOrderID.setSpan(mySpanOrderClick, orderIdStartIndex + 1, orderIdEndIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
I am automating a product using robotium. I need to do some dat validation kind of task there.
Scenario is like:
We click on a list, select some items in the list and do some operation.
I want to put the names of the items selected into an array. Such that i can compare it later.
I used the following code:
for(i=0; i<=n;i++)
{
solo.clickInList(i);
Array1[i]=solo.getText(i).toString();
}
But sadly, this statement is not extracting the text of the textView selected but the id of the textView.
Please help me by giving an example of how to get the text of the TextView selected.
At a fix!!
if you have only listview with texts, it should work for you (I didn't test it):
ListView listView = solo.getView(ListView.class, 0);
String text = listView.getItemAtPosition(position));
Another way will be like this:
ArrayList<TextView> result = solo.clickInList(line);
String text = "";
for (int i = 0; i < result.size(); i++) {
text += result.get(i).getText().toString() + " ";
}
if (text.length() > 0) {
text = text.substring(0, text.length() - 1); // remove last space
}
My Android app is displaying text in a TextView.
Are there any tags or anything to put around words that I want italicized? I don't need to set the TextView as italics because the whole sentence would be that way, and I only need specific words italicized.
You need to use a Spannable: see Is there any example about Spanned and Spannable text for an example.
I agree, this isn't a database issue. If this is not a custom app you're working on, you're out of luck. If it is, save the field in the database as HTML.
This function sets a string as the text of a TextView and italicizes one or more spans within that string as long as the span or spans are marked with the tags [i] and [/i]. Of course, it can be modified for other types of styling.
private void doItalicize(TextView xTextView, String xString) {
ArrayList<Integer> IndexStart = new ArrayList<>();
ArrayList<Integer> IndexEnd = new ArrayList<>();
ArrayList<StyleSpan> SpanArray = new ArrayList<>();
int i = 0;
do {
IndexStart.add(i, xString.indexOf("[i]"));
IndexEnd.add(i, xString.indexOf("[/i]") - 3);
xString = xString.replaceFirst("\\[i\\]", "");
xString = xString.replaceFirst("\\[/i\\]", "");
xTextView.setText(xString, TextView.BufferType.SPANNABLE);
SpanArray.add(i, new StyleSpan(Typeface.ITALIC));
Log.d(LOG_TAG, "i: " + i);
i++;
} while (xString.contains("[i]"));
Spannable xSpannable = (Spannable) xTextView.getText();
for (int j = 0; j < i; j++)
xSpannable.setSpan(SpanArray.get(j), IndexStart.get(j), IndexEnd.get(j), Spanned
.SPAN_EXCLUSIVE_EXCLUSIVE);
}
The solution would seem to be to save the content in the database as HTML and then output the HTML in the textview.
See the following article: How to display HTML in TextView?
Is there any way I can launch an activity from a portion of a string.
eg
I have this in my strings.xml file:
<string name="clickable_string">This is a <u>clickable string</u></string>
I would like the text between the u tags to be underlined and launch an activity when clicked when inserted in to a TextView
Try this,
final Context context = ... // whereever your context is
CharSequence sequence = Html.fromSource(context.getString(R.string.clickable_string));
SpannableStringBuilder strBuilder = new SpannableStringBuilder(sequence);
UnderlineSpan[] underlines = strBuilder.getSpans(UnderlineSpan.class);
for(UnderlineSpan span : underlines) {
int start = strBuilder.getSpanStart(span);
int end = strBuilder.getSpanEnd(span);
int flags = strBuilder.getSpanFlags(span);
ClickableSpan myActivityLauncher = new ClickableSpan() {
public void onClick(View view) {
context.startActivity(getIntentForActivityToStart());
}
};
strBuilder.setSpan(myActivityLauncher, start, end, flags);
}
TextView textView = ...
textView.setText(strBuilder);
textView.setMovementMethod(LinkMovementMethod.getInstance());
Basically you have to attach a Span object to the range of characters you want to be clickable. Since you are using HTML anyways, you can use the underline spans placed by the Html.fromSource() as markers for your own spans.
Alternatively you could also define a Tag within the string that only you know of.
i.e. <activity>
And supply your own tag handler to the Html.fromSource() method. This way your TagHandler instance could do something like, surround the tagged text with a specific color, underline, bold and make it clickable. However I would only recommend the TagHandler approach if you find yourself writing this type of code a lot.
assign this string to one of your xml layout and then in your code get the id of TextView and then implement OnClickListener for this Textview,inside of it you can start your new activity you want.
Answered here Make parts of textview clickable (not url)
I just made a modification if you want to use it with a HTML Message do the following
In your Display function
public void displayText(String message) {
chapterTextView.setText(Html.fromHtml(message),TextView.BufferType.SPANNABLE);
chapterTextView.setMovementMethod(LinkMovementMethod.getInstance());
Spannable clickableMessage = (Spannable) chapterTextView.getText();
chapterTextView.setText(addClickablePart(clickableMessage), BufferType.SPANNABLE);
}
The Modified function of addClickablePart
private SpannableStringBuilder addClickablePart(Spannable charSequence) {
SpannableStringBuilder ssb = new SpannableStringBuilder(charSequence);
int idx1 = charSequence.toString().indexOf("(");
int idx2 = 0;
while (idx1 != -1) {
idx2 = charSequence.toString().indexOf(")", idx1) + 1;
final String clickString = charSequence.toString().substring(idx1, idx2);
ssb.setSpan(new ClickableSpan() {
#Override
public void onClick(View widget) {
Toast.makeText(getActivity(), clickString,
Toast.LENGTH_SHORT).show();
}
}, idx1, idx2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
idx1 = charSequence.toString().indexOf("(", idx2);
}
return ssb;
}
Hope this help someone.