Reputation: 33
I am following the book and I made a list view using fragment. But I can't config the Action Bar in that application because now I want to add option menu to action bar. Here is the my code in github. I am really grateful if someone can point me where should I change my code.
I try to figure out what is different in my code with new project template but couldn't figure it out.
Code :
This is the base activity to inherit to all Activity
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
// universal fragment activity
public abstract class SingleFragmentActivity extends FragmentActivity {
protected abstract Fragment createFragment();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment);
FragmentManager manager = getSupportFragmentManager();
Fragment fragment = manager.findFragmentById(R.id.fragmentContainer);
if (fragment == null) {
fragment = createFragment();
manager.beginTransaction()
.add(R.id.fragmentContainer, fragment)
.commit();
}
}
}
This is the layout file that above fragment activity used by [R.id.fragmentContainer]
:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/fragmentContainer">
</FrameLayout>
Here is the activity that host the list activity
import android.support.v4.app.Fragment;
public class CrimeListActivity extends SingleFragmentActivity {
@Override
protected Fragment createFragment() {
return new CrimeListFragment();
}
}
Here is the list fragment activity :
import java.util.ArrayList;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.TextView;
public class CrimeListFragment extends ListFragment {
private ArrayList<Crime> mCrimes;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
getActivity().setTitle(R.string.crimes_title);
mCrimes = CrimeLab.get(getActivity()).getCrimes();
CrimeAdapter adapter = new CrimeAdapter(mCrimes);
setListAdapter(adapter);
}
public void onListItemClick(ListView l, View v, int position, long id) {
// get the Crime from the adapter
Crime c = ((CrimeAdapter)getListAdapter()).getItem(position);
// start an instance of CrimePagerActivity
Intent i = new Intent(getActivity(), CrimePagerActivity.class);
i.putExtra(CrimeFragment.EXTRA_CRIME_ID, c.getId());
startActivityForResult(i, 0);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
((CrimeAdapter)getListAdapter()).notifyDataSetChanged();
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.fragment_crime_list,menu);
}
private class CrimeAdapter extends ArrayAdapter<Crime> {
public CrimeAdapter(ArrayList<Crime> crimes) {
super(getActivity(), android.R.layout.simple_list_item_1, crimes);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// if we weren't given a view, inflate one
if (null == convertView) {
convertView = getActivity().getLayoutInflater()
.inflate(R.layout.list_item_crime, null);
}
// configure the view for this Crime
Crime c = getItem(position);
TextView titleTextView =
(TextView)convertView.findViewById(R.id.crime_list_item_titleTextView);
titleTextView.setText(c.getTitle());
TextView dateTextView =
(TextView)convertView.findViewById(R.id.crime_list_item_dateTextView);
dateTextView.setText(c.getDate().toString());
CheckBox solvedCheckBox =
(CheckBox)convertView.findViewById(R.id.crime_list_item_solvedCheckBox);
solvedCheckBox.setChecked(c.isSolved());
return convertView;
}
}
}
Here is the layout that used by CrimeAdapter inner class
[R.layout.list_item_crime]
:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<CheckBox
android:id="@+id/crime_list_item_solvedCheckBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_alignParentRight="true"
android:enabled="false"
android:padding="4dp"
android:focusable="false"/>
<TextView
android:id="@+id/crime_list_item_titleTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toLeftOf="@id/crime_list_item_solvedCheckBox"
android:textStyle="bold"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:text="Crime Title"/>
<TextView
android:id="@+id/crime_list_item_dateTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/crime_list_item_titleTextView"
android:layout_toLeftOf="@id/crime_list_item_solvedCheckBox"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:paddingTop="4dp"
android:text="Crime Date"/>
</RelativeLayout>
So where should I change to added a Action bar ??
Upvotes: 0
Views: 425
Reputation: 13932
I made a few simple changes first edit to styles.xml:
<!-- Changed your app theme -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
then updated SingleFragmentActivity.java to extend AppCompatActivity:
public abstract class SingleFragmentActivity extends AppCompatActivity {
protected abstract Fragment createFragment();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment);
FragmentManager manager = getSupportFragmentManager();
Fragment fragment = manager.findFragmentById(R.id.fragmentContainer);
if (fragment == null) {
fragment = createFragment();
manager.beginTransaction()
.add(R.id.fragmentContainer, fragment)
.commit();
}
}
}
then created a menu_list.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_settings"
android:orderInCategory="100"
android:title="Settings"
app:showAsAction="ifRoom"/>
</menu>
And then have CrimeListActivity inflate and handle options menu clicks:
public class CrimeListActivity extends SingleFragmentActivity {
@Override
protected Fragment createFragment() {
return new CrimeListFragment();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_list, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int itemId = item.getItemId();
if(itemId == R.id.action_settings){
// Handle the action
return true;
}
return super.onOptionsItemSelected(item);
}
}
This will only add it to your one CrimeListActivity though. To make the change across the board. You will need to have all Activity classes that don't use SingleFragmentActivity extend AppCompatActivity
Explanation
Basic Reason why these changes work:
FragmentActivity
does not know about the ActionBar
, if you would want something that has an ActionBar
you would need to use the newer but now deprecated Activity
which extends FragmentActivity
call ActionBarActivity
ActionBarActivity
now deprecated and replaced by AppCompatActivity
which does know about the ActionBar
when the correct Theme is Applied in your case Theme.AppCompat.Light.DarkActionBar
solves the case.
Good Luck and happy coding!
Upvotes: 2