I am trying to create a compound viewgroup after inflating the group from an XML file.
The viewgroup is composed as: A LinearLayout Root, 2 child LinearLayouts. I am able to see the layout correctly in the layout editor; however, when I attempt to add a view (say a button) from the editor, the view does not show up and the application immediately force closes. I was told i may need to Override the onLayout method to correctly draw the view components but I'm am fairly confused.
My Class:
public class FocusBox extends LinearLayout {
private LinearLayout rootLayout,
contentLayout,
topLayout;
public FocusBox(Context context)
{
super(context, null);
}
public FocusBox(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.focus_box, this);
rootLayout = (LinearLayout)findViewById(R.id.focusBoxParent);
contentLayout = (LinearLayout)findViewById(R.id.focusBottom);
topLayout = (LinearLayout)findViewById(R.id.focusTop);
}
}
And the xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="4dp"
android:id="#+id/focusBoxParent"
android:orientation="vertical">
<LinearLayout
android:background="#drawable/gradients"
android:layout_weight=".1"
android:gravity="center"
android:id="#+id/focusTop"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:text="TextView"
android:id="#+id/focusTitle"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_width="wrap_content"/>
</LinearLayout>
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight=".9"
android:id="#+id/focusBottom"
android:background="#drawable/gradient2"
android:orientation="horizontal">
</LinearLayout>
</LinearLayout>
Generally, if you inflate a layout from a valid XML you shouldn't get an error. You should do a clean build and re-deploy the app again.
Also check if you're using the correct class in the import statement in other classes (you could be using a FocusBox from some 3rd-party library instead of the one you made)
Related
I am new to Android development and feel like this is a really trivial problem, but I cannot word it well enough to find a solution online, so I might as well ask the question here.
My goal is to create a reusable component that is essentially an expandable card like the one described here: https://material.io/design/components/cards.html#behavior.
To do it, I created a custom view that extends a CardView:
public class ExpandableCardView extends CardView {
public ExpandableCardView(Context context) {
super(context);
}
public ExpandableCardView(Context context, AttributeSet attrs) {
super(context, attrs);
// get custom attributes
TypedArray array = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ExpandableCardView, 0, 0);
String heading = array.getString(R.styleable.ExpandableCardView_heading);
array.recycle();
// inflate the layout
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.expandable_card_view, this, true);
// set values
TextView headingTextView = findViewById(R.id.card_heading);
headingTextView.setText(heading.toUpperCase());
// set collapse/expand click listener
ImageView collapseExpandButton = findViewById(R.id.collapse_expand_card_button);
collapseExpandButton.setOnClickListener((View v) -> toggleCardBodyVisibility());
}
private void toggleCardBodyVisibility() {
LinearLayout description = findViewById(R.id.card_body);
ImageView imageButton = findViewById(R.id.collapse_expand_card_button);
if (description.getVisibility() == View.GONE) {
description.setVisibility(View.VISIBLE);
imageButton.setImageResource(R.drawable.ic_arrow_up);
} else {
description.setVisibility(View.GONE);
imageButton.setImageResource(R.drawable.ic_arrow_down);
}
}
}
And the layout:
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/expandable_card_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="16dp"
android:animateLayoutChanges="true"
app:cardCornerRadius="4dp">
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/card_header"
android:padding="12dp"
android:layout_width="match_parent"
android:layout_height="48dp"
android:orientation="horizontal" >
<TextView
android:id="#+id/card_heading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textColor="#color/colorPrimary"
android:layout_alignParentLeft="true"
android:text="HEADING"/>
<ImageView
android:id="#+id/collapse_expand_card_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
app:srcCompat="#drawable/ic_arrow_down"/>
</RelativeLayout>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/card_body"
android:padding="12dp"
android:layout_marginTop="28dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:visibility="gone" >
</LinearLayout>
</androidx.cardview.widget.CardView>
Ultimately I want to be able to use it like so in my activities, usually multiple instances per activity:
<xx.xyz.yy.customviews.ExpandableCardView
android:id="#+id/card_xyz"
android:layout_width="match_parent"
android:layout_height="match_parent"
custom_xxx:heading="SOME HEADING" >
<SomeView></SomeView>
</xx.xyz.yy.customviews.ExpandableCardView>
Where SomeView is any text, image, layout or another custom view altogether, typically with data bound from the activity.
How do I get it to render SomeView inside the card body? I want to take whatever child structure is defined within the custom view and show it in the card body when it is expanded. Hope I made it easy to understand.
I think that a better approach would be to define the layout that will be inserted into the CardView ("SomeView") in a separate file and reference it with a custom attribute like this:
<xx.xyz.yy.customviews.ExpandableCardView
android:id="#+id/card_xyz"
android:layout_width="match_parent"
android:layout_height="match_parent"
custom_xxx:heading="SOME HEADING"
custom_xxx:expandedView="#layout/some_view"/>
I'll explain my rationale at the end, but let's look at an answer to your question as stated.
What you are probably seeing with your code is SomeView and expandable_card_view appearing all at once in the layout. This is because SomeView is implicitly inflated with the CardView and then expandable_card_view is added through an explicit inflation. Since working with layout XML files directly is difficult, we will let the implicit inflation occur such that the custom CardView just contains SomeView.
We will then remove SomeView from the layout, stash it, and insert expandable_card_view in its place. Once this is done, SomeView will be reinserted into the LinearLayout with the id card_body. All this has to be done after the completion of the initial layout. To get control after the initial layout is complete, we will use ViewTreeObserver.OnGlobalLayoutListener. Here is the updated code. (I have removed a few things to simplify the example.)
ExpandableCardView
public class ExpandableCardView extends CardView {
public ExpandableCardView(Context context) {
super(context);
}
public ExpandableCardView(Context context, AttributeSet attrs) {
super(context, attrs);
// Get control after layout is complete.
getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
// Remove listener so it won't be called again
getViewTreeObserver().removeOnGlobalLayoutListener(this);
// Get the view we want to insert into the LinearLayut called "card_body" and
// remove it from the custom CardView.
View childView = getChildAt(0);
removeAllViews();
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.expandable_card_view, ExpandableCardView.this, true);
// Insert the view into the LinearLayout.
((LinearLayout) findViewById(R.id.card_body)).addView(childView);
// And the rest of the stuff...
TextView headingTextView = findViewById(R.id.card_heading);
headingTextView.setText("THE HEADING");
// set collapse/expand click listener
ImageView collapseExpandButton = findViewById(R.id.collapse_expand_card_button);
collapseExpandButton.setOnClickListener((View v) -> toggleCardBodyVisibility());
}
});
}
private void toggleCardBodyVisibility() {
LinearLayout description = findViewById(R.id.card_body);
ImageView imageButton = findViewById(R.id.collapse_expand_card_button);
if (description.getVisibility() == View.GONE) {
description.setVisibility(View.VISIBLE);
imageButton.setImageResource(R.drawable.ic_arrow_up);
} else {
description.setVisibility(View.GONE);
imageButton.setImageResource(R.drawable.ic_arrow_down);
}
}
}
expandable_card_view.java
The CardView tag is changed to merge to avoid a CardView directly nested within a CardView.
<merge
android:id="#+id/expandable_card_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="16dp"
android:animateLayoutChanges="true"
app:cardCornerRadius="4dp">
<RelativeLayout
android:id="#+id/card_header"
android:padding="12dp"
android:layout_width="match_parent"
android:layout_height="48dp"
android:orientation="horizontal" >
<TextView
android:id="#+id/card_heading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textColor="#color/colorPrimary"
android:layout_alignParentLeft="true"
android:text="HEADING"/>
<ImageView
android:id="#+id/collapse_expand_card_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
app:srcCompat="#drawable/ic_arrow_down"/>
</RelativeLayout>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/card_body"
android:padding="12dp"
android:layout_marginTop="28dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:visibility="gone" >
</LinearLayout>
</merge>
activity_main.xml
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.example.customcardview.ExpandableCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/imageView"
android:layout_width="100dp"
android:layout_height="100dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/ic_android" />
<TextView
android:id="#+id/childView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Say my name."
android:textSize="12sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/imageView" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.example.customcardview.ExpandableCardView>
</LinearLayout>
So, why do I suggest that you use a custom attribute to include SomeView in the layout as I identified at the beginning? In the way outlined above, SomeView will always be inflated and there is some effort to switch the layout around although SomeView may never be shown. This would be expensive if you have a lot of custom CardViews in a RecyclerView for instance. By using a custom attribute to reference an external layout, you would only need to inflate SomeView when it is being shown and the code would be a lot simpler and easier to understand. Just my two cents and it may not really matter depending upon how you intend to use the custom view.
I am trying to add my custom view to the main activity's xml.
I have created the following xml for the view:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Testing custom view"
android:textSize="20dp" />
</LinearLayout>
And created the following class in which the above xml is inflated:
public class TestView extends LinearLayout {
public TestView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
View.inflate(context, R.layout.test_name, null);
}
And in the xml of the main activity I have added the custom view like below:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.myapplication.MainActivity">
<com.example.myapplication.TestView
android:id="#+id/submit_area"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
When I am running the app, I am getting an empty screen. It's not showing the textview which displays "Testing custom view".
Any help would much appreciated.
Thanks
Your view inflation code in your custom view looks wrong.Try it the way given below.
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.view_color_options, this, true);
I have a layout problem with my custom viewgroup class.
I call init() in the constructor. In my init() function I inflate the viewgroups layout from an xml file, which contains a LinearLayout to which I add several other views.
I am using spacer (View layout_width="0" and layout_weight="1") to distribute the items equaly.
The problem lies here: the layout still has not defined any width when i add the children. So the spacer all have the size 0, and wont actually place the "line_dot" items equally. How can i somehow update their size?
public class SliderSwitch extends FrameLayout {
...
public SliderSwitch(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context context)
{
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.slider_switch,this);
sliderLayout = (LinearLayout) findViewById(R.id.sliderLayout);
labelLayout = (LinearLayout) findViewById(R.id.labelLayout);
// add one spacer
View spacer = (View) inflate(context,R.layout.spacer, null);
sliderLayout.addView(spacer);
// setup the view depending on how many elements there are
for (int i=1;i<numberOfElements-1;i++) {
ImageView lineDot = (ImageView) inflater.inflate(R.layout.slider_switch_line_dot, null);
sliderLayout.addView(lineDot);
View spacer = (View) inflate(context,R.layout.spacer, null);
sliderLayout.addView(spacer);
}
}
...
}
this is the xml file for the spacer:
<View
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
and this is the one for my viewgroup layout
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:id="#+id/relLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:orientation="horizontal" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/left_bg" />
<LinearLayout
android:id="#+id/sliderLayout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#drawable/middle_bg"
android:gravity="center"
android:orientation="horizontal" >
<!-- <include layout="#layout/spacer"/> -->
</LinearLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/right_bg" />
</LinearLayout>
<ImageButton
android:id="#+id/sliderKnob"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="0dp"
android:background="#null"
android:src="#drawable/knob" />
</RelativeLayout>
</LinearLayout>
I found the solution now. You have to set the LayoutParams in the code again (even if they are already defined in the xml file), then everything is neatly spaced, how its supposed to. seems to be a bug. But this solution works:
// add one spacer
View spacer = (View) inflate(context,R.layout.spacer, null);
spacer.setLayoutParams(new LinearLayout.LayoutParams(1,LayoutParams.WRAP_CONTENT,1.0F));
sliderLayout.addView(spacer);
// setup the view depending on how many elements there are
for (int i=1;i<numberOfElements-1;i++) {
ImageView lineDot = (ImageView) inflater.inflate(R.layout.slider_switch_line_dot, null);
sliderLayout.addView(lineDot);
spacer = (View) inflate(context,R.layout.spacer, null);
spacer.setLayoutParams(new LinearLayout.LayoutParams(1,LayoutParams.WRAP_CONTENT,1.0F));
sliderLayout.addView(spacer);
}
You can call init() on onSizeChanged callback. Remember to set and keep a flag in order to avoid calling it twice, since this callback may run more than once.
I am working on an android application that will get data from an xml file and insert it in a listview
but I want to change the UI and instead of displaying the data in a listview vertically, I want to display them horizontally in a scrollview
My question is if I have the following code
<HorizontalScrollView
android:id="#+id/horizontalScrollView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scrollbars="none">
<LinearLayout
android:id="#+id/linearLayout1"
android:orientation="horizontal"
android:layout_height="wrap_content"
android:layout_width="wrap_content" android:padding="2dp">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView
android:layout_width="wrap_content"
android:id="#+id/imageView11"
android:layout_height="wrap_content"
android:src="#drawable/i1"/>
<TextView
android:id="#+id/TextOnImage11"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Fantasia Reviews"
android:layout_alignParentBottom="true"
android:paddingLeft="2dp"
android:background="#drawable/txt_bg"
android:textSize="10dp"
android:paddingTop="2dp"
android:textColor="#FFFFFF"
android:textStyle="bold"
android:width="0dp" />
</RelativeLayout>
</LinearLayout>
</HorizontalScrollView>
how can I add more images and text dynamically from the java code ??
Thank you
I presume that your intent would be to add another RelativeLayout with it's own image/text pair straight after the RelativeLayout that you have shown in your code sample?
In that case as it is not simply adding one more view, I would take the time to create a class that represents your "structure" that you want to insert.
e.g. A class called "TextImagePair" that extends "RelativeLayout"
public class TextImagePair extends RelativeLayout {
public ReportDetailRow(Context context){
super(context);
}
public TextImagePair(Context context,AttributeSet attributeSet){
super(context, attributeSet);
}
public TextImagePair(Context context,AttributeSet attributeSet, int i){
super(context, attributeSet,i);
}
public TextImagePair(Context context, AttributeSet attributeSet, String text, int drawableResource) {
super(context, attributeSet);
// Inflate the layout
LayoutInflater inflator = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflator.inflate(R.layout.lay_textimagepair, this);
TextView tvText = (TextView)this.findViewById(R.id.layTextImagePair_textview);
tvText.setText(text);
ImageView imgView = (ImageView)this.findViewById(R.id.layTextImagePair_imageview);
imgView.setDrawable(getResources().getDrawable(drawableResource));
}
}
You would then have a seperate xml layout file (named lay_textimagepair in my code) that just contains the text and image views.
You would then add this to your view at run time with:
LinearLayout parent = (LinearLayout)findViewById(R.id.layParentView_liniearlayout);
TextImagePair tip = new TextImagePair(null,null,"Blah Blah Blah",R.drawable.something);
parent.addView(tip);
Sorry if there are any bugs in the above code but I am writing it without access to Eclipse!
Why do some views in a linearlayout within a scrollview fill the parent when fill_parent is set when inflated from xml directly but don't when added via a custom component that inflates the same xml?
The result of inflating the same xml in two different places:
The top item of the two is as a result of inflating the xml in a class that extends linearLayout and then adding that class to the linearLayout inside the scroll view. This view isn't filling the parent and I can't work out why.
The bottom item is the result of inflating the xml directly in the activity that this is all contained within. It appears as I expected.
This is the code that adds the two views in the activity:
scrollList.addView(new CommunityTaskListItem(this, null));
scrollList.addView(View.inflate(getBaseContext(), R.layout.communitytask, null));
This is the code that inflates the activity within a custom component class "CommunityTaskListItem":
View communityTask = View.inflate(context, R.layout.communitytask, null);
addView(communityTask);
I assume the xml is okay because it works fine when inflated directly in the activity. My question is why the fill_parent property seems to be lost when the xml is inflated in a custom component's class?
For good measure, here is the xml being inflated: EDIT: I gave you the wrong one before!!! Here's the right one:
<?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="wrap_content">
<LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="#+id/linearLayout1" android:background="#drawable/plainbutton" android:layout_marginBottom="5px" android:layout_marginTop="5px" android:layout_weight="1">
<TextView android:layout_height="wrap_content" style="#style/CommunityTaskText" android:layout_width="fill_parent" android:layout_weight="1" android:id="#+id/textViewCommunityTaskTimes" android:text="xx:xx - xx:xx"></TextView>
<TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" style="#style/CommunityTaskText" android:id="#+id/textViewCommunityTaskDescription" android:text="Task"></TextView>
</LinearLayout>
</LinearLayout>
I'd like to keep the custom component and not inflate the xml within my activity if I could.
EDIT: Code where CommunityTaskListItem is inflated:
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
public class CommunityTaskListItem extends LinearLayout {
TextView textViewCommunityTaskTimes;
TextView textViewCommunityTaskDescription;
public CommunityTaskListItem(Context context, AttributeSet attrs) {
super(context, attrs);
View communityTask = View.inflate(context, R.layout.communitytask, null);
addView(communityTask);
textViewCommunityTaskTimes = (TextView)findViewById(R.id.textViewCommunityTaskTimes);
textViewCommunityTaskDescription = (TextView)findViewById(R.id.textViewCommunityTaskDescription);
}
...
EDIT: All working now! Here's the final code for anyone else incase they have a similar issue:
Contructor for the custom object:
public CommunityTaskListItem(Context context, AttributeSet attrs) {
super(context, attrs);
setOrientation(VERTICAL);
addView(inflate(context, R.layout.communitytask, null));
textViewCommunityTaskTimes = (TextView)findViewById(R.id.textViewCommunityTaskTimes);
textViewCommunityTaskDescription = (TextView)findViewById(R.id.textViewCommunityTaskDescription);
}
Custom object xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="#+id/linearLayout1" android:background="#drawable/plainbutton" android:layout_marginBottom="5px" android:layout_marginTop="5px" android:layout_weight="1">
<TextView android:layout_height="wrap_content" style="#style/CommunityTaskText" android:layout_width="fill_parent" android:layout_weight="1" android:id="#+id/textViewCommunityTaskTimes" android:text="xx:xx - xx:xx"></TextView>
<TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" style="#style/CommunityTaskText" android:id="#+id/textViewCommunityTaskDescription" android:text="Task"></TextView>
</LinearLayout>
</LinearLayout>
To be honest I don't know exactly what the mistake I was making was so if someone could make that clear I'd be very grateful.
The first line should be:
scrollList.addView(new CommunityTaskListItem(this, null)
new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
You call inflate() inside CommunityTaskListItem class and inflated view becomes a child view of the CommunityTaskListItem view. But you don't set width and height for this view so it doesn't match its parent's width.
EDIT: I think your XML should look like this:
<?xml version="1.0" encoding="utf-8"?>
<packagename.CommunityTaskListItem
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent" android:layout_height="wrap_content">
<LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="#+id/linearLayout1" android:background="#drawable/plainbutton" android:layout_marginBottom="5px" android:layout_marginTop="5px" android:layout_weight="1">
<TextView android:layout_height="wrap_content" style="#style/CommunityTaskText" android:layout_width="fill_parent" android:layout_weight="1" android:id="#+id/textViewCommunityTaskTimes" android:text="xx:xx - xx:xx"></TextView>
<TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" style="#style/CommunityTaskText" android:id="#+id/textViewCommunityTaskDescription" android:text="Task"></TextView>
</LinearLayout>
</packagename.CommunityTaskListItem>
where packagename is the name of the package of the CommunityTaskListItem class.
In this case you should change the CommunityTaskListItem:
public class CommunityTaskListItem extends LinearLayout {
TextView textViewCommunityTaskTimes;
TextView textViewCommunityTaskDescription;
public CommunityTaskListItem(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onFinishInflate() {
textViewCommunityTaskTimes = (TextView)findViewById(R.id.textViewCommunityTaskTimes);
textViewCommunityTaskDescription = (TextView)findViewById(R.id.textViewCommunityTaskDescription);
}
// ....
}
This class cannot be created using its constructor. It can be only inflated.
The second way is to inflate children in the constructor like you do. But the XML should differ:
<?xml version="1.0" encoding="utf-8"?>
<merge
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="#+id/linearLayout1" android:background="#drawable/plainbutton" android:layout_marginBottom="5px" android:layout_marginTop="5px" android:layout_weight="1">
<TextView android:layout_height="wrap_content" style="#style/CommunityTaskText" android:layout_width="fill_parent" android:layout_weight="1" android:id="#+id/textViewCommunityTaskTimes" android:text="xx:xx - xx:xx"></TextView>
<TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" style="#style/CommunityTaskText" android:id="#+id/textViewCommunityTaskDescription" android:text="Task"></TextView>
</LinearLayout>
</merge>
The CommunityTaskListItem will be:
public class CommunityTaskListItem extends LinearLayout {
TextView textViewCommunityTaskTimes;
TextView textViewCommunityTaskDescription;
public CommunityTaskListItem(Context context) {
this(context, null);
}
public CommunityTaskListItem(Context context, AttributeSet attrs) {
super(context, attrs);
setOrientation(VERTICAL);
inflate(context, R.layout.communitytask);
textViewCommunityTaskTimes = (TextView)findViewById(R.id.textViewCommunityTaskTimes);
textViewCommunityTaskDescription = (TextView)findViewById(R.id.textViewCommunityTaskDescription);
}
// ....
}
This class can be created using its contructor and inflated from an XML. But if you want to inflate it, you should create a separate XML file. Let's call it task.xml.
<?xml version="1.0" encoding="utf-8"?>
<packagename.CommunityTaskListItem
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="wrap_content"/>
And that's how you can use it:
scrollList.addView(new CommunityTaskListItem(this),
new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
scrollList.addView(View.inflate(getBaseContext(), R.layout.task, null));