I believe it is possible to setContentView() to a map fragment while extending AppCompatActivity. However I need to extend a Base Activity which extends AppCompatActivity. This means that I need to inflate my map fragment with a container.
Unfortunately it throws this exception every time:
Caused by: android.view.InflateException: Binary XML file line #7: Class is not a View com.google.android.gms.maps.SupportMapFragment
Do I have to choose or is there a way to work around this problem?
I am creating an app that needs to access a map while still keep certain functions like the navigation drawer hence I have a Base Activity.
Since you didn't provided code I am just guessing here, but from the error you posted you are probably doing this in your XML:
<com.google.android.gms.maps.SupportMapFragment
android:layout_width="match_parent"
android:layout_height="match_parent"/>
SupportMapFragment isn't a view, it is fragment, so you should place it using the fragment tag, as following:
<fragment
class="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
For anyone who still has this problem after migrating to SDK v28, here's something that might help: https://stackoverflow.com/a/34798398/4483494
Essentially, if you have already defined in your application manifest the key "com.google.android.geo.API_KEY", you should delete the key "com.google.android.maps.v2.API_KEY".
Related
I have a complex imported package that creates an activity and then uses SetContentView on an R.layout file. This layout essentially inflates and covers the screen, but I would like it to only "inflate" inside an existing view that is attached to MainActivity.
The activity class looks something like this
public class ExampleActivity extends AppCompatActivity {
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
setTheme(R.style.Theme_AppCompat_NoActionBar);
super.onCreate(savedInstanceState);
setContentView(R.layout.example_layout);
}
}
And I would call it from something like a clickListener with a function like this (where activity is MainActivity)
public static void startNewActivity(Activity activity) {
Intent navigationActivity = new Intent(activity, ExampleActivity.class);
activity.startActivity(navigationActivity);
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:mapbox="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#AFAFB1"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="viewToFill">
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
So the question I'm asking is would it be possible to set an activity up so that when SetContentView is called a predefined view (attached to MainActivity) is filled instead of the entire screen. In simple terms, have SetContentView put R.layout.example_layout into the linearlayout viewToFill in activity_main.xml.
Any help would be appreciated, I have ideas of working around it, it's just that this solution is by far the least involved if it's possible, but I'm very aware it may not be
edit: made it clearer that the target layout is attached to a different activity than the new layout created by SetContentView
As per the official documentation in Android application components the Activity covers the entire screen / window which is the correct and desired behaviour.
If you want to start a view that only covers the partial screen then you should use a Fragment. A Fragment represents a reusable portion of your app's UI and provides the modularity that you want.
Just define Theme.AppCompat.NoActionBar for that Activity in AndroidManifest.xml.
The essence of this question was "can I have 2 activities running on the same screen" and the answer to that question is no, it is not currently possible (for the most part).
I say for the most part because I actually stumbled across exactly what I was looking for at https://developer.android.com/guide/topics/large-screens/activity-embedding, activity embedding on a phone screen is what I was looking for which is the ability to run 2 activities with ui elements on the same screen. However as the docs say this is an experimental API that is only for newer large screen devices, so it is still very early days for this technology and there's a good chance that it never comes to small screen devices.
I came across fragments a lot both here and researching this question, but a fragments intention is to give a single activity reusable portions of the UI and to provide lifecycles to those portions, among a host of other features.
So with the complex package I have, I am going to find what the activity lifecycle provides to it, and find another way of mimicking it without it having to start a new activity and then I'll replace the setcontentview with a regular inflation pointed somewhere in activity_main.xml
I have an xml layout which includes the following code:
<fragment
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="100dp"
android:name="com.google.android.gms.maps.SupportMapFragment" />
This layout can be inflated in the main activity more than once and, in that case, should display multiple MapFragments. When that happens, however, I get the following error:
Duplicate id 0x7f0a0213, tag null, or parent id 0xffffffff with another fragment for com.google.android.gms.maps.SupportMapFragment
From my understanding, this happens because you can't have more than 1 <fragment> with the same id.
How can I inflate these views with these map fragments multiple times? Is it possible to assign different ID's to each fragment every time the layout is inflated?
EDIT: I found this. I guess I can't set the ID of the fragment itself programmatically.
just change the id from android:id="#+id/map"
to android:id="#+id/map2" and etc.
Please take into account, that every google map is expensive for performance and memory, so ask yourself do you really need more than one map
I want to write new UI class which contain Check box and Label. At the moment there is existing UI class with same elements but their element descriptions are different. But data model for both UIs are going to be same.
So is it good practice to keep separate UI classes (by duplicating GridBagConstraints and other stuffs) for each or move common code in to abstract layer and derive description of the UI elements in the implementation level?
There are some other things that you can try, so you can avoid duplicating UI code, I'll give you 2 examples:
You can use the tag to bring the UI code inside another layout file and show it in you current layout, at the end you will be able to call it directly from your current Activity or Fragment in the same way you do with the other elements at the root of your Fragment or Activity class.
Re-using layouts
First layout file named: include_example_layout.xml
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="#+id/textView_includeExampleLayout_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<CheckBox
android:id="#+id/checkBox_includeExampleLayout_valid"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</merge>
Second layout file named: activity_main.xml
<LinearLayout>
<include layout="#layout/toolbar_search_algolia"/>
</LinearLayout>
And from the MainActivity file you will be able to call the ids of this file include_example_layout as if they were declared directly in your activity_main file, so you will be able to reuse it.
The second one is creating a View element, this has an added advantage to the first method but is a little more complex, the thing is that you will be able to move some UI logic to the class of the new View element, for example if you want to disable the checkbox when something is happening with the information you can move thtat logic to the new view class.
Custom View
I'll no write a complete tutorial about this because it is a extense topic but I'll left some examples in other places that will help you understand the most basic concepts, there are two way in wich you can build CustomViews the first one is extending the View class that will force you to create it from scratch, but you can also extend other Views like a LinearLayout and this will help you to get started with the concept of a CustomView (is not recommended in every case, it can slow down your UI if you don't use it wisely)
Example extending LinearLayout
Example extending View
I am wondering what's the difference between #+id/android:list and #+id/list. I know the last one which is a regular id assignment but the first looks different. What makes it special?
Where I saw it:
I was studying on ListView, ListAdapter and things like that and the author define the ListView in layout xml file as below :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<ListView
android:id="#+id/android:list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
<TextView
android:id="#+id/android:empty"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="#string/main_no_items"/>
</LinearLayout>
and also let me mention #+id/android:empty id as well.
And he also extends ListActivity class.
Here is the source of the article.
And also what's in my mind as questions are :
Should we extend ListActivity? Maybe I want an Activity which also contains other Views.
We use #+id/android:list just because we extend ListActivity or we can use the same convention if we extend Activity?
Thanks.
Resource IDs in Android are specific to a package (which is good, or else you'd have lots of conflicts if your app is dealing with several packages at the same time).
#+id/list will create a resource ID in your app (=your package) with the name "list" and give it a unique ID. In code, that would be R.id.list.
#android:id/list will use the ID "list" from the package android (which, in code, would be android.R.id.list.
EDIT: Need to add the corrections David Hedlund pointed out: The proper reference would be #android:id/list. Also, + indicates you're defining a new ID - you obviously don't need that when you're referencing something that was defined in the Android API.
I think the example code you posted has a typo, so it should be #android:id/list (without the +). From the ListActivity javadoc:
your own view MUST contain a ListView object with the id "#android:id/list"
#android:id/list is specific to ListActivity, so you do not need it if you are adding a ListView into any other kind of Activity. You should extend ListActivity if you want the user to do more than view the list. For example, you can override ListActivity.onListItemClick to respond to clicks on an item in the list.
Similarly, #id/android:empty (again, without the +), is a special case for ListActivity. This allows you to specify an alternative view that should be displayed when your list is empty. That View will not be displayed when the list is populated.
in android,
In XML: #[package:]layout/filename
like
android:id="#+id/android:list"
This is the standard way to refer to a list view when refering to listFragment or listActivity
so filename is android:list is a reference to ListView.
navigate to res/values/ids.xml
you will find <item type="id" name="list" />
ListView is a view group that displays a list of scrollable items. The list items are automatically inserted to the list using an Adapter that pulls content from a source such as an array or database query and converts each item result into a view that's placed into the list.
This is more of a theoretical question, I have searched in many places, but unable to find the answer:
If i add an android:onClick tag to my ListView inside the layout file, what is the method signature I should use for my java Activity in order to correctly have it been called?
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:entries="#array/models"
android:onClick="getSpecs">
</ListView>
This is the Java method signature, but it will be fired everytime you click anywhere in the ListView. It is not an ItemClickListener, as I assume that was your intention for that XML.
public void getSpecs(View v) {
}
Note that the android:onClick XML attribute is the same as View#setOnClickListener, meaning it sets the generalized view's click listener. For buttons and such this is fine, but ListViews and other complex, nested views, there are other interfaces for catching the appropriate clicks.