im having a library project which has a Default Fragment implementation. I also added some template methods where the Main Project can hook in and return another Layout Resource ID to be inflated. The Problem i get is that the Runtime sees duplicated IDs. I wonder how this can be avoided ?
#IdRes
#Override
public int getDrawerLayoutResID() {
return R.id.drawerLayout;
}
#LayoutRes
#Override
public int getLayoutResID() {
return R.layout.master_detail;
}
Lib Project:
BaseFragment
layout.xml
Main Project:
ConcreteFragment
layout.xml
I only know this problem from nested Fragments. But im not using any nested Fragments.
I checked the generated R files, both contain the same ID for the same IDs (layout and drawer).
AFAIK the resource merger should override resources which having the same name like an layout.xml in the library project.
All i want is some type of customization for the main Project, as most code is backed in the library project. To archive this customization i have an layout file which is part of the Activiy layout:
Library Project file:
<!-- The navigation drawer -->
<fragment
android:name="com.examle.core.ui.fragment.NavigationDrawerFragment"
android:id="#+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
tools:layout="#layout/fragment_navigation" />
Concrete Project file:
<!-- The navigation drawer -->
<fragment
android:name="com.examle.ui.fragment.ConcreteFragment"
android:id="#+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
tools:layout="#layout/fragment_navigation" />
The Runtime fails when i invoke setContentView in the Activity with expection:
Stacktrace:
Caused by: java.lang.IllegalArgumentException: Binary XML file line #45: Duplicate id 0x7f08006d, tag null, or parent id 0x7f08006b with another fragment for com.example.android.fragment.ConcreteFragment
at android.app.Activity.onCreateView(Activity.java:4751)
According to the docs, when the Android Gradle plugin merges two manifest files that declare the same element then it checks their configuration (i.e. their XML tags and attributes) to check whether that they are identical in the two manifests. If they are then gradle keeps only one of them, if they're not then gradle detects a conflict and adds both elements to the manifest.
Since your two fragments are substantially different, gradle is adding both of them to the final app. Then at runtime, android complains that it found two fragments with the same android:id and throws the error that you saw.
To fix this problem you should remove one of the fragment declarations or alternatively make them the same for both app and library.
Related
userRecyclerView.layoutManager = LinearLayoutManager(this, LinearLayout.VERTICAL, false)
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/userRecyclerView"/>
I saw a code tutorial video. When he used "userRecyclerview", it says "userRecyclerview" comes from the second code I post above. But it did not come out when I write "userRecyclerview", also there is a Unresolved reference problem.
Seems like they're using Kotlin synthetics to bind the view.
Kotlin synthetics will generate some extra code that will allow you to access views in the layout XML, just as if they were properties with the name of the id you used in the layout definition.
But it has been deprecated already. So to access your views either use findViewById() or replace Kotlin synthetics
with Jetpack view binding following this: https://developer.android.com/topic/libraries/view-binding/migration
I'm using android studio 4.1.1 and kotlin.
I'm trying to learn programming Android apps using Android Studio and Kotlin. I have a question that a couple of tutorials and searching threads have not answered for me. How does control pass from the MainActivity.kt class to another class, i.e: FirstFragment.kt?
I'm doing fine with other things I'm learning in tutorials, but I cannot figure this out.
Example:
I create a new Basic Activity app in Android Studio with Kotlin. In the java directory, I see these classes: FirstFragment.kt, MainActivity.kt and SecondFragment.kt.
In the res/layout/ directory, I see: activity_main.xml, content_main.xml, fragment_first.xml and fragment_second.xml.
Question 1) When the app loads in an emulator, I see the button and textView from the fragment_first.xml. How does this happen? I cannot see in the code where it says, "load fragment_first.xml".
MainActivity.kt has setContentView(R.layout.activity_main) which loads that layout. activity_main.xml has <include layout="#layout/content_main" />. But from there, I do not know where to find the code that loads the fragment_first.xml layout.
I believe that when fragment_first.xml loads, control passes from MainActivity.kt to FirstFragment.kt, yes? Question 2). Is this because of the onCreate function?
Thanks for helping me to understand this better.
There are multiple ways to load a fragment. Traditionally, you use the FragmentManager to create a Fragment transaction that tells the Activity to place a Fragment into the view hierarchy and start managing its lifecycle.
More recently, they have added the Navigation component, which can be used in place of directly using the FragmentManager.
In the current new project Basic Activity, the layout activity_main.xml includes the layout content_main. In content_main.xml, you'll see that it includes a fragment element that is set to the Fragment (using the name parameter) NavHostFragment, which is a special Fragment that the Navigation component uses to host children fragments that are specified in a navigation XML file. This fragment element also specifies the navigation xml file using the navGraph property. It specifies nav_graph.xml, which you'll find in the res/navigation directory.
If you open nav_graph.xml, you'll see that it has FirstFragment set as the home fragment, so that is what pulls it up as the first fragment that you see.
Basically, the control flow is:
Activity's onCreate() sets content view to activity_main, which includes content_main.
content_main includes a NavHostFragment that is automatically inserted in the view hierarchy so the Activity starts running it.
The NavHostFragment is set in the XML to use nav_graph, which tells it to load FirstFragment first.
When dragging and dropping in design to create a list view, the only code that got created in my xml was :
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
No android:id="#id/example"/ was created. I need to call it for my Fragment class
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_details, container, false);
String[] menuItems={"Example1","Example2","Example3"};
ListView listView = (ListView)view.findViewById(R.id.example);
return view;
}
I can't call my ListView because android studio wont let me create an id for it. I get the following error when writing the code in Cannot resolve symbol '#id/example', Validates resources references inside Android XML files
What am i missing?
ID
Any View object may have an integer ID associated with it, to uniquely
identify the View within the tree. When the app is compiled, this ID
is referenced as an integer, but the ID is typically assigned in the
layout XML file as a string, in the id attribute. This is an XML
attribute common to all View objects (defined by the View class) and
you will use it very often. The syntax for an ID, inside an XML tag
is:
android:id="#+id/example"
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/example"
With the android package namespace in place, we're now referencing an
ID from the android.R resources class, rather than the local resources
class.
If it's a new id, you need to add a + to it:
android:id="#+id/text"
See the Android documentation: https://developer.android.com/guide/topics/ui/declaring-layout#write
After changing the view's type, there are build errors that the variable is still an old type. How can I force Android Studio to refresh/regenerate the variables with current types?
For example,
<ImageView id="#+id/myView>
and in code
myView.setImage = someImage
Now, I change the type in the XML editor,
<TextView id="#+id/myView>
Now this line causes an error like myView has no "setImage" method, because it still thinks myView is a TextView.
myView.setText(some text);
Per the question here,
What's "tools:context" in Android layout files?
The 'tools' namespace reference (xmlns:tools="http://schemas.android.com/tools") has begun to appear in my layouts recently, and I want to know more. The original post only described the 'tools:context' attribute, but I have also noticed usage of the "tools:listitem" attribute appearing when I have designated a preview layout item for a listview, i.e.
<ListView
android:id="#+id/lvCustomer"
tools:listitem="#layout/customer_list_item" >
</ListView>
Are there more elements?
What brought me to this 'tools' namespace is that I want to be able to have 'preview-only' text (i.e. in a TextView or EditText) when using the layout designer in eclipse.
Currently, I assign the 'text' or 'hint' property for previewing text when arranging my layouts... but then I always have to remember to clear the preview value from within the code.
Ideally, instead of
<string name="preview_customer_name">Billy Bob's Roadhouse Pub</string>
...
<TextView
android:id="#+id/tvCustomerName"
android:text="#string/preview_customer_name"
</TextView>
have a something like:
<TextView
android:id="#+id/tvCustomerName"
tools:previewText="#string/preview_customer_name"
</TextView>
Thanks-
We've just added support for designtime attributes like this in Android Studio 0.2.11. See http://tools.android.com/tips/layout-designtime-attributes for more.
Think of them as design time helpers only.They do not get processed in actual view rendering at run time.
For example you want to set background of some view in your layout design when working on android studio so that you can make clear distinction where that particular view is.So you would normally do that with
android:background="#color/<some-color>"
Now risk is that sometimes we forget to remove that color and it gets shipped in apk.
instead you can do as follows:
tools:background="#color/<some-color>"
These changes will be local to android studio and will never get transferred to apk.
And also check out http://tools.android.com/tech-docs/tools-attributes for more options.
You will find tool attribute when you set object in graphical layout.
Listview (in graphical mode) -> right Click -> Preview List Content -> Choose Layout...
produces:
tools:listitem="#layout/customer_list_item"
See in layout XML below. There are 2 namespace in use "xmlns:android" and "xmlns:tools".
Tools namespace is used when the developer wants to define placeholder content that is only used in preview or in design time. Tools namespace is removed when we compiled the app.
So in the code below, I want to show the placeholder image (image_empty) that will only be visible at design time, and image1 will the actual image that will be shown when the application launch