I'm creating a custom ListFragment for my Android application. I want to add a child to #id/listContainer. But I'm not able to get the reference to the view using findViewById(android.R.id.listContainer).
This is the default layout for ListFragment.
list_content.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout android:id="#+id/progressContainer"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
android:gravity="center">
<ProgressBar style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="#string/loading"
android:paddingTop="4dip"
android:singleLine="true" />
</LinearLayout>
<FrameLayout android:id="#+id/listContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:drawSelectorOnTop="false" />
<TextView android:id="#+android:id/internalEmpty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textAppearance="?android:attr/textAppearanceLarge" />
</FrameLayout>
</FrameLayout>
This is my custom ListFragment code.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(android.R.layout.list_content, container, false);
ProgressBar progressBar = new ProgressBar(getActivity());
progressBar.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, Gravity.CENTER));
progressBar.setIndeterminate(true);
ViewGroup listContainer = (ViewGroup) view.findViewById(android.R.id.listContainer);
listContainer.addView(progressBar);
return view;
}
Android Studio says error: cannot find symbol variable listContainer.
What I am doing wrong?
Try getListView().getParent(). since getListView() gives you the list view widget,it's parent should be the frame layout that you need.
The problem is the way you are accessing resource:
ViewGroup listContainer = (ViewGroup) view.findViewById(android.R.id.listContainer);
listContainer.addView(progressBar);
change it to
ViewGroup listContainer = (ViewGroup) view.findViewById(com.android.internal.R.id.listContainer);
listContainer.addView(progressBar);
Since the listContainer is an internal resource, call it using
com.android.internal.R.id.RESOURCE_ID
Change this line :
ViewGroup listContainer =
(ViewGroup)view.findViewById(android.R.id.listContainer);
To
ViewGroup listContainer =
(ViewGroup)view.findViewById(R.id.listContainer);
Change View view = inflater.inflate(android.R.layout.list_content, container, false);
To
View view = inflater.inflate(R.layout.list_content, container, false);
Here R must be import import com.your_package_name.R;
Now you can change
ViewGroup listContainer = (ViewGroup) view.findViewById(android.R.id.listContainer);
To
ViewGroup listContainer = (ViewGroup) view.findViewById(R.id.listContainer);
Related
I have a fragment layout to which i want to add another sub layout dynamically ,
I tried this https://stackoverflow.com/a/22592269/8476022
sub-layout xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:hint="Question"
android:textColor="#color/colorTextBlack"
android:textSize="16dp" />
</android.support.constraint.ConstraintLayout>
this is my main layout
<?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:background="#f2f2f2"
android:orientation="vertical">
<FrameLayout
android:id="#+id/flContainer"
android:layout_width="match_parent"
android:layout_margin="20dp"
android:layout_height="wrap_content"/>
</LinearLayout>
inside my fragment i included the sublayout
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_start_question, container, false);
flContainer = (FrameLayout) v.findViewById(R.id.flContainer);
flContainer.addView(R.layout.sub_layout);
return v;
}
but i am getting error near addView the screenshot is below
can anyone please help to find the error
You are getting Error because
addView(View child) need parameter a view and you are adding FrameLayout which is ViewGroup
Try this way
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View myView = inflater.inflate(R.layout.sub_layout, null);;
flContainer = (FrameLayout) v.findViewById(R.id.flContainer);
flContainer.addView(myView);
Add view takes View object. You are passing the layout Id.
addView(View view)
you do not pass the layout Id
flContainer.addView(R.layout.sub_layout);// Wrong
First inflate a view using inflater then add it to container.
View view=LayoutInflater.from(getContext()).inflate(R.layout.yourView,null);
yourContainer.addView(view);
You need to inflate layout to add the view refer this
View child = getLayoutInflater().inflate(R.layout.sub_layout, null);
flContainer = (FrameLayout) v.findViewById(R.id.flContainer);
flContainer.addView(child);
You want to use:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_start_question, container, false);
// flContainer = (FrameLayout) v.findViewById(R.id.flContainer);
// flContainer.addView(R.layout.sub_layout);
LinearLayout linPhoneNumber = (LinearLayout) v.findViewById(R.id.linPhoneNumber);
View viewPhoneNumber = getActivity().getLayoutInflater().inflate(R.layout.fragment_contact_phone, null);
LinearLayout linPhoneLayout = (LinearLayout) viewPhoneNumber.findViewById(R.id.linPhoneLayout);
TextView txtPhoneNumber = (TextView) viewPhoneNumber.findViewById(R.id.txtPhoneNumber);
txtPhoneNumber.setText(phone);
linPhoneNumber.addView(viewPhoneNumber);
return v;
}
put one linear layout in fragment_start_question.xml :
<LinearLayout
android:id="#+id/linPhoneNumber"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical"></LinearLayout>
then fragment_contact_phone.xml
<LinearLayout
android:id="#+id/linPhoneLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/margin_top_10"
android:orientation="horizontal"
android:padding="#dimen/margin_top">
<ImageView
android:id="#+id/imgCall"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center_vertical"
android:src="#drawable/icon_call" />
<Textview
android:id="#+id/txtPhoneNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="#dimen/margin_top_1"
android:textColor="#color/menu_text_color"
android:textSize="#dimen/margin_top_1"/>
</LinearLayout>
Replace your onCreateView with the following,
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_start_question, container, false);
flContainer = (FrameLayout) v.findViewById(R.id.flContainer);
View subView = inflater.inflate(R.layout.sub_layout, null);
flContainer.addView(subView);
return v;
}
You are passing the layout id only,Define a layout first like:
LinearLayout sublayout = (LinearLayout)v.findViewBYId(R.layout.sub_layout)
flContainer.addView(sublayout);
My findViewById returns null, but it shouldn't.
As you'll see, the button is in the same XML file.
And calling getActivity() makes no difference at all
Here's my onCreateView:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);
Button request = (Button) getView().findViewById(R.id.button_request);
return rootView;
}
And here's my fragment_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container_relative"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
tools:context="br.com.igor.MainActivity$PlaceholderFragment" >
<TextView
android:id="#+id/servic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:layout_marginBottom="0dp"
android:paddingTop="15dp"
android:text="Sample instructions" />
<Button
android:id="#+id/button_request"
style="#style/button_default"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="15dp"
android:layout_below="#id/servic"
android:text="Request" />
</RelativeLayout>
getView is returning null, not findViewById. Use rootView in place of getView
Button request = (Button) rootView.findViewById(R.id.button_request);
getView returns the view you inflated in onCreateView
I am trying to programmatically add. Here is the parent view.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/test"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal" >
</LinearLayout>
Here is the view to add.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:layout_centerHorizontal="true" >
<TextView
android:id="#+id/textview"
android:text="TEST"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
Here is the code.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.test, container, false);
LinearLayout linear = (LinearLayout) view.findViewById(R.id.test);
RelativeLayout layout;
ImageView image;
TextView text;
LayoutParams lp;
layout = (RelativeLayout) inflater.inflate(R.layout.test_row, null, false);
linear.addView(layout);
return view;
}
It adds the view, but it doesn't center and it also ignores the topmargin property. What am I doing wrong?
Answer: I replaced null when inflating my view with container, did the trick.
This seems to be a repeat,all you need to do is specify the parent view instead of added it later to the parent. Hope this helps. See
Layout params of loaded view are ignored
This is my Home.xml layout file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/rellay"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#drawable/placesgradient">
<Button
android:id="#+id/btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="click"
/>
**<I want to include another layout here on a click of a button dynamically on click of a button >**
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_below="#id/btn2"
android:text="hello this is text..see above" />
</RelativeLayout>
This is my Home.java file
public class Home extends Fragment implements OnClickListener {
Button b1;
RelativeLayout r1;
View rootView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.home, container, false);
b1 = (Button) rootView.findViewById(R.id.btn2);
b1.setOnClickListener(this);
return rootView;
}
#Override
public void onClick(View arg0) {
ViewGroup con = null;
r1 = (RelativeLayout) rootView.findViewById(R.id.rellay);
LayoutInflater layoutInflater = (LayoutInflater)getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
r1.addView(layoutInflater.inflate(R.layout.test1, con , false));
}
}
When I click on the button it places the test1.xml layout file at the top of the home.xml layout. I need it to be between the button and the text. I checked this code on stack before but it doesn't seem to work with the FragmentActivity. Here 1 indicates the index or the second child in this case.
rl.addView(1, layoutInflater.inflate(R.layout.content_layout, this, false) );
How can I achieve it? Help!!
I would put some container view at the position you want your layout to be like this:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/rellay"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#drawable/placesgradient">
<Button
android:id="#+id/btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="click"
/>
<FrameLayout
android:id="#+id/flContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_below="#id/btn2"
android:text="hello this is text..see above" />
</RelativeLayout>
Then you can retrieve the container in your Fragment like this:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.home, container, false);
// Retrieve your container
flContainer = rootView.findViewById(R.id.flContainer);
b1 = (Button) rootView.findViewById(R.id.btn2);
b1.setOnClickListener(this);
return rootView;
}
And later when you want to add your layout you can add a child to the FrameLayout like this:
flContainer.addView(subLayout);
If you later want to change the layout in your container you can do it like this:
flContainer.removeAllViews();
flContainer.addView(otherLayout);
Use LayoutParams.
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.BELOW, R.id.btn2);
r1.addView(layoutInflater.inflate(R.layout.test1, con , false),params);
Or put the view in your layout and toggle visibility with View.setVisibility(View.GONE/View.VISIBLE)
I have a fairly complex layout (containing RelativeLayouts, TextViews and ImageViews) that I want to place above a listview. This view should scroll with the listview.
I tried adding the layout as a header to the listview using this code:
View v = inflater.inflate(R.layout.list_view, container, false);
View header = inflater.inflate(R.layout.header_layout, container, false);
// populate views in the header
mList = (ListView)v.findViewById(R.id.list);
mList.addHeaderView(header);
mAdapter = new ReviewsAdapter(getActivity());
mList.setAdapter(mAdapter); <-- error occurs here
ReviewsAdapter is a custom adapter I've written which extends BaseAdapter.
Upon executing the code, I get this error:
11-25 17:19:14.802: E/AndroidRuntime(1215): java.lang.ClassCastException: android.widget.FrameLayout$LayoutParams cannot be cast to android.widget.AbsListView$LayoutParams
11-25 17:19:14.802: E/AndroidRuntime(1215): at android.widget.ListView.clearRecycledState(ListView.java:513)
11-25 17:19:14.802: E/AndroidRuntime(1215): at android.widget.ListView.resetList(ListView.java:499)
11-25 17:19:14.802: E/AndroidRuntime(1215): at android.widget.ListView.setAdapter(ListView.java:442)
11-25 17:19:14.802: E/AndroidRuntime(1215): at com.coppi.storefront.product.ProductReviewsFragment.onCreateView(ProductReviewsFragment.java:104)
If I comment out the mList.addHeaderView(header) line I do not get the error. I can also display the header layout without the listview with no problems.
I'm assuming this has something to do with the contents of the header layout but I'm not sure exactly what would be causing it.
Here is the header xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<RelativeLayout
android:id="#+id/header_section"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="#dimen/margin_sides"
android:background="#color/pdp_availability_section_background" >
<TextView
android:id="#+id/header_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="#dimen/margin_sides"
android:paddingBottom="#dimen/margin_sides"
android:text="#string/ratings_reviews"
android:textColor="#000"
android:textSize="18dp" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/body_section"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="#id/header_section" >
<TextView
android:id="#+id/product_title"
style="#style/ProductTitleFont"
android:layout_marginBottom="#dimen/product_title_bottom_margin"
android:layout_marginLeft="#dimen/margin_sides"
android:layout_marginRight="#dimen/margin_sides" />
<RelativeLayout
android:id="#+id/attributes_section"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/product_title"
android:layout_centerHorizontal="true"
android:layout_margin="#dimen/margin_sides" >
<LinearLayout
android:id="#+id/overall_section"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="bottom" >
<TextView
android:id="#+id/overall_label"
style="#style/ProductTitleFont"
android:layout_width="wrap_content"
android:text="#string/overall_rating" />
<ImageView
android:id="#+id/overall_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:src="#drawable/icon_rating_empty" />
<ImageView
android:id="#+id/overall_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/icon_rating_empty" />
<ImageView
android:id="#+id/overall_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/icon_rating_empty" />
<ImageView
android:id="#+id/overall_4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/icon_rating_empty" />
<ImageView
android:id="#+id/overall_5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/icon_rating_empty" />
<TextView
android:id="#+id/overall_score"
style="#style/ProductTitleFont"
android:layout_width="wrap_content"
android:layout_marginLeft="10dp"
android:text="4.6" />
</LinearLayout>
<Button
android:id="#+id/rate_review_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#id/overall_section"
android:layout_marginBottom="#dimen/margin_sides"
android:layout_marginTop="#dimen/margin_sides"
android:text="#string/rate_review_button_text" />
</RelativeLayout>
<View
android:id="#+id/attributes_divider"
android:layout_width="fill_parent"
android:layout_height="1dp"
android:layout_below="#id/attributes_section"
android:layout_marginBottom="#dimen/margin_sides"
android:layout_marginTop="#dimen/margin_sides"
android:background="#color/pdp_section_divider" />
<TextView
android:id="#+id/review_count"
style="#style/ProductTitleFont"
android:layout_width="wrap_content"
android:layout_below="#id/attributes_divider"
android:layout_marginLeft="#dimen/margin_sides"
android:text="0 " />
<TextView
style="#style/ProductTitleFont"
android:layout_width="wrap_content"
android:layout_alignBaseline="#id/review_count"
android:layout_marginRight="#dimen/margin_sides"
android:layout_toRightOf="#id/review_count"
android:text="#string/customer_reviews" />
<View
android:id="#+id/review_count_divider"
android:layout_width="fill_parent"
android:layout_height="1dp"
android:layout_below="#id/review_count"
android:layout_marginBottom="#dimen/margin_sides"
android:layout_marginTop="#dimen/margin_sides"
android:background="#color/pdp_section_divider" />
</RelativeLayout>
</RelativeLayout>
Update: I tried reducing the header .xml file to just a single TextView and the problem continues. So I don't believe the problem is being cause by something in the xml.
FrameLayout and AbsListView convert their children layout params to FrameLayout.LayoutParams and AbsListView.LayoutParams. This is where the casting fails.
View header = View.inflate(this, R.layout.header_layout, null);
should fix it.
Edit:
As mentioned in the comments, changing the ViewGroup Parameter of the inflate call also makes it work:
header = inflater.inflate(R.layout.header_layout, null, false);
Although Souvlaki's method will fix the issue and allow you to continue working. It is always best to give the view being inflated a reference to the container it will be in. This allows for Android to correctly inflate it for the right context.
What you should do is find the ListView and then pass that to the inflate.
ListView listView = (ListView) layout.findViewById(R.id.listview);
View header = inflater.inflate(this, R.layout.header_layout, listView, false);
I see same situation.
in my case, it's a trouble that call timing for ListView.addHeaderView().
Before: (Error)
ListView.addHeaderView() is called in Fragment.onCreateView() method.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.fragment_main, container, false);
mListView = (ListView) layout.findViewById(R.id.listview);
mListView.addHeaderView(inflater.inflate(R.layout.list_header_book, listview, false));
return layout;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mAdapter = new BookAdapter(getActivity(), mBookList);
mListView.setOnItemClickListener(mBookItemClickListener);
mListView.setAdapter(mAdapter);
}
After:(OK)
ListView.addHeaderView() is called in Fragment.onActivityCreated() method.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main, container, false);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mAdapter = new BookAdapter(getActivity(), mBookList);
mListView = (ListView) getView().findViewById(R.id.listview);
mListView.setOnItemClickListener(mBookItemClickListener);
mListView.addHeaderView(LayoutInflater.from(getActivity()).inflate(R.layout.list_header_book, null));
mListView.setAdapter(mAdapter);
}
From drspaceboo's post above, this worked for me:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
mListLayoutView = inflater.inflate(getLayoutId(), container, false);
int headerLayoutId = R.layout.list_header_layout;
mListHeaderView = inflater.inflate(headerLayoutId, mResourcesListView, false);
// ...
mResourcesListView.addHeaderView(mListHeaderView, null, false);
Where getLayoutId() returns the main layout that contains the ListView xml