3

I have a simple xml which I want to inflate as a java view object. I know how to inflate a view:

view = LayoutInflater.from(context).inflate(R.layout.alarm_handling, this);

But then I have a view which is a child of the parent (this). And then the messy problem starts with setting layoutparameters and having an extra layout which I do not need. These are much easier to do in xml.

With an Activity one can just call: setContentView() but with a View that is not possible.

In the end I would like to have a Java class (extends ViewSomething) which I can refer to in an other xml. I have looked at ViewStub, which almost is the answer, except that it is final :(

public class AlarmView extends ViewStub{ //could work if ViewStub wasn't final

public AlarmView (Context context, AttributeSet attrs) {
    super(context);

    //using methods from ViewStub:
    setLayoutResource(R.layout.alarm_handling);
    inflate();
}
}

So how to to this? What to extend to be able to just call setContentView() or setLayoutResource()?

I looked at many SO answers but none of them fit my question.

bluevoid
  • 1,274
  • 13
  • 29
  • I'm a little puzzled. I believe you can inflate a view with a null parent (I.E. inflate(R.layout.alarm_handling, null) or some variant) but it sounds very much like you are wanting to use a custom view from xml, which is also quite possible. Is your problem that you want a custom xml inflater? – C B J Jul 09 '13 at 08:31
  • I do not know if I need a custom xml inflater. I want to create a custom component which takes care of its own layout (inflate from xml) without the extra (parent) layout which I think is unnessary. – bluevoid Jul 09 '13 at 08:37

1 Answers1

6

as far as I understood the trick that you want to apply it's a bit different than what you trying to.

No ViewStub are not the solution as ViewStub have a very different way of handling everything.

Let's say for the sake of the example your XML layout is something like this (incomplete, just to show the idea):

<FrameLayout match_parent, match_parent>
     <ImageView src="Myimage", wrap_content, Gravity.LEFT/>
     <TextView text="hello world", wrap_content, Gravity.CENTER_HORIZONTAL/>
</FrameLayout>

then you don't want to extend FrameLayout and inflate this XML inside it, because then you'll have two FrameLayouts (one inside the other) and that's just a stupid waste of memory and processing time. I agree, it is.

But then the trick is to use the merge on your XML.

<merge match_parent, match_parent>
     <ImageView src="Myimage", wrap_content, Gravity.LEFT/>
     <TextView text="hello world", wrap_content, Gravity.CENTER_HORIZONTAL/>
</merge>

and inflate as normal on your widget that extends FrameLayout

public class MyWidget extends FrameLayout
   // and then on your initialisation / construction
   LayoutInflater.from(context).inflate(R.layout.alarm_handling, this);

and your final layout on screen will only have 1 FrameLayout.

happy coding!

Budius
  • 39,391
  • 16
  • 102
  • 144
  • Cool, that sounds like what I am searching for! I will give it a try to see if it works for me. – bluevoid Jul 09 '13 at 08:43
  • It works beautifull, this wil take out a lot of code from my project where I have been setting LayoutParams in java classes to get things right. Thanx! – bluevoid Jul 09 '13 at 08:47
  • This works great. The only issue is that the UI preview in android Studio will not know how to show the contents of layout because it doesn't know if the original tag was FrameLayout, LinearLayout, or RelativeLayout. – gardenofwine Apr 26 '15 at 13:55
  • @gardenofwine I agree with you. It's very annoying and I've seen before there's a "bug ticket" for Android Studio to proper handle preview of "merge" tag. Until then, we just have to live with it. – Budius Apr 26 '15 at 14:23
  • you can use tools:parentTag="FrameLayout" look at this answer https://stackoverflow.com/a/39539735/4985958 – Sergey Chilingaryan Jun 14 '21 at 11:43