I want a custom row, so I am using a List View in an xml and inflating into a fragment. I am very confused of how to set the adapter for the list View.
I created a new adapter which extends Base Adapter. In the getView method, I really don't know what context to pass while inflating the row.xml layout.
How do I set the adapter for the list view and where?
public class ResultsFragment extends Fragment{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.results_layout, container, false);
listView = (ListView)v.findViewById(R.id.results);
return v;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
loadPage(dataBean.getWhat(), dataBean.getWhere(), dataBean.getPageStart());
//resultsAdapter.setRssData(rssData);
//setListAdapter(resultsAdapter);
}
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
Context context = getActivity().getApplicationContext();
resultsAdapter = new ResultsAdapter(context);
}
/**
* Set List Adapter
*/
private void setAdapter(){
if(listView.getAdapter() == null){
listView.setAdapter(resultsAdapter);
}
else{
resultsAdapter.notifyDataSetChanged();
}
}
}
You must extend Listfragment (instead of Fragment), and using its ListFragment.setListAdapter to set your adapter. In the adapter getView() inflate your row.. that s all
If you do not want to change your extended class, you should use listview.setAdapter(...) method. As you see in my example :
ListView productList= (ListView) getActivity().findViewById(R.id.product_list);
SampleAdapter adapter = new SampleAdapter(getActivity());
adapter.add(new SampleItem(
"Sunny LCD TV 2\" SN022L66-T1 Full HD",
R.drawable.product_sample_pic);
productList.setAdapter(adapter);
Related
i have an ActionBar that has 2 tabs and each tabs layout is a fragment. in 1 of these tabs , there is a listView. and i want to set ArrayAdapetr for it. but when i run app, error occurred and error is about my application context. my code is :
public class TarfandFrag extends Fragment {
String values[] = new String[]{"sadeq","ali"};
ListView listView;
Context context;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.tarfad_layout,container,false);
listView = (ListView) view.findViewById(R.id.list_tarfand);
return view;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ArrayAdapter adapter = new ArrayAdapter(context,android.R.layout.simple_list_item_1,values);
listView.setAdapter(adapter);
}
}
but its not working. notice that i don't want use listFragment or anything else. i replace context with getActivity() , context.getApplicationContext, getActivity.getApplicationContext. but not working. plz help meeeee
Assing getActivity() to context in onCreate.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context=getActivity();
}
In a fragment, onCreate() is called before onCreateView(). the consequence of this is that, at the point onCreate() is called, your ListView is not yet associated with an element in the layout (as your are doing this in onCreateView() which gets called later) and will hence resolve to null and you will get a null pointer exception when you set the adapter for the ListView. Move the code setting the adapter to within the onCreateView() method and use getActivity() and you should be fine.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.tarfad_layout,container,false);
listView = (ListView) view.findViewById(R.id.list_tarfand);
// Here listview will not be null as it is now bound to an object
ArrayAdapter adapter = new ArrayAdapter(getActivity(),android.R.layout.simple_list_item_1,values);
listView.setAdapter(adapter);
return view;
}
I am building an android application containing 4 tabs, each containing a fragment attached to cursor adapter. Each fragment contains a list of items.If I scrolled a lot down in any list, I have to scroll a lot back to get to the top.I want the it to behave like this: when I click on the current tab icon, it will automatically scroll back to top. How can I implement this functionality?
edit 1:
this is how the it is implemented:-
public class OutboxFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> {
OutboxListAdapter mAdapter;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mAdapter = new OutboxListAdapter(getActivity(),R.layout.outbox_list_item, null, 0);
setListAdapter(mAdapter);
getLoaderManager().initLoader(0, null, this);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_outbox, container, false);
return view;
}
On tab changed you can refresh your list view:
MyAdapter myAdapter = new MyAdapter(mContext, items);
mListView.setAdapter(myAdapter);
mListView.setSelection(0);
Instead of setting a new adapter (which causes ListView to reset its state), simply update the content of the adapter already set on the ListView.
You can create a refill() method to your adapter:
public void refill(List<EventLog> events) {
mEvents.clear();
mEvents.addAll(events);
notifyDataSetChanged();
}
And call it onTabChanged:
if (mListView.getAdapter() == null) {
MyAdapter myAdapter = new MyAdapter(mContext, items);
mListView.setAdapter(myAdapter);
} else {
((MyAdapter)mListView.getAdapter()).refill(items);
}
based on your problem you need to scroll the fragment list to the top. you can do this by calling following function:
getListView().smoothScrollToPosition(0);
which getlistView returns your fragment ListView;
I developed an app which fills a list. It works fine in the way I did it but I'm not conviced that I solved the problem in a recommended way. I read that you should override onActivityCreated in a Fragment and fill the list there instead of doing this in onCreateView. onCreateView should only be used to inflate static views. Is this true? If yes, how should these two methods look like in the end?
This is my Fragment class:
public class FragmentMain extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main, container, false);
List<MyItem> items = createListItems();
ListView listView = (ListView) view.findViewById(R.id.list);
MyListAdapter adapter = new MyListAdapter(view.getContext(), items);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(view.getContext(),
"Clicked " + position, Toast.LENGTH_LONG)
.show();
}
});
return view;
}
.
.
.
}
My MainActivity just adds the fragment:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentMain fm = new FragmentMain();
getFragmentManager().beginTransaction()
.add(R.id.fragment_main_container, fm).commit();
}
.
.
.
}
That is true to a certain extend only because onCreateView happens on the UI thread and you don't want anything slowing that down otherwise your UI will be slow and choppy. For example, in your fragment class you have a call to a method "createListItems()". I don't know how many items you're making but if it's a lot it could slow down your UI (especially if youre accessing a database and querying objects and so on). So you could do it in onActivityCreated but you could also use an AsyncTask. So your code would become something like this:
public class LoadListObjectsTask extend AsyncTask<Void, List<MyItem>, Void> {
private MyListAdapter myListAdapter;
private Context mContext;
public LoadListObjectsTask(Context context) {
this.mContext = context;
}
#Override
public void doInBackground(Void...params) {
//create your list objects here instead of on UI thread. This will run on a separate thread.
myListAdapter = new MyListAdapter(mContext, items);
return items; //return list of MyItems
}
//This is called when doInBackground is done. THIS WILL RUN ON THE UI THREAD So don't do
//anything slow here
#Override
public void onPostExecute(List<MyItem>...params //don't really need the list here//) {
listView.setAdapter(myListAdapter);
}
}
then in your fragment
public class FragmentMain extends Fragment {
private ListView listView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main, container, false);
List<MyItem> items = new ArrayList<MyItem>();
listView = (ListView) view.findViewById(R.id.list);
//new code
new LoadListObjectsTask(getActivity()).execute();
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(view.getContext(),
"Clicked " + position, Toast.LENGTH_LONG)
.show();
}
});
return view;
}
public void onResume()... {
//also add the task here so your content is reloaded on resume..
new LoadListObjectsTask(getActivity()).execute();
}
.
.
.
}
If you don't want to do this just make your List of MyItems a private field and move
List<MyItem> items = createListItems();
to onActivityCreated().
Hope that helps!
My listview gets filled on the start but after i cant find a way to make changes
pls see the code bellow
public class myFragment extends android.support.v4.app.Fragment
{
ListView list;
ArrayList<String> restorants=new ArrayList<String>();
Manager m=new Manager();
ArrayAdapter<String> adapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_, container, false);
list=(ListView) rootView.findViewById(R.id.myList);
for(Restorant r : m.getResByCity("nyc"))
{
restorants.add(r.getName());
}
adapter=new ArrayAdapter<String>(getActivity(), R.layout.item_list, R.id.restorantItem,restorants);
list.setAdapter(adapter);
return rootView;
}
public void makeChange(String s)
{
restorants.remove(0);
((ArrayAdapter)list.getAdapter()).notifyDataSetChanged();
}
}
While calling the method makeChange() i have checked that the restorants items are removing so that there is no problem with calling the method
makeChange() is called from my mainActivity that contains viewpager where this fragment is contained in the viewpager.
you need to remove the element from the dataset you provided to the adapter,
adapter.remove(s)
Here you can find the documentation
I have a simple MyListFragment fragment which shows one simple array of data on the screen.
public class MyListFragment extends ListFragment {
private ArrayAdapter<String> adapter;
public ArrayAdapter<String> getAdapter() {
return adapter;
}
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
String[] values = new String[] {"data", "data", "data"};
adapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, values);
setListAdapter(adapter);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return super.onCreateView(inflater, container, savedInstanceState);
}
}
I wonder how can I change this data dynamically from my Activity? Please tell me if there is a simple way how to do this! I've tried but have failed...
UPD: I added a function changeContent to MyListFragment:
public void changeContent(String[] value) {
adapter.addAll(value);
adapter.notifyDataSetChanged();
}
}
As you see, adapter is a global variable and it's initialized inside onActivityCreated, but my program crashes because inside changeContent in equals null! I can't get why!
You could write a function that changes your values variable and then once you have filled it with your new data just call
adapter.notifyDataSetChanged();
to fill your list with the new data.