My Fragment layout:
<RelativeLayoutLayout 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"
>
<ListView
android:id="#+id/my_list"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayoutLayout>
In my Fragment class:
ListView myList;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//NullPointerException
myList = (ListView) getView().findViewById(R.id.my_list);
...
}
Why I get NullPointerException when trying to get the ListView ?
You are trying to access your Fragment's View before the View has been inflated.
onCreateView() is where you create the View, not where you should be accessing the Views (onViewCreated() is more appropriate for that).
Your onCreateView() should have something like this to inflate your View:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.my_fragment_layout, container, false);
// If you want to do something with the layout here, you can
return layout;
}
As I couldn't find any fragment layout file which returns View to onCreateView(). So I think you missed it.
Your code look like,
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.<layout_xml>, container, false); // You missed this line
myList = (ListView) v.findViewById(R.id.my_list); // Now access myList from View v
return v;
Related
I'm about to set an ImageView with setImageResource, but it's not working. nothing error too. and the logcat seems fine.
Here is my code :
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_item_list_request, container, false);
setHasOptionsMenu(true);
View anotherView = inflater.inflate(R.layout.style_fragment_list_request,container,false);
imgView = (CircleImageView)anotherView.findViewById(R.id.listPhoto);
imgView.setImageResource(R.drawable.pastel_red);
}
Considering that I called and declare the ImageView from another layout. Is at problem if I inflate 2 layouts just for set image for another layout ?
Anything wrong here?
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_item_list_request, container, false);
setHasOptionsMenu(true);
return view;
}
public void onActivityCreated(){
ViewGroup layout = (ViewGroup) getView().findById(R.id.layout_another_view); // need layout for anotherView in fragment_item_list_request.xml
View anotherView = inflater.inflate(R.layout.style_fragment_list_request,container,false);
imgView = (CircleImageView)anotherView.findViewById(R.id.listPhoto);
imgView.setImageResource(R.drawable.pastel_red);
layout.addView(anotherView);
}
What if you do this instead:
View anotherView = inflater.inflate(R.layout.style_fragment_list_request,null,false);
The statement return anotherView; is missing in onCreateView().
I am trying to define a listview with a corresponding Adapter to add string to the listview. Howevewr, my listview comes as being null. The code is as below:-
public class CategoryFragment extends Fragment {
....
....
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ListView listView = (ListView) getActivity().findViewById(R.id.cat_vacancies);
listAdapter = new ArrayAdapter<String>(getActivity(),android.R.layout.simple_list_item_2);
listView.setAdapter(listAdapter);
....
}
}
What have I done wrong at this point?
my fragment xml is as follows( I have only added the relevant portions which I think may help in diagnosing the problem)
<RelativeLayout>
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/cat_vacancies">
</ListView>
</RelativeLayout>
P.S. This is, as far as I know, a silly mistake, but I have not yet completely grasped android completely, so excuse my problems.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.[layout id], container, false);
ListView listView = (ListView) view.findViewById(R.id.cat_vacancies);
retrun view;
}
Try whit that way
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.yourFragmentXml, container, false);
ListView listView = (ListView) view.findViewById(R.id.cat_vacancies);
listAdapter = new ArrayAdapter<String>(getActivity(),android.R.layout.simple_list_item_2);
listView.setAdapter(listAdapter);
....
}
Inside a fragment I try to inflate two layouts besides the root layout:
View a, b;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.list_fragment, container, false);
//..
a = inflater.inflate(R.layout.empty_list_view, container);
b = inflater.inflate(R.layout.progress_list_view, container);
//..
return root;
}
public void showB() {
a.setVisibility(GONE);
b.setVisibility(VISIBLE);
}
So I just return a single layout from the onCreateView method. However I inflate two more, a and b.
However when I display b actually a will be displayed. So progress_list_view never shows up. Can someone explain this strange behavior?
I suspect that a and b are both added to the container (ViewGroup). And since a is added first, it will be displayed first.
edit:
The point is, you're doing a huge mess and there is no good reason why you're doing it.
What happens there is that you inflate root, but not attach it to the container with this line View root = inflater.inflate(R.layout.list_fragment, container, false);
Then you inflate two views and add them directly to the container with those lines a = inflater.inflate(R.layout.empty_list_view, container);, which is a wrong thing to do as per Fragment documentation:
The fragment should not add the view itself, but this can be used to generate the LayoutParams of the view
also both a and b are the same object, which is the container object as per documentation for the LayoutInflater
If root was supplied, this is the root
and root was supplied by you and it's the container, so what you have is basically the same asa=container; b=container;
and then you return root, at which point I really don't know what is happening anymore due to this mess. I decribed.
Lucky to fix is easy:
create another XML layout like this (shortened):
<FrameLayout>
<include layout="#layout/empty_list_view"/>
<include layout="#layout/progress_list_view"/>
</FrameLayout>
then you inflate this new XML:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.new_xml, container, false);
a = root.findViewById( .. ID of the root of empty_list_view.. )
b = root.findViewById( .. ID of the root of progress_list_view.. )
return root;
}
then the code will work.
original answer:
There's no strange behavior. You inflated those layouts and you have 2 View objects that are representative of them. But nothing attached those Views to the UI.
Only the view that you return from the onCreateView method that will be attached to the device UI.
For example:
the following code will show a:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//..
View a = inflater.inflate(R.layout.empty_list_view, container);
View b = inflater.inflate(R.layout.progress_list_view, container);
//..
return a;
}
the following code will show b:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//..
View a = inflater.inflate(R.layout.empty_list_view, container);
View b = inflater.inflate(R.layout.progress_list_view, container);
//..
return b;
}
if you want to have them both togeher you should put them together in the XML layout file. Maybe using an include tag if you need it re-usable.
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout layoutMain = new LinearLayout(this);
layoutMain.setOrientation(LinearLayout.HORIZONTAL);
setContentView(layoutMain);
LayoutInflater inflate = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// 1st Layout
RelativeLayout layoutLeft = (RelativeLayout) inflate.inflate(
R.layout.main, null);
// 2nd Layout
RelativeLayout layoutRight = (RelativeLayout) inflate.inflate(
R.layout.row, null);
RelativeLayout.LayoutParams relParam = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
layoutMain.addView(layoutLeft, 100, 100);
layoutMain.addView(layoutRight, relParam);
}
You can only return one view from the onCreateView. The view that is returned is the view that is displayed. Looks like you always return view a.
R.layout.list_fragment should look something like this:
<FrameLayout>
<include
android:id="#+id/a"
layout="#layout/empty_list_view"/>
<include
android:id="#+id/b"
layout="#layout/progress_list_view"/>
</FrameLayout>
Your code will look something like this:
View a, b;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.list_fragment, container, false);
a = root.findViewById(R.id.a);
b = root.findViewById(R.id.b);
return root;
}
public void showB() {
a.setVisibility(GONE);
b.setVisibility(VISIBLE);
}
Why don't you inflate new view in the container.
Try this
LayoutInflater mInflater = null;
ViewGroup mContainer = null;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mInflater = inflater;
mContainer = container;
View root = inflater.inflate(R.layout.list_fragment, container, false);
return root;
}
public void showB() {
mInflater.inflate(R.layout.progress_list_view, mContainer, false);
}
public void showA() {
mInflater.inflate(R.layout.empty_list_view, mContainer, false);
}
I am creating a new Tab interface and for every tab I have functionality like:
public class ClassViewFragment extends Fragment {
ListView classListView = null;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.class_view, container, false);
classListView = (ListView) findViewById(R.id.classList);
return rootView;
}
}
But I am getting cannot resolve method findViewById also at another place I am also unable to use runOnUiThread and getting Error:(88, 29) error: cannot find symbol method runOnUiThread(<anonymous Runnable>)
I understand these will work fine if my class was extended from Activity but it’s a tab fragment so how can I use this funcitons?
you need
classListView = (ListView) rootView.findViewById(R.id.classList);
as that is the view you are concerned with
to get runOnUiThred you need to do getActivity().runOnUiThread
You need to reference findViewById using the view,
public class ClassViewFragment extends Fragment {
ListView classListView = null;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.class_view, container, false);
classListView = (ListView) rootView .findViewById(R.id.classList);
return rootView;
}
}
For runOnUiThread is a possible duplicate of Modifying an Android view from a different thread
use its like,
activity.runOnUiThread(new Runnable());
Here is a shore explanation of findViewById method;
findViewById() method will work with the related object that your main layout is bound to. For example, In an activity, when you make a
setContentView(activity_main);
You imply that your Activity will retrieve its layouts from activity_main. So when you make a findViewById() in an activity, that actually means this.findViewById(), where this is your Activity.
So in your case, the layout class_view is bound to the rootView. But when you just write findViewById, it means that this.findViewById. And this is the scope you're in, which is the Fragment in your case. However, I don't think a Fragment has that capability. So you should refer to the rootView to retrieve your views.
rootView.findViewById()
Fragments don't have a findViewById() method like Activity, so you have to call the method of the root view of the fragment. Try doing rootView.findViewById(R.id.classList) instead.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_content_mediaplayer, container, false);
mSeekbar = (SeekBar) v.findViewById(R.id.seekBarMusic);
return v;
Use rootView.findViewById(R.id.classList) instead of findViewById(R.id.classList).
Try this:
public class ClassViewFragment extends Fragment {
ListView classListView = null;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.class_view, container, false);
classListView = (ListView) rootView.findViewById(R.id.classList);
return rootView;
}
}
findViewById must run inside onViewCreated() method
ListView classListView = null;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.class_view, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
classListView = (ListView) view.findViewById(R.id.classList);
}
}`
So I am finally learning Fragments after learning Activities. I am looking at a video tutorial. All of a sudden he changed the way a Fragment inflates a layout. Why does he have two different ways? The first way in FragmentA is:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_a, container, false);
}
Then the other way in FragmentB is:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_b, container, false);
if (savedInstanceState == null)
{
}
else {
savedInstanceState.getString("text");
TextView myText = (TextView) view.findViewById(R.id.textView);
myText.setText(data);
}
return view;
}
So why did it change from return inflater.inflate to View view = inflater.inflate
Sorry for dumb question, but I can't find this answer on Google.
It's basically the same,
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
has to return a View.
And
inflater.inflate(R.layout.fragment_b, container, false)
returns a View as well.
In the second example he assigns the return value of inflater.inflate() to a View object, as he needs to loads some data and set it on this View object... then he returns it.
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View rootView = inflater.inflate(R.layout.lstindicators, container,
false);
And return your view thats all! :D
jejeje... and if you want to change your current fragment for another chechk this:
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.content_frame, fragment).commit();