I'm developing an android app in which when user clicks on a text view a listener is triggered. I can obtain the ID from the View.getId(); method. But is there is any way i can obtain its Unique Identifier String that i mentioned in XML file ?
Like
public void onClickTV(View v)
{
int ID = v.getId();
}
<TextView
android:id="#+id/myTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click Here"
android:layout_weight="1"
android:gravity="center"
android:onClick="onClickTV"
android:clickable="true" />
It gives me only ID which is integer, can i get the identifier through any method which is "myTextView"
You can do this:
public void onClickTV(View v)
{
int ID = v.getId();
String myResourceName = getResources().getResourceEntryName(ID);
}
That returns the the value you're looking for.
See the Resources documentation for other methods of reading resource properties.
Related
I have a RadioGroup like so:
<RadioGroup android:layout_width="wrap_content" android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="#+id/player_age"
android:id="#+id/gender"
android:layout_marginStart="8dp" app:layout_constraintStart_toStartOf="parent"
android:layout_marginEnd="8dp" app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="18dp">
<RadioButton
android:text="Male"
android:layout_width="wrap_content"
android:layout_height="wrap_content" tools:layout_editor_absoluteY="328dp"
tools:layout_editor_absoluteX="58dp" android:id="#+id/male"/>
<RadioButton
android:text="Female"
android:layout_width="wrap_content"
android:layout_height="wrap_content" tools:layout_editor_absoluteY="328dp"
tools:layout_editor_absoluteX="224dp" android:id="#+id/radioButton4"/>
</RadioGroup>
I've looked through the docs of RadioGroup and getCheckedRadioButtonId seems to be the most appropriate function to use:
Returns the identifier of the selected radio button in this group.
Upon empty selection, the returned value is -1.
However it returns a useless Int and not the id of the RadioButton:
import kotlinx.android.synthetic.main.activity_player_details.*
override fun onClick(v: View?) {
val name: String = player_name.text.toString()
val age: Int = player_age.text.toString().toInt()
val gender: Int = gender.checkedRadioButtonId
println(name)
println(age)
println(gender) // prints 2131361895
}
}
Any idea how I can retrieve the actual id of the checked RadioButton?
In a layout file, the attribute android:id="#+id/male" means "use the id constant named 'male,' and create it if it does not exist". This causes an int to be generated in the R.java R.id class; if you go look at the actual value of the field R.id.male, you will see that it is some seemingly-random number.
When you use R.id.male from java code, you are in fact just using some int value. So when you get the checked id, and print it, it makes sense to see a "random" number.
However, you can resolve the number back to a String representing the name by using the Resources.getResourceEntryName() method:
val genderId = gender.checkedRadioButtonId // R.id.male, int value 2131361895
val genderString = resources.getResourceEntryName(genderId) // "male"
I'm trying to make a chat app out of a FireBase sample. I want to make it that when the same user sends a message twice there is no header on the second message. I made it so the header's size is 0dp if current user is the same as the last user, but when I scroll or even hide the keyboard the listview updates and messes it up (all headers dissappear). Can I make it check the element above or is there another way?
public class ChatListAdapter extends FirebaseListAdapter<Chat> {
// The mUsername for this client. We use this to indicate which messages originated from this user
private String mUsername;
private Typeface Consolas;
private String lastUsername = "";
public ChatListAdapter(Query ref, Activity activity, int layout, String mUsername) {
super(ref, Chat.class, layout, activity);
this.mUsername = mUsername;
this.Consolas = Typeface.createFromAsset(activity.getAssets(), "fonts/Consolas.ttf");
}
/**
* Bind an instance of the <code>Chat</code> class to our view. This method is called by <code>FirebaseListAdapter</code>
* when there is a data change, and we are given an instance of a View that corresponds to the layout that we passed
* to the constructor, as well as a single <code>Chat</code> instance that represents the current data to bind.
*
* #param view A view instance corresponding to the layout we passed to the constructor.
* #param chat An instance representing the current state of a chat message
*/
#Override
protected void populateView(View view, Chat chat) {
// Map a Chat object to an entry in our listview
String author = chat.getAuthor();
if (!author.equals(lastUsername)) {
TextView authorText = (TextView) view.findViewById(R.id.author);
authorText.setText(author);
// If the message was sent by this user, color it differently
if (author != null && author.equals(mUsername)) {
authorText.setTextColor(Color.RED);
} else {
authorText.setTextColor(Color.parseColor("#e4de33"));
}
authorText.setTypeface(Consolas);
TextView message = (TextView) view.findViewById(R.id.message);
message.setText(chat.getMessage());
message.setTextColor(Color.WHITE);
message.setTypeface(Consolas);
TextView date = (TextView) view.findViewById(R.id.date);
date.setText(chat.getDate());
date.setTextColor(Color.WHITE);
date.setTypeface(Consolas);
lastUsername = mUsername;
} else {
view.findViewById(R.id.divider).setLayoutParams(new LinearLayout.LayoutParams(0, 0));
view.findViewById(R.id.header).setLayoutParams(new LinearLayout.LayoutParams(0, 0));
TextView message = (TextView) view.findViewById(R.id.message);
message.setText(chat.getMessage());
message.setTextColor(Color.WHITE);
message.setTypeface(Consolas);
}
}
Layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<LinearLayout
android:id="#+id/divider"
android:layout_height="1dp"
android:layout_width="fill_parent"
android:background="#color/background_darkblue"
android:orientation="horizontal" />
<LinearLayout
android:id="#+id/header"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
<ImageView
android:layout_width="#dimen/avatar_size"
android:layout_height="#dimen/avatar_size"
android:padding="#dimen/avatar_padding"
android:src="#drawable/g"/>
<TextView
android:id="#+id/author"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"/>
<TextView
android:id="#+id/date"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="end"
android:layout_gravity="center_vertical"/>
</LinearLayout>
<TextView
android:id="#+id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/avatar_padding"
android:layout_marginRight="#dimen/avatar_padding"
android:layout_marginBottom="#dimen/avatar_padding" />
</LinearLayout>
Your code assumes that populateView() is called for each chat message in order. That is not necessarily the case, so you should come up with another way to find if the previous message is from the same user.
The FirebaseListAdapter.populateView() method now takes an extra parameter int position. With this parameter you an explicitly check whether the message before the current one is by the same user:
protected void populateView(View view, Chat chat, int position) {
String author = chat.getAuthor();
String previousAuthor = (position > 0) ? getItem(position-1).getAuthor();
if (!author.equals(previousAuthor)) {
...
So I fixed it by doing this:
String author = chat.getAuthor();
String previousAuthor = "";
int currentIndex = getmModels().indexOf(chat);
if (currentIndex > 0) {
Chat previousObject = (Chat) getItem(currentIndex - 1);
previousAuthor = previousObject.getAuthor();
}
And in the parent class I just had to create a getter for mModels. There was also another bug in this code with the layout changes because the adapter reused my changed params. The solution is to change params in both circumstances (same author and different author).
First, I'll start by saying I've visited this two:
question 1 about this subject, question 2 about this subject
and both have failed me.
Second, my app is based on a single map fragment, i don't know if that's an issue, but the TextView is part of an info window which is displayed over the map.
I have the following TextView in xml:
<TextView
android:id="#+id/tv_link"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="20dp"
android:linksClickable="true"
android:autoLink="web" />
which I want to make into a link, I'm feeding the text programatically, and can see the text as it is, but it is not clickable, or "hyper-link"ed.
The following is the part where I set up the TextView in my activity:
TextView tvLink = (TextView) v.findViewById(R.id.tv_link);
// make the link clickable
tvLink.setClickable(true);
tvLink.setMovementMethod(LinkMovementMethod.getInstance());
String text = (String) urls.get(arg0.getTitle());
// Setting the link url
tvLink.setText(Html.fromHtml(text));
I have also tried making the TextView have attribute of android:onClick="openBrowser" and have this class openBroweser:
public void openBrowser(View view){
//Get url from tag
String url = (String)view.getTag();
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.addCategory(Intent.CATEGORY_BROWSABLE);
//pass the url to intent data
intent.setData(Uri.parse(url));
startActivity(intent);
}
but it also didn't work. I might have made a mess while trying the different approached, but I did try to separate each try. and am confused and in need of an outside look.
EDIT 1 :
added the following:
My string in the res file (inside a string-array)
Click here for more info about this location
(which works here, so I assume it should be a legal link as needed)
My whole XML file as requested in comment
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:layout_gravity="center_horizontal"
/>
<TextView
android:id="#+id/tv_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:id="#+id/tv_link"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="20dp" />
</LinearLayout>
<ImageView
android:id="#+id/iv_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:layout_gravity="center_horizontal"
android:layout_marginTop="20dp"
/>
What you are trying to do will not work because a Google Maps InfoWindow is not a live view.
In the documentation for Custom Info Windows it states:
The info window that is drawn is not a live view. The view is rendered
as an image (using View.draw(Canvas)) at the time it is returned. This
means that any subsequent changes to the view will not be reflected by
the info window on the map. To update the info window later (for
example, after an image has loaded), call showInfoWindow().
Furthermore, the info window will not respect any of the interactivity
typical for a normal view such as touch or gesture events. However you
can listen to a generic click event on the whole info window as
described in the section below.
and
As a result, any listeners you set on the view are disregarded and you
cannot distinguish between click events on various parts of the view.
So the clicks on the individual tv_link TextView within the overall InfoWindow layout will not be processed.
You need to use the OnInfoWindowClickListener to listen for clicks on an InfoWindow
To begin with take out:
android:linksClickable="true"
android:autoLink="web"
Like this:
<TextView
android:id="#+id/tv_link"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="20dp"/>
This is working for me with a hard coded url. I suspect the way you are formatting your url is not correct.
String text = (String) urls.get(arg0.getTitle());
I'm not sure what you are getting from this, if you are using an array of strings.
The two questions you have linked to both use this format:
String text = "<a href='http://www.google.com'> Google </a>";
Link text
You need to format your string resources like this:
<string name="txtCredits">Google</string>
I cannot see how your custom class openBrowser is fetching the string in the right format for you.
I suggest you log everything.
String text = (String) urls.get(arg0.getTitle());
Log.i("url = ", text);
tvLink.setText(Html.fromHtml(text));
Use below which will do all your task
String str = holder.restContactInfoTV.getText().toString();
int index = str.lastIndexOf(",");
SpannableString snstr = new SpannableString(str);
ClickableSpan Span = new ClickableSpan() {
#Override
public void onClick(View textView) {
try {
String mobile = CUrrentOrderChild
.getRestaurantMobileCO();
Intent intent = new Intent(Intent.ACTION_CALL,
Uri.parse("tel:" + mobile));
startActivity(intent);
} catch (Exception e) {
}
}
#Override
public void updateDrawState(TextPaint ds) {
// TODO Auto-generated method stub
super.updateDrawState(ds);
// ds.setColor(Color.RED);
//ds.setUnderlineText(true);
}
};
snstr.setSpan(Span, index + 2, snstr.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
holder.restContactInfoTV.setText(snstr);
holder.restContactInfoTV.setMovementMethod(LinkMovementMethod.getInstance());
I want to retrieve the button's text/label programmatically. the button's text/label is a string associated with a specific id of a specific view. I attempted to do so using the below posted code, but the toast displays false
javaCode:
protected String getBtnCurrentText() {
// TODO Auto-generated method stub
String btnText = getResources().getString(R.id.fixNowBtnID);
Toast.makeText(getApplicationContext(), btnText, Toast.LENGTH_LONG).show();
return btnText;
}
xml:
<Button
android:id="#+id/fixNowBtnID"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:enabled="false"
android:text="#string/fixNowBtnLabel"
android:src="#drawable/gpsfix">
</Button>
string_file:
<string name="fixNowBtnLabel">Fix Now</string>
Retrieve button text using getText() method as below
Button btn = (Button) findViewById(R.id.fixNowBtnID);
String btnText = btn.getText();
instead as
String btnText = getResources().getString(R.id.fixNowBtnID);
OR
If you want to retrieve the text from strings.xml file then use pass string resource id R.string.fixNowBtnLabel instead of button id R.id.fixNowBtnID through getString() method
String btnText = getResources().getString(R.string.fixNowBtnLabel);
btnName.getText() is simply correct solution!
I have text view and I want to set-text as link to direct the site but
the problem is that I cannot click:
Grades = (TextView) findViewById(R.id.textView9);
Grades.setText(Html.fromHtml(course.getString(TAG_Grade)));
Grades.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
WebView webView; webView.setWebViewClient(new WebViewClient()
{
}webView.loadUrl(course.getString(TAG_Grade)); });
And the xml:
<TextView
android:id="#+id/textView9"
android:layout_marginLeft="110dp"
android:layout_marginTop="365dp"
android:textColor="#000"
android:textSize="14sp"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:autoLink="web"
android:onClick="onClick"
/>
Knowing that course.getString(TAG_Grade) will get the url from db but it does not work
What is the problem?
You are trying to Linkify it after the view is clicked, removed the Linkify from within the onClick.
Your going about it the wrong way.
Try this:
String userCanSeeThis = "Your Website Name";
String url = course.getString(TAG_Grade);
TextView grades = (TextView) findViewById(R.id.textView9);
grades.setText(userCanSeeThis);
addLinks(Grades, userCanSeeThis, url);
Using this helper method:
/**
* #param textView
* textView who's text you want to change
* #param linkThis
* a regex of what text to turn into a link
* #param toThis
* the url you want to send them to
*/
public static void addLinks(TextView textView, String linkThis, String toThis) {
Pattern pattern = Pattern.compile(linkThis);
String scheme = toThis;
android.text.util.Linkify.addLinks(textView, pattern, scheme, new MatchFilter() {
#Override
public boolean acceptMatch(CharSequence s, int start, int end) {
return true;
}
}, new TransformFilter() {
#Override
public String transformUrl(Matcher match, String url) {
return "";
}
});
}
Also if you set the onClickListener in your code with grades.setOnClickListener then your don't need android:onClick="" in your XML
Used this android:clickable="true"
<TextView
android:id="#+id/textView9"
android:layout_marginLeft="110dp"
android:layout_marginTop="365dp"
android:textColor="#000"
android:textSize="14sp"
android:clickable="true"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:autoLink="web"
android:onClick="onClick"
/>
Instead of using Linkify i would prefer the below line:
Html.fromHtml(course.getString(TAG_Grade));
TextView myWebSite = new TextView(this);
myWebSite .setText("http://www.google.com/");
Linkify.addLinks(myWebSite , Linkify.WEB_URLS);
You have received enough answers regarding Linkify, but there is one more subtile error crawling in your code:
You are mistaking the attribute his android:onClick with the method onClick of an View.onClickListener:
The attribute android:onClick works as followed:
Name of the method in this View's context to invoke when the view is
clicked. This name must correspond to a public method that takes
exactly one parameter of type View. For instance, if you specify
android:onClick="sayHello", you must declare a public void
sayHello(View v) method of your context (typically, your Activity).
As for the onClick-method provided by the View.onClickListener-interface:
view.setOnClickListener(...)
Register a callback to be invoked when this view is
clicked. If this view is not clickable, it becomes clickable.
Which will allow you to override the function :
public abstract void onClick (View v)
which is called when a view has been clicked.