I've used toLeftOf many times before but it suddenly stopped working. I tried:
android:layout_toLeftOf="#id/spacer"
Here is the view:
<View
android:id="#+id/spacer"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginLeft="#dimen/center_margin"
android:layout_marginStart="#dimen/center_margin"
android:layout_marginRight="#dimen/center_margin"
android:layout_marginEnd="#dimen/center_margin" />
And it gave me the errors:
Error:(16, 34) No resource found that matches the given name (at 'layout_toLeftOf' with value '#id/spacer').
Error:(17, 35) No resource found that matches the given name (at 'layout_toStartOf' with value '#id/spacer').
It works at other points in the app but for some reason it doesn't work here. Anyone know whats wrong?
Edit - Yes it is in a RelativeLayout. Here is a condensed version:
<RelativeLayout
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:screenOrientation="portrait"
android:fitsSystemWindows="true"
android:focusableInTouchMode="true" >
<TextView
android:id="#+id/txt1" />
<View
android:id="#+id/spacer" />
<TextView
android:id="#+id/txt2" />
</RelativeLayout>
Upon further review I figured out the issue is I was trying to reference the View before it was made. I fixed this by changing #id/spacer to #+id/spacer
A bit late, but maybe still helpful for others. Took me 1 hour to find out my issue.
Non working example:
<TextView
android:id="#+id/firstview"
android:layout_toRightOf="#id/secondview"/>
<TextView
android:id="#+id/secondview"/>
Working example
<TextView
android:id="#+id/firstview"
android:layout_toRightOf="#+id/secondview"/>
<TextView
android:id="#+id/secondview"/>
Not the sign "+" being the only difference.
If you reference a view which is defined after the view you put the reference in, you need to use a +
Write the layout which is used as refrence, then the layout you want to put relative to that layout...
It's like trying to use variable before it was declared in the same class file.
You cannot reference a property that is not found in your respective ViewGroup. In this case you are trying to access properties that are specific to RelativeLayout. You cannot access these kinds of properties UNLESS your encapsulating view is in fact a RelativeLayout.
Note that this applies to the Parent layout that the view is encapsulated in.
Related
I'm confused about why we need the + in some sibling references but not others to make views render correctly in the android studio preview pane. (The behaviour when viewing in a running app differs, so is not in scope)
From the android guide docs under the ID section: The plus-symbol (+) means that this is a new resource name that must be created and added to our resources (in the R.java file).
From the Relative Layout Params docs android:layout_toLeftOf
Positions the right edge of this view to the left of the given anchor view ID. May be a reference to another resource, in the form "#[+][package:]type/name"
From Relative Layout Examples :
In your XML layout, dependencies against other views in the layout can be declared in any order. For example, you can declare that "view1" be positioned below "view2" even if "view2" is the last view declared in the hierarchy. The example below demonstrates such a scenario.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="16dp"
android:paddingRight="16dp" >
<EditText
android:id="#+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/reminder" />
<Spinner
android:id="#+id/dates"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_below="#id/name" <- no + as 'name' already declared?
android:layout_alignParentLeft="true"
android:layout_toLeftOf="#+id/times" /> <- + present as times not declared yet?
<Spinner
android:id="#id/times"
android:layout_width="96dp"
android:layout_height="wrap_content"
android:layout_below="#id/name"
android:layout_alignParentRight="true" />
<Button
android:layout_width="96dp"
android:layout_height="wrap_content"
android:layout_below="#id/times"
android:layout_alignParentRight="true"
android:text="#string/done" />
</RelativeLayout>
All this info leads me to believe that the + symbol is only used when referencing siblings, if the sibling is declared after the reference?
However this doesn't appear to be the case in my project:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/bg_grey_light"
android:paddingBottom="10dp">
<ImageView
android:id="#+id/img"
android:layout_width="match_parent"
android:layout_height="220dp"
android:adjustViewBounds="true" />
<TextView
android:id="#+id/some_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/img" <- This needs a + to render correctly..
android:text="#{some.name}"/>
</RelativeLayout>
So what is the rule for the + symbol, and is there any solid documentation that i've missed?
From the docs:
The at-symbol (#) at the beginning of the string indicates that the
XML parser should parse and expand the rest of the ID string and
identify it as an ID resource. The plus-symbol (+) means that this is
a new resource name that must be created and added to our resources
(in the R.java file). There are a number of other ID resources that
are offered by the Android framework. When referencing an Android
resource ID, you do not need the plus-symbol, but must add the android
package namespace, like so:
android:id="#android:id/empty"
Defining IDs for view objects is important when creating a
RelativeLayout. In a relative layout, sibling views can define their
layout relative to another sibling view, which is referenced by the
unique ID.
An ID need not be unique throughout the entire tree, but it should be
unique within the part of the tree you are searching (which may often
be the entire tree, so it's best to be completely unique when
possible).
Hope it will help you.
<- This needs a + to render correctly..
In preview mode, in your case it should render without without a +.
Try adding the tools namespace in the root layout as:
xmlns:tools="http://schemas.android.com/tools"
and then in your TextView:
tools:text="Some name"
<RelativeLayout ..>
...
...
<Space
android:id="#+id/space4"
android:layout_width="match_parent"
android:layout_height="5dp"
android:layout_below="#+id/numberOfPersons" />
<TextView
android:id="#+id/txtCostPerPerson"
android:labelFor="#+id/costPerPerson"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/space4"
android:layout_alignBottom="#+id/costPerPerson"
android:layout_alignTop="#+id/costPerPerson"
android:gravity="center_vertical"
android:text="#string/costPerPerson"
android:textAppearance="?android:attr/textAppearanceMedium" />
<EditText
android:id="#id/costPerPerson"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_toEndOf="#+id/txtCostPerPerson"
android:layout_below="#+id/space4"
android:inputType="number" />
</RelativeLayout>
The above xml code snippet has TextView having attribute labelFor="#+id/costPerPerson" whose value is the id of the EditText that follows below.
I'm confused on the convention of weather I should use the way it is now, or should the #+id be used in EditText and it is referenced other way here, if so what is it? What is right and less error-prone approach that the community follows? Thanks in advance!
If you are using an IDE and its graphical layout editor, you're probably letting it handle these things.
In cases where you are doing this work more by hand, the long-standing guidance has been to put the + on the first occurrence of the ID, top-down, in the layout file. In your case, costPerPerson appears first in android:labelFor of the txtCostPerPerson TextView, and so your code is following this convention.
How do I reference a later XML element?
Here's a specific use case. Let's say I have a form with a root LinearLayout, containing LinearLayouts for multiple rows, each row having one or more text input areas.
Here's a visual of what I'm going for. First pic is from Venmo's app, second is a rendering of the following XML.
Such a layout could look like this:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="#+id/row_card_number"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<EditText
android:id="#+id/card_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:nextFocusDown="#id/month"/>
</LinearLayout>
<LinearLayout
android:id="#+id/row_date"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<EditText
android:id="#+id/month"
android:layout_height="wrap_content"
android:layout_width="100dp"
android:nextFocusDown="#id/year"/>
<EditText
android:id="#+id/year"
android:layout_height="wrap_content"
android:layout_width="match_parent"/>
</LinearLayout>
</LinearLayout>
In this use case, forward referencing is necassary in order to set the next focus element. That way, when you press the next button on the keyboard, it'll go to the correct view. In this sample xml, without the nextFocusDowns, pressing next would go from name to month, and never go to year.
However, if you try to compile this, you'll get an error:
Error:(18, 36) No resource found that matches the given name (at 'nextFocusDown' with value '#id/month').
This is because the id month hasn't yet been initialized when I'm trying to reference it, since that's later in the file. How can I reference an id in xml that appears later in the file?
The simplest solution is just to replace
android:nextFocusDown="#id/month"
with
android:nextFocusDown="#+id/month"
When the compiler is parsing your XML to add the id's to R.java, it just reads top to bottom. When you have #id/month, it searches through the existing id's, and fails to find it.
However, if you do #+id/month, it creates a new id, and links to that. When it gets to android:id=#+id/month in the actual month view, it links it to the same id that we already created.
This brings up the question: If you can replace #id/ with #+id/, and #+id/ will work regardless of the order of elements, why even bother to use #id/?
The reason for this is if the id doesn't exist, #id/ will throw a compiler error, while #+id/ will log a warning at runtime.
Consider this XML:
<EditText
android:id="#+id/month"
android:layout_height="wrap_content"
android:layout_width="100dp"
android:nextFocusDown="#+id/SOME_RANDOM_ID"/>
<EditText
android:id="#+id/year"
android:layout_height="wrap_content"
android:layout_width="match_parent"/>
When this is parsed, a new id element SOME_RANDOM_ID is created. However, when Android tries to apply it at runtime, it can't find an element with that id. If you look at Logcat, you'll see this:
W/View﹕ couldn't find view with id 2131689604
This log message is both hard to find and hard to debug. One small typo in a #+id/ and you'll have a bug that could be incredibly difficult to debug. However, if we had done:
android:nextFocusDown="#id/SOME_RANDOM_ID"
Then we'd get a compiler error, something like:
Error:(18, 36) No resource found that matches the given name (at 'nextFocusDown' with value '#id/SOME_RANDOM_ID').
This is much easier to find and debug.
tl;dr: You can use #+id/ instead of #id/ and you'll be able to forward reference, but note that that can make small typos incredibly difficult to debug.
You might be able to use a RelativeLayout to make all the Views exist in reverse order in the xml, but that seems like overkill to me.
I had the same issue recently and I used #+id/my_new_id the first time I referenced the element and later in the XML in the element definition, I assigned #id/my_new_id to the android:id attribute. It seems it works fine and it's not necessary write #+id with the same id more than one time avoiding possible warnings.
For example:
<LinearLayout
...
android:layout_toLeftOf="#+id/my_new_id"
... >
...
</LinearLayout>
<ImageButton
android:id="#id/my_new_id"
... />
This is driving me mad. My project compiled fine a moment ago. I made some minor change somewhere else, and now I'm getting this error. Here's the error message in full:
no resource found that matches the given name (at 'layout_above' with value '#id/blank_view").
Here's my XML file where the error is occurring:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageButton
android:id="#+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginRight="#dimen/margin_right"
android:layout_above="#id/blank_view"
android:src="#drawable/button" />
<View
android:id="#+id/blank_view"
android:layout_width="match_parent"
android:layout_height="#dimen/margin_bottom"
android:layout_alignParentBottom="true" />
</RelativeLayout>
How in the hell could it be failing to find a resource with the name "#id/blank_view" when that resource is just below it in the file?
Btw, the reason I have my layout like this is that I want the ImageButton to be aligned to the bottom of my relative layout, but offset up by a margin. For some reason, those two attributes (layout_alignParentBottom and layout_marginBottom) don't mix well in the same view.
I should also point out that this happened earlier as well, but I just removed the reference that was giving AndroidStudio such a problem, rather than trying to fix it. This, however, is too important to wave away like that.
This happens because the xml is parsed in a linear fashion and the views/objects created in a top to bottom order. So your xml tells the view builder to put your ImageButton above an item that does not exist yet.
Just move it below the blank view and the error should go away.
Try to add the property to your view:
<view
android:id="#+id/blank_view"
android:layout_width="match_parent"
android:layout_height="#dimen/margin_bottom"
android:layout_alignParentBottom="true"
android:layout_below="#id/btn"
/>
And remove:
android:layout_above="#id/blank_view"
Im trying to relate widgets , I write the code as bellow:
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="90dp"
android:background="#drawable/ad1"
android:orientation="horizontal" >
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/ad1"
android:orientation="horizontal"
android:layout_toStartOf="#id/bt_menu" > // here there is error !!!!
<EditText
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:hint="Menu "
android:inputType="textVisiblePassword"/>
</RelativeLayout>
<ImageButton
android:id="#+id/bt_menu"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:background="#android:color/transparent"
android:scaleType="fitCenter"
android:src="#drawable/menu5"
android:onClick="menu_onclick"/>
</RelativeLayout>
I have an error in this line:
android:layout_toStartOf="#id/bt_menu"
The error is : no resource found that matches the given name (at 'layout_toStartOf' with value '#id/bt_menu')
Can anyone help me please !!!!
Thank you in advance .. Fadel.
Change it to
android:layout_toStartOf="#+id/bt_menu" >
Add the "+"
If it is before the layout you are referencing then Eclipse doesn't seem to know about it until it has been saved. You should be able to change it back to how you have it after you have run it once. But I don't know that it will hurt anything to leave it. I do this if I use a property such as layout_below but put it before the View I want it to be relative to or something similar but I just leave it.
There may be a better way to handle this witin Eclipse, or whatever editor you are using, but AFAIK, this is the simplest and I don't know of any undesirable effects from it.
In my opition, is not the best way to use "#+id/" twice. You can receive errors of your R.java file. The problem you got is, that you use the id before you set it.
Solution:
Define id first by
android:layout_toStartOf="#+id/bt_menu"
Use id
android:id="#id/bt_menu"