GridView: Using RecyclerView or Simply TextView with clickable words - android

So, Does anybody know how to create following grid? I need to set clickable event to every word:
If four words are not fit to a line then should be shown three in a line:
if it will be exceed to a line n words then should be shown n words in a line.
Is there anybody knows how to implement this?

You can use SpannableString and ClickableSpan. this Activity, for example, creates TextView with your text and manages clicks on each word:
public class MainActivity extends AppCompatActivity {
Activity activity;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
activity = this;
TextView textView = (TextView) findViewById(R.id.textView);
String text = "up down Antidisestablishment over took dropped lighten with from throught fell on up down Antidisestablishment over took dropped lighten with from throught fell on";
String[] textArray = text.split(" ");
SpannableString ss = new SpannableString(text);
int start = 0;
int end = 0;
for(final String item : textArray){
end = start + item.length();
ClickableSpan clickableSpan = new ClickableSpan() {
#Override
public void onClick(View textView) {
Toast.makeText(activity, "Say " + item+ "!", Toast.LENGTH_SHORT).show();
}
#Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
}
};
ss.setSpan(clickableSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
start += item.length()+1;
}
textView.setText(ss);
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setHighlightColor(Color.TRANSPARENT);
}
}
and here is activity_main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity"
android:padding="5dp">
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24sp"
android:textColor="#000000"
android:textColorLink="#000000"/>
</LinearLayout>
if you click on any word you get popup with this word
EDIT: to justify the text use the library android-justifiedtextview
But not the library from gradle, there are the old version which does not support SpannableString. I recommend just copy the class JustifyTextView from git to your project. Then you can use this view in your .xml like:
<com.yourdomain.yourproject.JustifyTextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24sp"
android:textColor="#000000"
android:textColorLink="#000000"/>
here is what I got with this library:
you also can modify the library to keep last line unjustified. Every word in the text is still clickable.

If the amount of items you have to add is little, consider using a FlowLayout. It extends a LinearLayout, so just wrap it in a ScrollView, add your views to it dynamically, and you should be good to go.

Related

Android : Adding an imageview right at the end of a textview via ImageSpan and make the image clickable

I want to achieve a design as shown above in the screenshot. The image is fetched from a URL and I want to add a click listener in the image only. Tried using Image span but with no success. Could somebody help me through this?
Thank you
Here is a more complete answer to your question. I use a drawable resource, but you can create a drawable from your bitmap. See the following code for a description. This code can be placed into the onCreate() of your main activity (or elsewhere.)
// Get a string that can be spanned with an ImageSpan and a ClickableSpan.
SpannableString ss = new SpannableString("Some text ");
// This will be the image. I use a resource here, but there are constructors that can
// accept a Drawable. See BitmapDrawable at https://developer.android.com/reference/android/graphics/drawable/BitmapDrawable#BitmapDrawable(android.content.res.Resources,%20android.graphics.Bitmap)
ImageSpan imgSpan = new ImageSpan(this, R.drawable.ic_baseline_airplanemode_active_24, ImageSpan.ALIGN_CENTER);
ClickableSpan cs = new ClickableSpan() {
#Override
public void onClick(#NonNull View widget) {
Toast.makeText(MainActivity.this, "Clicked!", Toast.LENGTH_SHORT).show();
}
};
// The image will overlay the last blank in the text.
ss.setSpan(imgSpan, ss.length() - 1, ss.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// The clickable span will overlay the image from the ImageSpan.
ss.setSpan(cs, ss.length() - 1, ss.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// Just a TextView.
TextView myView = findViewById(R.id.myView);
myView.setText(ss);
// Prevent the ImageSpan from showing a highlight on click.
myView.setHighlightColor(getResources().getColor(android.R.color.transparent));
// Make sure the TextView can be clicked.
myView.setMovementMethod(LinkMovementMethod.getInstance());
You can set another span call ClickableSpan at the same place of the ImageSpan. Here an example code:
builder.setSpan(new ClickableSpan() {
#Override
public void onClick(#NonNull View widget) {
Toast.makeText(context, "icon clicked", Toast.LENGTH_SHORT).show();
}
},
builder.length() - 1,
builder.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
holder.tvTitle.setText(builder);
holder.tvTitle.setMovementMethod(LinkMovementMethod.getInstance());
It is important to setMovementMethod for the click to work.
I don't know your limitation, but you can using a layout like bellow:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:padding="5dp">
<TextView
android:id="#+id/top_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Papaya (Around)"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<TextView
android:id="#+id/bottom_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=",(2kg)"
app:layout_constraintTop_toBottomOf="#id/top_tv"
app:layout_constraintStart_toStartOf="#id/top_tv"/>
<ImageView
android:id="#+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_launcher_help"
app:layout_constraintTop_toTopOf="#id/bottom_tv"
app:layout_constraintBottom_toBottomOf="#id/bottom_tv"
app:layout_constraintStart_toEndOf="#id/bottom_tv"/>
</androidx.constraintlayout.widget.ConstraintLayout>
and using setOnClickListener for ImageView. The result:

TextView, how to display prompt for user

I need to set prompt for my TextView, if String is too long to fit inside TV (i set max length 20) then it displays only part of it with "..." at the end. I want to display prompt with full String when i click on TV. Is it possible? And if yes then how to do it?
Inside activity:
textCompany.setText(testDb.getCompanyName(id));
textCompany.setEllipsize(null);
And XML:
<TextView
android:id="#+id/textCompany"
android:layout_width="match_parent"
android:layout_below="#+id/textId"
android:layout_height="wrap_content"
android:maxLength="20"
android:ellipsize="end"
android:gravity="end"
android:layout_marginEnd="20dp"
android:textSize="17sp"
android:text="verylongstringjusttotestifthisworksandletshopeitwill" />
You can do that with a simple onClickListener. First, you check what the length of the text is, then if it's more than 20 characters, you take the first 20 and add three dots to the end and display that. At the same time, you save the full text to a temporary variable, and you display it when someone clicks your TextView.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final TextView textView = findViewById(R.id.textCompany);
String shortMessage;
final String message = textView.getText().toString();
if(message.length() >= 20){
shortMessage = message.substring(0,19)+"...";
textView.setText(shortMessage);
}
textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
}
});
}
Note: make sure you make your textView clickable by adding the following to your xml:
android:clickable="true"
The behavior you mentioned is due to
android:ellipsize="end"
It displays the end of text with "Some text..." if it does not fit in width.
You can programmatically change the ellipsize value to none to display the full text on Click.
myTextView.setEllipsize(null);

linkify on textview with domain in text not working, links not clickable

I'm not able to linkfy a string with a href when the string says the domain name with it. so string. let me show you.
Here is the string:
<string name="go_to_settings">Please go to "Settings" in mywebsite.com to change this status</string>
And it would say this to the user: "Please go to "Settings" in mywebsite.com to change this status. "
here is the textview I'm using:
<TextView
android:id="#+id/tv_instructions"
android:layout_width="280dp"
android:layout_height="wrap_content"
android:layout_marginTop="73dp"
android:lineSpacingExtra="3sp"
android:textAlignment="center"
android:textColor="#5c5c5c"
android:textColorLink="#color/action_blue"
android:linksClickable="true"
android:text="#string/go_to_settings"/>
and here is how i am trying to make the link clickable:
Linkify.addLinks(tv_instructions, Linkify.ALL)
tv_instructions.movementMethod=LinkMovementMethod.getInstance()
But i am seeing happen on api 24 and 27 device and emulator is that the link is going to www.mywebsite.com instead of www.mywebsite/settings
but here is the strange thing, if i change the text the user sees and remove .com from that then it works fine. so if the user see this instead it works:
and it would say this to the user: "Please go to "Settings" in mywebsite to change this status. "
notice there is no .com being mentioned. How can i get this displayed. i also tried this way:
tv_instructions.text=(utils.fromHTML(resources.getString(R.string.go_to_settings),null))
tv_instructions.movementMethod=LinkMovementMethod.getInstance()
and textview like this:
<TextView
android:id="#+id/tv_instructions"
android:layout_width="280dp"
android:layout_height="wrap_content"
android:layout_marginTop="73dp"
android:lineSpacingExtra="3sp"
android:textAlignment="center"
android:textColor="#5c5c5c"
android:text="#string/go_to_settings"
/>
you guys have any idea what I'm doing wrong ?
Figured this out. for some reason i needed to wrap my text as character data using tag cData in my strings file. this works:
<string name="go_to_settings"><![CDATA[Please go to "Settings" in mywebsite.com to change this status :]]></string>
then the textview looks like this:
<TextView
android:id="#+id/tv_instructions"
android:layout_width="280dp"
android:layout_height="wrap_content"
android:layout_marginTop="73dp"
android:lineSpacingExtra="3sp"
android:text="#string/go_to_settings"
android:textAlignment="center"
android:textColor="#5c5c5c"
android:textColorLink="#color/action_blue"/>
Java Code
tv_instructions.text=(utils.fromHTML(resources.getString(R.string.go_to_settings),null))
tv_instructions.movementMethod=LinkMovementMethod.getInstance()
linkify on textview with domain in text not working, links not clickable
You can also use ClickableSpan
If an object of this type is attached to the text of a TextView with a movement method of LinkMovementMethod, the affected spans of text can be selected. If selected and clicked, the onClick(View) method will be called.
Check below SAMPLE CODE
Try this
public class MainActivity extends AppCompatActivity {
TextView myTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myTextView = (TextView) findViewById(R.id.myTextview);
setSpan();
}
private void setSpan() {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder("Please go to \"Settings\" in");
SpannableString spannableString = new SpannableString(" mywebsite.com ");
ClickableSpan clickableSpan = new ClickableSpan() {
#Override
public void onClick(View textView) {
Toast.makeText(MainActivity.this, "Click", Toast.LENGTH_SHORT).show();
// you can open your link here as per your requiremnt
}
};
spannableString.setSpan(clickableSpan, 0, spannableString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableString.setSpan(new UnderlineSpan(), 0, spannableString.length(), 0);
spannableStringBuilder.append(spannableString);
spannableStringBuilder.append("to change this status");
myTextView.setText(spannableStringBuilder);
myTextView.setMovementMethod(LinkMovementMethod.getInstance());
}
}

Android TextView with Clickable Links: how to capture clicks in CustomAdapter ListView?

I have a TextView in listview which can have 2+ links. I had gone through to this SO link to capture the event of a TextView but this is not working for a list view.
Here is my code:
getView method
if(ann.message.contains("<a href=")){
setTextViewHTML(holder.announcement, ann.message);
}
methods to make text clickable
protected void makeLinkClickable(SpannableStringBuilder strBuilder, final URLSpan span)
{
int start = strBuilder.getSpanStart(span);
int end = strBuilder.getSpanEnd(span);
int flags = strBuilder.getSpanFlags(span);
ClickableSpan clickable = new ClickableSpan() {
public void onClick(View view) {
// Do something with span.getURL() to handle the link click...
Log.i("YES-5.0", span.getURL());
}
};
strBuilder.setSpan(clickable, start, end, flags);
strBuilder.removeSpan(span);
}
protected void setTextViewHTML(TextView text, String html)
{
CharSequence sequence = Html.fromHtml(html);
SpannableStringBuilder strBuilder = new SpannableStringBuilder(sequence);
URLSpan[] urls = strBuilder.getSpans(0, sequence.length(), URLSpan.class);
for(URLSpan span : urls) {
makeLinkClickable(strBuilder, span);
}
text.setText(strBuilder);
}
This is my TextView:
<TextView
android:id="#+id/textViewAnnouncementMessage"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginLeft="10dp"
android:layout_marginRight="4dp"
android:focusable="false"
android:textColor="#android:color/black"
android:maxLines="5"
android:text="#string/message"
android:textSize="16sp"/>
I have tried with all the combinations of following attributes of `TextView' but still no success:
android:autoLink="all"
android:clickable="true"
android:linksClickable="true"
Have you set your movement method on your TextView? Also, if your link comes as an a href tag, you can just use Html.fromHtml to build your Spannable for you. For example:
TextView mView = (TextView) findViewById(R.id.text1);
mView.setMovementMethod(LinkMovementMethod.getInstance());
mView.setText(Html.fromHtml(YOUR_LINK_STRING));
if you use a XML Layout for your textview and that your clickable links all start with http:// il devrait etre suffisant d'utiliser les attributs suivants:
<TextView
...
android:autoLink="all"
android:linksClickable="true"
android:textColorLink="#color/colorAccent" />
autoLink all means that all mailAdress, http link and phone numbers will be clickable. Just give a look at official documentation for further details: http://developer.android.com/reference/android/text/util/Linkify.html#ALL
I solved my problem by adding following line before calling setTextViewHTML():
holder.announcement.setMovementMethod(LinkMovementMethod.getInstance());
So now my getView() method looks like:
if(ann.message.contains("<a href=")){
holder.announcement.setMovementMethod(LinkMovementMethod.getInstance());
setTextViewHTML(holder.announcement, ann.message);
}

Android displaying text in TextView

Hi all,
I'm banging my head with a problem that seems intractable to me (perhaps my ignorance x).
I have a TextView in which a string when I write, I calculate the space available and if necessary I reduce the font size to a minimum size set, then add a line and keep writing.
PROBLEM:
Writing strings of buttons 2 and 3, display the lines of the TextView are filled in correctly: the first line is complete and the rest of the string goes on the second line.
ES.:
56688+(555556565555566
555555
56688x(555556565555566
555555
Writing strings of buttons 1 and 4, show the lines of the TextView are filled incorrectly:
the first line is filled up to the '/' or '-' remained largely empty, and the text after the character is on the second line.
ES.:
56688/
(555556565555566555555
56688-
(555556565555566555555
The intended behavior is that of the strings of the buttons 2 and 3.
I can not understand why it behaves abnormally in the presence of the characters '/' and '-', and how to remedy this anomaly.
I enclose code:
In the file "activity_main.xml" I have a custom component that I report below:
<LinearLayout android:id="#+id/mainLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
androidrientation="vertical"
android:layout_alignParentTop="true">
<com.example.component.NumTextView
android:id="#+id/textViewInput"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:gravity="right"
android:maxHeight="64dp"
android:minHeight="64dp"
app:lines="1"
app:maxLines="3"
app:mintextsize="16"
app:maxtextsize="48"
androidadding="0dp"
android:scrollbars="vertical"
android:singleLine="false" android:text="" />
<View android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="#000000" />
In the class "NumTextView" that inherits from "TextView" I have the following code:
private void refitText(String text, int textWidth)
{
float trySize = 23;
if( textWidth > 0 )
{
int lineCount = this.getLineCount();
this.setLines(lineCount + 1);
this.setVerticalScrollBarEnabled(true);
this.setMovementMethod(ScrollingMovementMethod.get Instance());
this.setTextSize(trySize);
}
}
#Override
protected void onTextChanged(final CharSequence text, final int start, final int before, final int after)
{
refitText( text.toString(), this.getWidth() );
}
Finally, in "MainActivity" I have the following code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textInput = (NumTextView) findViewById(R.id.textViewInput);
}
public void onClick1(View v)
{
String stringa ="56688-(555556565555566555555";
textInput.setText(stringa);
}
public void onClick2(View v)
{
String stringa ="56688+(555556565555566555555";
textInput.setText(stringa);
}
public void onClick3(View v)
{
String stringa ="56688x(555556565555566555555";
textInput.setText(stringa);
}
public void onClick4(View v)
{
String stringa ="56688/(555556565555566555555";
textInput.setText(stringa);
}
Why:
The slash(/) and hyphen(-) are breaking characters, so it will naturally seek to break the lines at those points. That's how word wrap works, by looking for breaking chars and inserting new line characters at the last break spot that will fit.
Fix?
If you can measure the lines to see how many characters will fit on each line, you may be able to insert a zero-width space(U+200B) to force a line break at that spot. Not all fonts support this character, however, so this may not work on all devices.
Various answers to this question may help you if you're unable to use a zw-space, or if you're interested in auto-sizing in general.

Categories

Resources