Wrong layout hierarchy created from inflating - android

I have a custom component that actually wraps another component. Its layout is:
<AutoCompleteTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:background="#drawable/text_view_background" android:textCursorDrawable="#null"
android:textColor="#android:color/black" android:inputType="textNoSuggestions"
android:paddingLeft="7dp"/>
In the component's code I'm trying to inflate it:
inflate(context,R.layout.results_auto_complete,this);
resultsAutoComplete=(AutoCompleteTextView)getChildAt(0);
But I'm getting a ClassCastException and it says the first child is a RelativeLayout! I traced all the children of this relative layout and it's actually the layout of the widget whose configuration activity contains my custom component! When I tested the component with a simple test activity everything worked!
So why is it happening and what can I do about this?
Thanks.

If your AutoCompleteTextView is a standalone xml file (your code is the root xml tag) of results_auto_complete.xml. It is the result of the inflation, NO need to use getChildAt(i).
if <AutoCompleteTextView> is a child element in an XML file, use should assign it an Id: android:id="#+id/your_view_id". Then after the inflation, use:
this.findViewById(R.your_view_id);
where this is current activity which loads the component view.
Update, try this:
LayoutInflater mInflater = (LayoutInflater)etContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
resultsAutoComplete=(AutoCompleteTextView)mInflater.inflate(R.layout.your_view_id, this, true);

It seems the problem is that I have 2 layouts with the same identifiers from different projects (one project is linked to the other), so when I'm trying to inflate a layout from one of the projects, I'm getting the layout with the same identifier in the other project. Anyway, thanks for trying to help.

Related

Is it bad proactive to create backing subclasses for your layouts if they don't need customization?

I'm new to Android and have recently started adopting the pattern to create an auto-layout-loading custom view based on a layout file. In the layout you use the 'merge' tag as the root, then in the constructor of your view, you inflate that layout into yourself so you are essentially the root of the merged-in controls. Right after you inflate, still in the constructor, you can find the child controls from the layout and assign them to private fields in the custom class so they will always be available, even when using recycler views.
Contrast that with including a layout. In that case, the layout has to define a root element (which can be your custom control, but in that case, you would not inflate the layout into yourself and would have to move the control lookup to onFinishInflate) but otherwise it ends up with the same view hierarchy.
In short, instead of this...
<include layout="#layout/layout_myCustomControl" />
You can now do this...
<com.mydomain.MyCustomControl />
However I find the auto-loading custom control version to be much more flexible and maintainable. The advantages of the second one are not only that you can use custom attributes in the referencing XML layouts (which you can't with the 'include' version) but it also gives you a central place to manage the code as well as layout management/control lookup.
So now I can do this...
<com.mydomain.MyCustomControl
app:myCustomAttribute="Foo" />
And if the control has to have code backing up its behavior, it's nicely encapsulated in the custom view.
Here's an example layout for the auto-loading version...
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is static text in the header" />
<TextView android:id="#+id/dateTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</merge>
And here's the class that uses it...
public class MainHeader extends LinearLayout
{
TextView dateTextView;
public MainHeader(Context context, #Nullable AttributeSet attrs)
{
super(context, attrs);
setOrientation(VERTICAL);
LayoutInflater.from(context).inflate(R.layout.header_main, this);
dateTextView = (TextView)findViewById(R.id.dateTextView);
dateTextView.setText(<<Code for setting date goes here>>);
}
}
But what I'm wondering is if the layout is purely static in nature--say holding a static image and fixed text--is it still considered good practice to use a custom view to represent it? I'd say yes for consistency, plus should I want to extend it in the future, you're already prepared for it and have to do so in just one place regardless of how many places it's used. In contrast, if you included the layout directly in say 20 places, you may have to update all 20 (depending on what's actually changed/needed.)
Pros for the Custom View approach:
Central location for managing layout loading and control lookup
Can support backing code implicitly/internally for updating the view.
Can use attributes when being referenced in other layout files
Better encapsulation (you can hide the layout itself from the outside world exposing behaviors via direct methods)
Can simply be 'new'd' up in code and the layout will automatically load. No inflating or casting needed.
Cons for Custom View approach
When used in Layout files, you now have to also specify width and height making usage a little more verbose.
May add extra classes to your project (not always, but sometimes.)
Again, it seems to me like a no-brainer, but I'm wondering if there's a preferred 'Androidy' way, or is it just a preference up to each developer?
Such approach will add additional level in your view trees. So you only made the UI tree more complex for no good reason. From other side, you can follow next steps to get rid of that side-effect:
<merge /> can only be used as the root tag of an XML layout
when inflating a layout starting with a <merge />, you must specify a parent
ViewGroup and you must set attachToRoot to true (see the
documentation of the inflate() method)
That's it.
Well apparently what I came up with wasn't that unique after all! Here's an article explaining in detail this exact scenario, along with the pros and cons of each. Looks like they too came to the same conclusion.
TrickyAndroid: Protip. Inflating layout for your custom view

How to create dynamic xml file in res in android

I want solution of following:
I have create xml file in data/data/com.example.file/files/abc.xml so during running of app how I get this abc.xml in res/layout and should display on screen.
Thanks.
In general, the XML vocabulary for declaring UI elements closely
follows the structure and naming of the classes and methods, where
element names correspond to class names and attribute names correspond
to methods.
Courtesy goes to #Mike M : You cant create this .XML files used for layouts are pre-compiled .
I'm not sure I have followed your question- are you trying to attach a child view to the RelativeLayout? If so you want to do something along the lines of:
RelativeLayout item = (RelativeLayout)findViewById(R.id.item);
View child = getLayoutInflater().inflate(R.layout.child, null);
item.addView(child);
the RelativeLayout item will be the container for your child view.
Your question needs to be a bit more specific, but here's a general answer:
If you are using fragments then you should re-create your fragment and then use:
inflater.inflate(R.layout.abc, container, false);
If you are using activities then you should use:
setOnContentView(abc);

What is tag <view> in layout xml used for?

I notice that there is a tag <view>(not <View>) which can be used in Android layout xml. When I add such a tag in a layout xml, the app can be successfully compiled but crashes when running. So what is this <view> used for?
view is an alternative way for specifying a view to inflate. You need to combine it with class attribute to specify the class name.
This is "useful" if your view class is an inner class and you cannot use something with a $ in the tag name in XML. (Having inner classes as Views you inflate is not a very good idea though.)
For example:
<view class="your.app.full.package.Something$InnerClass" ... />
Reference: http://androidxref.com/5.0.0_r2/xref/frameworks/base/core/java/android/view/LayoutInflater.java#696
View is widget of android that is use to add any kind of view.Like in problems when we use scrollView in a activity and at bottom of activity there is buttons ,That time we add view to looks better.We can set any kind of color to View .
for exp
This will make a View of 20dp height.

Can I create an xml file with one view without the containing layout

I have a custom view called CustomImageView.
I would like to create an xml file with this view so I inflate the view and add it programmatically to my current layout. (depending on orientation , I will decide where to add it)
Is it possible to so something like this in the xml without a containing layout
<?xml version="1.0" encoding="utf-8"?>
<CustomImageView
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="wrap_content"
android:height="wrap_content"
android:level="2"
android:anotherattr="adsad" />
After that I will inflate it. or should I put it in a Layout like LinearLayout? I just want an xml with my view so I can inflate it and add to my existing layout.. I am not sure what the containing layout would be!
This is perfectly legitimate. You can do it with built-in or custom views. Here is an example from the Android framework. It's an XML layout file containing a single TextView, representing a default ListView row layout. The TextView has several attributes assigned to it in XML, just as your custom view will.
Is it possible to so something like this in the xml
Yes you can inflate an XML that just contains one view. But why not just create the view programmatically? new CustomImageView(...)
depending on orientation , I will decide where to add it
Consider using the layout directories such as "layout-land" to automatically inflate different layouts based on orientation - that's what those are for. Read more about this Supporting Different Screens
I am not sure what the containing layout would be
Use the layout directories and it removes all doubt

Android: how to use XML for custom view layout

I'm coming from the world of GWT and UIBinder, where I'm used to defining custom components by extending Composite, and then putting all the UI layout code in a MyComponent.ui.xml file. This is a very nice way to build up components from smaller pieces.
I'm trying to achieve the same effect on Android with custom Views. I've been able to programmatically extend View, and then add objects by calling addView(textView). I'd like to be able to do that in XML, but I don't see how to associate an xml layout file with the view (apart the primary res/layout/main.xml file, which provides the primary layout for the app.
How can I layout my custom views in XML?
Edit: My question was unclear. What I'm looking to do is associate a my_widget.xml file with my customized view. Then in my_widget.xml I'd like to define various TextViews, etc, and plug them into my View class.
Use the fully qualified name of your custom view class in place of one of the built-in views. Here's a layout, for instance, that fills the window with your class:
<?xml version="1.0" encoding="utf-8"?>
<my.package.MyCustomView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/my_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
To construct Views from XML, use LayoutInflater.
You can use findViewById (int id) with an id defined in XML. See the example in the android doc here (scroll down to IDs).

Categories

Resources