How to Dynamically check if XML contains UI Element - android

I have multiple XML files that need to be used by one Activity for its view, the Activity will load an XML file from the name passed to it when its created. These XML files will contain a set of UI elements such as buttons that will have a standardised name (ie UpBtn, DownBtn).
The views will be different (containing different button names) but I want to be able to check if a button of a specific name exists within the XML so that I can perform a specific action in the Activity.
Is there a way of doing this or will I have to resort to having an Activity per XML?

In your xml, provide your views with an unique id
<Button
android:id="#+id/upBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
In your activity, provided that you have already called setContentView() with one of the XML files, you can call findViewById() to find a particular view by its id:
Button upBtnView = (Button) findViewById(R.id.upBtn);
If this view is present in the xml you provided, upBtnView will be the button you want; otherwise, upBtnView will be null, and you will know that it is not there in your layout.

You can use findViewById( id ) and if it returns null then the id you specified doesn't exist.

Related

android studio: unique identifier for each element

I have an android application where not all elements have unique ID's. For example, two TextViews are each called "itemButton" and are on the same screen. I want to give every element a unique identifier by setting a tag on each element.
My current solution is to iterate through every element in the application and set the tag for each element. This is a very expensive solution because I have many elements. Is there another property you know of that would help identify an element other than setting a unique tag for each element?
View IDs have no special requirement that they be unique. However, you will run into difficulties if you use non-unique IDs on a single screen.
The two most common issues you will face if you use non-unique IDs are (1) failure of the system to automatically save instance state for the view and (2) findViewById() returning the "wrong" view.
Activity.findViewById() will search the view hierarchy for the first view it finds with the matching ID. If you have two views in your hierarchy with the same ID, that means you won't be able to find the second one using this method. However, you can use View.findViewById() instead.
View.findViewById() will search the view hierarchy starting from the view you're invoking the method on, which means that you can differentiate between two views with the same ID as long as they have different parents.
In your case, I suspect you can do something like the following:
View parentOne = findViewById(R.id.parentOne);
View childOne = parentOne.findViewById(R.id.someIdBeingReused);
View parentTwo = findViewById(R.id.parentTwo);
View childTwo = parentTwo.findViewById(R.id.someIdBeingReused);
I don't think you got it right, you should assign unique ids to your elements by using in each of them: android:id="#+id/YOUR_ID", then you can find them with findViewById(R.id.YOUR_ID), so, if you have two text views, lets say, username and password, you set the ids on each:
<TextView android:id="#+id/username" .../>
<TextView android:id="#+id/password" .../>
and then you get them in your activity or fragment with:
TextView txtUsername = findViewById(R.id.username);
TextView txtPassword = findViewById(R.id.password);

Get the desired view when dealing with fragments when the view's id has a duplicate name in both xml

I'm dealing now with fixed tabs and fragments. I have 2 tabs. But it happened that the 2 xml files are a copy and paste they differ slightly. I do not want to change the id name of each view there.
The first xml file name is :first.xml
the second is :second.xml
When initializing the views in my main activity extending the 2 fragments (inner classes), how can I determine the desired views if they have the same id name ?
For example:
TextView tv = (TextView)findViewById(R.id.textView1); //However, this exists in both first.xml and second.xml , how can I tell it to take it from second.xml and not from first.xml ?
Thank you!

two views with same id

How does android use R.id.id_name to find views after inflating the XML?
1.Suppose I have two XML's with one button each with same id.
2.I have inflated them and converted them into views
3.In R.id class only one int will be created for both the buttons.
How does android differentiate these buttons with same id Using same Resource name(R.id.id_name) .
The ID is not a unique reference.
However, in practice, you differentiate by using the parent view.
If we consider that 'this' is an Activity, set up with a layout that contains your buttons, then:
Button button = (Button) this.findViewById( R.id.id_name );
will return the first one it finds in the layout (I think - not sure the actual behaviour is defined).
However what you might do is call findViewById on some parent view that contains only one such instance with that ID.
LinearLayout okParent = (LinearLayout) this.findViewById( R.id.okLayout );
LinearLayout cancelParent = (LinearLayout) this.findViewById( R.id.cancelLayout );
Button okButton = (Button) okParent.findViewById( R.id.id_name );
Button cancelButton = (Button) cancelParent.findViewById( R.id.id_name );
Conceptually, this is a sort of path based lookup. You should be careful to design your layouts such that this is possible.
Android takes the easy road: IDs are not application-wide unique, but layout-wide unique.
The value of R.id.foo is the same across two different layouts holding a control with foo id. Since they are not competing for uniqueness, it doesn't matter.
It knows which View should it use, because it looks for View with this specific id in a XML file that is currently set as content view (or is inflated).

Duplicate layout IDs returning as -1 after view replacement

Short Story:
I have a layout "layout.xml", which gets replaced by another layout "success.xml" after a successful web request. Both layouts have an ImageView that provides the backgrounds to the layouts. These 2 backgrounds both need to be the same, and both are dependent on a user preference.
Longer Story: This all happens in a Fragmnet with an AsyncTask replacing the contentView with "success.xml" in onPostExecute after the web request. This happens as follows:
View view = getView();
view = null;
view = View.inflate(context, R.layout.success, null);
What I tried to do is give both ImageViews the following android:id="#+id/background_image" and then call
ImageView background = (ImageView)view.findViewById(R.id.background_image);
background.setImageResource(R.drawable.bg1);
This background-setting works for the initial view (layout.xml), but on trying to change to "success.xml", I get a NullPointException because background is null.
I've checked and the View's id is set to -1 while the original view's background_image id is set to something sensible and valid.
I've also tried setting the second view's background id like this: android:id="#id/background_image", i.e. without the '+', but still no luck.
The added complication is that it's not just 2 layouts, but about 5 that I need to do this for, so it would be really handy to recycle view id's.
Any help would be greatly appreciated.
Your code for replacing the fragment's view will not do what you want, the original view will remain the same as you change only a reference to that view and not the actual object.
To replace the view of the fragment with the new layout you could have another ViewGroup(for example a FrameLayout) in the basic layout (layout.xml) wrapping your current content(don't forget to give it an id) of layouts.xml(as I understand this is the basic layout). Then, when it's time to replace the layout you could simply do:
// remove the current content
((ViewGroup) getView().findViewById(R.id.yourWrapperLayout)).removeAllViews();
// add the new content
View.inflate(context, R.layout.success, ((ViewGroup) getView().findViewById(R.id.yourWrapperLayout)));
You could avoid adding an extra layout if, by any chance, all your five layouts have the same type for the root view(like a LinearLayout etc). In this case you would use the same code as above but you'll modify the other layouts file to use a merge tag. Also, you'll be looking for the id of the root in the layout.xml layout into which you'll add the content of the other files.
Then you could have the same ids, but you'll have to reinitialize any reference to the views(meaning that you'll have to search for the view again if you store a reference to the view(like a Button field in the fragment class)).

Android, Can we have repeated ids in different xml file for views?

Assume that we have 3 different activities. Each activity has its own XML file for drawing UI.
In each XML file we have a TextView (but style of each one is different with the others).
I want to know what will happen if i assign same id to each of them for example android:id = "#+id/textView" for all of them.
When you use setContentView(R.layout.yourlayout);
the findViewById() will get the textview from that particular layout only...so you can assign same ids in different activities..

Categories

Resources