Afternoon all,
I'm currently learning all about fragments and their use in android apps. I'm trying to populate a listView with an array of Strings. This sort of idea worked when I was populating the list without using fragments but at the moment it's throwing a runtime exception "Unable to start activity". A simple point at where to look would be much appreciated as I can't figure out the logcat reading.
The fragment is thus:
public class setupFragment extends Fragment {
#Override
public void onAttach(Context context) {
super.onAttach(context);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_setup, container, false);
ListView listView = (ListView)getView().findViewById(R.id.listView); //the program seems to at this point
String[] setups = getResources().getStringArray(R.array.setups);
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, android.R.id.text1, setups);
listView.setAdapter(arrayAdapter);
return view;
}
}
It's my first time posting java fragments, so any posting errors I apologize for. Cursory breakpoint debugging indicates that the program is breaking on the ListView declaration.
I can post some of the logcat on request, I'm not posting it at the moment due it being long and convoluted.
Replace: ListView listView = (ListView)getView().findViewById(R.id.listView);
with: ListView listView = (ListView) view.findViewById(R.id.listView);
You can't call getView() before returning one from onCreateView().
getView() returns null.
Replace getView() with view, returned object
ListView listView = (ListView)getView().findViewById(R.id.listView);
String[] setups = getResources().getStringArray(R.array.setups);
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, android.R.id.text1, setups);
listView.setAdapter(arrayAdapter);
Cut this code and paste it inside onViewCreated method, you cannot get a reference of a view by calling getView() since that view is not attached to that fragment yet.
Also change your getView() to just view.
Your ListView declaration should be as follows :
ListView listView = (ListView) view.findViewById(R.id.listView);
Refer this link to know more about getView() and Fragments. Basically the getView() method returns the root view of the fragment which is nothing but the view returned by onCreateView()
Related
Ok so i tried to learn of all These other questions here, but i am not getting the hang of it, so i decided to ask by myself.
I got a Main Activity with different Fragments for changing the views (used the Android Standard sidebar activity template). From there the user creates Tasks via a separate Acitivty which Returns the values. In the Main Activity the Tasks are getting stored into the SQLite-database. So far it works.
Now i have the Fragment TaskList with the corresponding layout TaskList_main.xml. In this XML file i got a simple ListView which i want to fill with the values from the database. My Problem is where to write that method and when to Access it. the method would be
public void showAllListEntries() {
List<TaskData> TaskList = datasource.getAllTasks();
//Daten werden im ArrayAdapter gespeichert
ArrayAdapter<TaskData> TaskListArrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, TaskList);
ListView TaskDataListView = (ListView) findViewById(R.id.TaskListView);
TaskDataListView.setAdapter(TaskListArrayAdapter);
}
My Fragment is empty like this atm
public class TaskList extends Fragment {
View view;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.activity_main_tasklist, container, false);
return view;
}
}
I can also send the main Activity if you like but it's a bit messy
So can someone tell me how i get this to work? And did i explain my Problem clearly?
You can do it in onCreateView. But you should make an async call to get the tasks to display and have your fragment as a listener. When you get the tasks you can create your adapter and attach it to the ListView.
And you should have a ProgressBar in TaskList_main.xml (which should be renamed to task_list_fragment.xml, I don't think there is a naming convention for layouts, but this is quite used) and hide it when you receive the data.
I've got the following function:
public static class ListFragment extends Fragment {
private ParseQueryAdapter<ParseObject> mainAdapter;
private ListView listView;
public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState )
{
View rootView = inflater.inflate(R.layout.fragment_list, container, false );
mainAdapter = new ParseQueryAdapter<ParseObject>( this, "Todo" );
mainAdapter.setTextKey("title");
mainAdapter.setImageKey("image");
// Initialize ListView and set initial view to mainAdapter
listView = (ListView) findViewById(R.id.list);
listView.setAdapter(mainAdapter);
mainAdapter.loadObjects();
return rootView;
}
}
The errors returned are:
The constructor ParseQueryAdapter(MainActivity.ListFragment, String) is undefined MainActivity.java
Cannot make a static reference to the non-static method findViewById(int) from the type Activity MainActivity.java
I can assume that the first one due to the change of the object of type this but I would like a more seasoned input on the correct fix.
The second error though thoroughly confounds as it appears to be valid to my eyes.
Appreciate any input.
1) Change the instantiation of ParseQueryAdapter as follows. The code is in a Fragment, but ParseQueryAdapter requires a Context object.
mainAdapter = new ParseQueryAdapter<ParseObject>( this.getActivity(), "Todo" );
2) Remove the static modifier from your class definition.
I got a ListView with a custom Adapter.
In the Adapter a layout is inflated from xml.
All works fine, and I can see the items, until the Screen Orientation is changed.
I know that the Activity is recreated (or resumed) then, and the ListView is recreated too, as well as the Adapter.
But there are no items in the ListView now. The Adapter isn't empty, I use toasts to display the count of items in the Adapter.
I guess there is an inflating problem, because if I use the same Adapter (or an adapter with the same data) to a new ListView nothing is shown as well.
But the most crazy thing I don't understand is, that if I let my getView() method return a simple TextView, all works fine, even after orientation change.
I tried several things, like don't recycle a View so that it is inflated every time, or save the View to the matching Item (from getItem(position) from the Adapter).
I'm grateful for all hints :)
EDIT: so I was asked for some code.
Here is the getView() of my Adaptar
#Override
public View getView(final int position, View convertView,
ViewGroup parent) {
View view = convertView;
final Event event = getItem(position);
if (view == null) {
view = inflater.inflate(R.layout.new_event_item_layout, parent,
false);
view.setTag(R.id.eventDate, view.findViewById(R.id.eventDate));
view.setTag(R.id.eventTime, view.findViewById(R.id.eventTime));
view.setTag(R.id.eventName, view.findViewById(R.id.eventName));
view.setTag(R.id.eventBemerkungen,
view.findViewById(R.id.eventBemerkungen));
view.setTag(R.id.eventIcon, view.findViewById(R.id.eventIcon));
}
((TextView) view.getTag(R.id.eventDate)).setText(event.getDate());
((TextView) view.getTag(R.id.eventTime)).setText(event.getName());
((TextView) view.getTag(R.id.eventName)).setText(event.getTime());
((TextView) view.getTag(R.id.eventBemerkungen)).setText(event
.getDescription());
SquaredImageView icon = (SquaredImageView) view.getTag(R.id.eventIcon);
Picasso.with(context).load(event.getUri())
.placeholder(R.drawable.ic_reload).into(icon);
view.setBackgroundColor(event.getBackgroundColor());
view.setVisibility(View.VISIBLE);
return view;
//return getDummyTextView();
}
public TextView getDummyTextView()
{
TextView tv=new TextView(context);
tv.setText("YOLO BIATCHSES");
tv.setTextColor(Color.WHITE);
return tv;
}
I have had the same exact problem although it wasn't because of orientation change and I found the solution by just setting listView.setAdapter(adapter) again after the recreation of the activity or whatever case you have. I suspect the listview is basically losing the pointer to the adapter.
I am not entirely sure this is the right SE to ask this on but I am wondering if this is expected when developing for android. I am ending up with a larger containing class and then a significant amount of nested/newed anonymous classes for callbacks within callbacks. I am wondering if this is expected or if there is a better way of doing this as the amount of nested classes is starting to lead to very convoluted code.
This is just a dialog fragment that has some settings on it. When you click on a setting it populates a list view with the appropriate options and when you select an option it updates the value that you clicked on. It is a DialogFragment with a nested anonymous OnClickListener() that then assigns a nested anonymous OnItemClickListener() to a ListView type of object. This allows me to use the ListView object for multiple settings with having to duplicate the ListView for each one of them (I just bind a new adapter and OnItemClickListener to it).
class MyDialogFragment extends DialogFragment
{
protected View _root;
protected ListView _listViewSomeSettingOptions;
protected TextView _textViewSomeSetting;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
_root = inflater.inflate(R.layout.layout_for_dialog, container, false);
_listViewSomeSettingOptions = (ListView)_root.FindViewById(R.id.listViewSettingOptions);
_textViewSomeSetting.setOnClickListener(new OnClickListener()
{
protected ArrayList<String> _someSettingOptions = new ArrayList<String>();
// Fill _someSettingOptions with a list of options
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, _someSettingOptions);
_listViewSomeSettingOptions.setAdapter(adapter);
_listViewSomeSettingOptions.setOnItemClickListener(new OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
_textViewSomeSetting.setText(_someSettingOptions.get(position));
}
}
}
}
}
Is this just how it goes? Should I be making custom controls that implement the listeners instead of using the anonymous ones? This DialogFragment is approaching 1000 lines all in onCreateView now handling the different options and display updates of a user tweaking the setting options and its just tingling my "Maybe this is not the best design" sense. I guess besides Upkeep I am wondering if there is a drawback to this form of development.
I have a dialog which extends DialogFragment:
public class MyCustomDialogFragment extends DialogFragment {
static MyCustomDialogFragment newInstance() {
return new MyCustomDialogFragment();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.institutional_info_custom_list, container, false);
return view;
}
}
And this is where I use this dialog (it is inside an onclick listener):
MyCustomDialogFragment newFragment = MyCustomDialogFragment.newInstance();
View DialogView = newFragment.getView();
DetailListView = (ListView) DialogView.findViewById(R.id.custom_dialog_list);
final MasterDetailArrayAdapter adapter = new MasterDetailArrayAdapter(ComeHaInvestito.this, MasterAndDetailstatisticsInfoList);
DetailListView.setAdapter(adapter);
newFragment.show(getFragmentManager(), "master_detail_dialog");
MasterAndDetailstatitiscsInfoList is a list I am using with my custom ArrayAdapter, but the problem is with the View of the DialogFragment: it is null! Why? I read the android documentation and they say that getView() returns the View of the dialog which is the one returned by the onCreateView() overriden method.
So why I get a null pointer exception when trying to revocer the ListView which is in the dialogFragments layout???
Sorry but this does not make sense to me. An explanation will be appreciated.
Thanks!
Use setArguments() to provide the dataset for the Adapter to the DialogFragmet. In DialogFragment override onViewCreated(), retrieve the ListView, create the Adapter and set it to the ListView