All these days, I avoided using fragments. But then I realized for my this particular applications fragments are ideal. I have a master - detail list in my app.
Let us say you want to have two fragments - one is a fragment which contains a list of elements and second one expands one element of the list. Both of them share the same cursor from the activity.
Let us start with list fragment.
Do not try creating list fragment using a wizard. It unnecearrily adds too many methods and classes.
Let us start writing our own fragment like this
Next using code menu override option, override the following method
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
This method should be used for inflating the layout file for the fragment. I have a framelayout in parent activity of this fragment with the id as container. So I will specify that for inflating. The framelayout will be the parent viewgroup for fragment.
R.layout.listfragment is my layout file which for the fragment. Here it is
Note that the ids of both ListView and TextView are android ids. This is needed because we want to use listfragment methods for most of our works, instead of getting listview with the help of findviewbyid etc.
How about the adapter for the list? I am having a database cursor for my list. So I can use simple cursor adapter. The adapter should be set in onActivityCreated() method.
Where is the cursor for the adapter? Instead of trying to fetch the cursor all over again, you can access the cursor from the activity. (Make sure it is not private). Using getActivity() and typecasting it to parent activity name, you get access to parent activity. Next you access cursor from there.
OK. The first parameter to SimpleCursorAdapter is context. Second parameter is the layout for each row of the list. You can use android.R.layout.simple_list_item_1. Or you can write your own layout file.
Third parameter is cursor. And fourth and fifth are mapping of columns in cursor to views in listview.
Now how do we handle item clicks?
You can write an interface in the fragment. And when item is clicked from list, call the function of this interface. Now the parent activity must implement this interface in order to listen to itemclick of this fragment.
Let us write the interface.
Create an instance of this interface in onActivityCreated method. Developers tutorial asks you to create call back instance in onAttach() method. I faced some difficulties. So I am writing it in onActivityCreated() method like this.
Now the thing remaining is how do we use this interface.
Override the OnListItemClick() method of ListFragment and here call the OnItemSelected method of interface.
OK. Now our onclick method is ready to go to the parent activity.
Parent activity needs few lines of code.
In order to use Fragments with support library, you need to extend your class from FragmentActivity.
Here is the layout file of the activity - R.layout.listact
In oncreate method of we are fetching the cursor and then creating a fragment and adding it to frame layout.
Notice that we are implementing the interface here. Android studio forces you to implement the method of the OnListItemSelectedListener interface. We complete its code.
Let us say you want to have two fragments - one is a fragment which contains a list of elements and second one expands one element of the list. Both of them share the same cursor from the activity.
Let us start with list fragment.
Do not try creating list fragment using a wizard. It unnecearrily adds too many methods and classes.
Let us start writing our own fragment like this
class MyListFragment extends ListFragment{ }
Next using code menu override option, override the following method
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
This method should be used for inflating the layout file for the fragment. I have a framelayout in parent activity of this fragment with the id as container. So I will specify that for inflating. The framelayout will be the parent viewgroup for fragment.
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.listfragment,container,false); }
R.layout.listfragment is my layout file which for the fragment. Here it is
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" 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" /> <TextView android:id="@android:id/empty" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="No items in list" /> </LinearLayout>
Note that the ids of both ListView and TextView are android ids. This is needed because we want to use listfragment methods for most of our works, instead of getting listview with the help of findviewbyid etc.
How about the adapter for the list? I am having a database cursor for my list. So I can use simple cursor adapter. The adapter should be set in onActivityCreated() method.
Where is the cursor for the adapter? Instead of trying to fetch the cursor all over again, you can access the cursor from the activity. (Make sure it is not private). Using getActivity() and typecasting it to parent activity name, you get access to parent activity. Next you access cursor from there.
@Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); MyActivity act = (MyActivity) getActivity(); mCursor = act.mCursor; SimpleCursorAdapter adapter = new SimpleCursorAdapter(act, android.R.layout.simple_list_item_1, mCursor, new String[]{"name"}, new int[]{android.R.id.text1}, 0); setListAdapter(adapter); }
OK. The first parameter to SimpleCursorAdapter is context. Second parameter is the layout for each row of the list. You can use android.R.layout.simple_list_item_1. Or you can write your own layout file.
Third parameter is cursor. And fourth and fifth are mapping of columns in cursor to views in listview.
Now how do we handle item clicks?
You can write an interface in the fragment. And when item is clicked from list, call the function of this interface. Now the parent activity must implement this interface in order to listen to itemclick of this fragment.
Let us write the interface.
package your.package.name; public interface OnListItemSelectedListener{ public void OnItemSelected(int position); }
Create an instance of this interface in onActivityCreated method. Developers tutorial asks you to create call back instance in onAttach() method. I faced some difficulties. So I am writing it in onActivityCreated() method like this.
public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); ........ try { mCallback = (OnListItemSelectedListener) act; } catch (ClassCastException e){ Toast.makeText(act,"Class must implement OnListItemSelectedListener",Toast.LENGTH_SHORT).show(); } }
Now the thing remaining is how do we use this interface.
Override the OnListItemClick() method of ListFragment and here call the OnItemSelected method of interface.
@Override public void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); if(mCallback!=null) mCallback.OnItemSelected(position); }
OK. Now our onclick method is ready to go to the parent activity.
Parent activity needs few lines of code.
public class MyActivity extends FragmentActivity implements OnListItemSelectedListener { private MySqliteHelper mSqliteHelper; private int mPos; private MyListFragment fragment; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.listact); mCursor=mSqliteHelper.getallrows(); fragment = new MyListFragment(); getSupportFragmentManager().beginTransaction().add(R.id.list_container,fragment).commit(); } }
In order to use Fragments with support library, you need to extend your class from FragmentActivity.
Here is the layout file of the activity - R.layout.listact
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginLeft="5dp" android:layout_marginRight="5dp" android:id="@+id/list_container" /> </LinearLayout>
In oncreate method of we are fetching the cursor and then creating a fragment and adding it to frame layout.
Notice that we are implementing the interface here. Android studio forces you to implement the method of the OnListItemSelectedListener interface. We complete its code.
@Override public void OnItemSelected(int position) { mPos = position; //do something }
Comments
Post a Comment