How to define a custom (composite) layout in Android? - java

I want to learn - if there is a way - how to define a custom view type, and use it in XML layouts.
For example, I have a custom button that looks like this:
<LinearLayout>
<ImageView />
<TextView />
</LinearLayout>
I know I can save this as mybutton.xml, and do <include layout="#layout/mybutton" />, but is there a way that I can use this like this:
<MyButton />
?
I would also like to be able to instantiate this new, custom class in Java code. Like this :
MyButton mb = new MyButton();
Should I define MyButton as a Java class? If so, what should I extend, and how ?
Thanks for any help !

You will need to define a custom class for your object.
MyButton.java
public class MyButton extends View{}
You will have to create the constructor to inflate your XML document, and then call the object in your XML by the fully qualified package name.
<com.example.MyButton/>

Related

Android onClick() on include view won't let binding

I have a separate layout that I want to call onClick and update a field on callback
<include
android:onClick="#{() -> viewModel.changeItem(2)}"
layout="#layout/item"
app:attr="#{viewModel.title}"
app:desc="#{viewModel.description}"
app:active="#{viewModel.isSelected}"
/>
But it returns the following binding error:
Cannot find the setter for attribute 'android:onClick' with parameter
type lambda on com.X.databinding.ItemBinding.
But I can binding on other views
<TextView
android:onClick="#{() -> viewModel.changeItem(1)}"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
What I suggest you is to call the onClick directly from code.
Setup an ID for your view in your .xml, then set something like this :
val item = findViewById(R.id.your_id) etc.
item.onClick { functionYouWantToCall() }
However, I do not know if this is possible to set an ID or an onClickListener on an include layout.
If you can not do it, simply put your include inside a LinearLayout, then set your onClick on it.
I used to set onClicks in the .xml too, but I think it is much more efficient to set it in the code.
Moreover, I do not know if you can set arguments in a function you call from the xml.

How is +id valid inside a RelativeLayout?

In a relative layout I see a pattern as:
<TextView
android:id=“#+id/txt_id”
etc
android:layout_alignBottom="#+id/some_other_txt”
etc
/>
<TextView
android:id="#+id/some_other_txt"
etc
/>
I thought +id is used only when creating an id for a widget. Is this a kind of “trick” to layout a widget relative to another widget declared later in the file?
UPDATE:
This question is specifically about the RelativeLayout possitioning. Not about the difference in syntax in general as the linked question
Its just a reference point for placing the different elements in the layout builder.
From this SO answer
The first time you reference an ID, use the #+ prefix, which tells the resource builder to add the ID,
Here you're making a forward reference to a widget & id that's not already defined:
<TextView
android:id=“#+id/txt_id”
etc
android:layout_alignBottom="#+id/some_other_txt”
etc
/>
Here you are defining it:
<TextView
android:id="#+id/some_other_txt"
More context here

map namespace on XML for Google Maps API on android

I have the following XML file for a View on Android.
As I am trying to integrate the Google Maps, I need to declare the namespace map, in order to set it's properties. Using like this, it looks like I cant declare the namespace inside the fragment.
I've also tried to declare the namespace after the namespace "android" (in the beggining of RelativeLayout) but the namespace is still not recognized on the fragment.
How can I solve this problem?
<fragment xmlns:map="http://schemas.android.com/apk/res-auto"
android:id="#+id/venues_map"
android:name="com.google.android.gms.maps.MapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
map:cameraZoom="13" />
For what I know, there is some bug that doesn't allow to put the map namespace properties inside the fragment if it not the only thing on the screen ( Meaning there are more views surround it).
Why wont you set your properties using code?
If you want to set zoom level do this:
cameraPosition = new CameraPosition.Builder().target(latlng).zoom(14.0f).build();
CameraUpdate cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition);
map.moveCamera(cameraUpdate);

How to have a header in every layout page?

I want that this code:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" >
<TextView android:id="#+id/logo" style="#style/logo"
android:layout_alignParentTop="true"
android:text="#string/logo" tools:context=".MainActivity" />
to start in every layout. How can I do that I wouldn't need to add this to every layout page? Like for example in PHP I would use <?=include("header.php");?> (just an example, actually it's bad practise, doesn't matter here). Thank you.
Save your header in XML file and then include this XML as child layout in other layouts:
<include layout="#layout/headerlayout" android:id="#+id/headerLayoutid" ... />
The headerlayout.xml is name of your above layout that should be defined in res/layout and you like that be shown as header in all layouts(layout="#layout/headerlayout"),also headerLayoutid is id of your headerlayout(in it's parent) and you can reference to it in your parent layouts or in your code.
You can override all the layout parameters. This means that any android:layout_* attribute can be used with the tag. Here is an example:
<include android:layout_width="fill_parent" layout="#layout/image_holder" />
You can see more details in about include in this page.
Edit:
If you have problems in about finding views in included layout,see this questions,I hope these help you:
findViewById not working for an include?
Finding an view by id?
The <include> tag is what you want. Read about it in Re-using Layouts with <include/>
You can use the <include .../> tag in your layout to reuse your header where is needed. See here for an example.

Android: Specifying a onClick() member method in XML?

I have a layout in XML as follows:
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:onClick="myButton.performClick" />
myButton is a member of this activity, is it possible use a class member method here?
is it possible use a class member method here?
According to the API - no. The API says:
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.
No, as the docs say (emphasis mine):
you must declare a public void sayHello(View v) method of your context
(typically, your Activity)
If you wanted to execute a method on a field, you could wrap it I suppose.
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:onClick="performClick" />
Then:
public void performClick(View view) {
myButton.performClick(view);
}
but that almost defeats the purpose of the XML onClick attribute (making things more concise). Is there a good reason for performClick to be on your button instead of your activity anyway?
Lastly, doing this on the LinearLayout is fine. The attribute is supported for all Views.
onClick doesn't go in the Linear Layout tag. It goes in the tag of the button whose on click you want to set.
So you do it like this:
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="methodName"/>
</LinearLayout>

Categories

Resources