How to implement Android Fragment Transaction .add

2019-07-14 07:19发布

问题:

I'm would like to make my Android application use Fragment Transactions, so that I can switch between various Fragments display their associated lists. My application worked fine prior to attempting to convert to just Fragment Transactions. In my initial activity_main.xml, I removed the android:name="com.birdsall.peter.chap.ChapterFragment", it is my understanding you can't use xml defined fragments with fragment transactions.

1) I can't seem to get the .add() within getSupportFragmentManager correct with it's parameters, even with code from a working example.
I have also attempted to use the newer version of FragmentTransactions to no avail.
I even took a working example of code using getSupportFragmentManager / FragmentTransactions, modified to use the names I had, it worked. I then imported that code into my application and it fails on the .add() syntax. I'm somewhat new to Android development and can't pinpoint where I'm going wrong.

Here is my main xml layout for the FrameLayout

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >

 <FrameLayout
    android:id="@+id/fragment_container"
    android:layout_width="0dip"
    android:layout_height="match_parent"
    android:layout_weight="1" />

 <fragment
      android:id="@+id/chapterfragments"

      android:layout_width="match_parent"
      android:layout_height="match_parent" />

 <!-- Removed this from above <fragment> block to enable Fragment Transaction

 android:name="com.birdsall.peter.chap.ChapterFragment"  -->              
 </LinearLayout>

Here is the xml layout for the ChapterFragment ListView

chapterfragment.xml

<?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" >

<ListView android:id="@+id/chapterlist" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_alignParentLeft="true" />

</RelativeLayout>

Here is the layout for the details of the list chapter_info.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:orientation="vertical" android:padding="6dip">


<TextView android:id="@+id/chapter1" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_alignParentTop="true"
android:textAppearance="?android:attr/textAppearanceSmall" />

<TextView android:id="@+id/textViewLiteral" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_alignParentTop="true"
android:layout_toRightOf="@+id/chapter1" android:text=" - "
android:textAppearance="?android:attr/textAppearanceSmall" />

<TextView android:id="@+id/chaptertitle1" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_alignParentTop="true"
android:layout_toRightOf="@+id/textViewLiteral" 
android:textAppearance="?android:attr/textAppearanceSmall" />

</RelativeLayout>

Here is the MainActivity.java that I have modified. I left the 'setContentView(R.layout.activity_main);' as I thought I needed to create a view (even though it empty) to add the fragment view to.

package com.birdsall.peter.chap;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;

public class MainActivity extends FragmentActivity implements       ChapterFragment.ChapterSelectedListener {



private static final String TAG = "Main_Activity";

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, "Starting ...");

setContentView(R.layout.activity_main);


if (findViewById(R.id.fragment_container) != null) {
  if (savedInstanceState != null) {
      return;
  }

  // Create an instance of ExampleFragment
  ChapterFragment firstFragment = new ChapterFragment();


  // Add the fragment to the 'fragment_container' FrameLayout
  getSupportFragmentManager().beginTransaction()
          **.add**(R.id.fragment_container, firstFragment).commit(); 


         Log.i(TAG, "Ending ..."); 
  }

}   ...

Here is my ChapterFragment.java

package com.birdsall.peter.chap;

import android.app.Activity;
import android.app.Fragment;
import android.app.LoaderManager;
import android.content.CursorLoader;
import android.content.Loader;
import android.database.Cursor;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.Toast;

public class ChapterFragment extends Fragment implements     LoaderManager.LoaderCallbacks<Cursor> {
ChapterSelectedListener mCallback;
 // Container Activity must implement this interface
public interface ChapterSelectedListener {
    public void onChapterSelected(String position, int rowId);
}

 public SimpleCursorAdapter dataAdapter;
 private static final String TAG = "ChapterFragment";


 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState ) {
     View listview = inflater.inflate(R.layout.activity_main,null);
     ListView mList =(ListView)listview.findViewById(R.id.chapterlist);
      // The desired columns to be bound
      String[] columns = new String[] {
        TDAdb.COL_CHAPTER,
        TDAdb.COL_CHAPTERTITLE};


      // the XML defined views which the data will be bound to
      int[] to = new int[] { 
        R.id.chapter1,
        R.id.chaptertitle1,

      };

      // create an adapter from the SimpleCursorAdapter
      dataAdapter = new SimpleCursorAdapter(
        getActivity(), 
        R.layout.chapter_info, 
        null, 
        columns, 
        to,
        0);
      mList.setAdapter(dataAdapter);
      //Ensures a loader is initialized and active.
      getLoaderManager().initLoader(0, null, this);
     return listview;

 }
 @Override
 public void onStart() {
  super.onStart();
  Log.i(TAG, " onStart");
  displayListView(); 
  Log.i(TAG, " end of onStart");
 } 
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        // This makes sure that the container activity has implemented
        // the callback interface. If not, it throws an exception
        try {
            mCallback = (ChapterSelectedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement ChapterSelectedListener");
        }
    }

 @Override
public void onResume() {
  super.onResume();
  //Starts a new or restarts an existing Loader in this manager
  Log.i(TAG, " onResume");
  getLoaderManager().restartLoader(0, null, this);
 }

 private void displayListView() {

     Log.i(TAG, " Starting displayListView");
  // The desired columns to be bound
  String[] columns = new String[] {
    TDAdb.COL_CHAPTER,
    TDAdb.COL_CHAPTERTITLE};


  // the XML defined views which the data will be bound to
  int[] to = new int[] { 
    R.id.chapter1,
    R.id.chaptertitle1,

  };

  // create an adapter from the SimpleCursorAdapter
  dataAdapter = new SimpleCursorAdapter(
    getActivity(), 
    R.layout.chapter_info, 
    null, 
    columns, 
    to,
    0);

  // get reference to the ListView
  ListView listView = (ListView) getView().findViewById(R.id.chapterlist);
  // Assign adapter to ListView
  listView.setAdapter(dataAdapter);
  //Ensures a loader is initialized and active.
  getLoaderManager().initLoader(0, null, this);


  listView.setOnItemClickListener(new OnItemClickListener() {
   @Override
   public void onItemClick(AdapterView<?> listView, View view, 
     int position, long id) {


    // Get the cursor, positioned to the corresponding row in the result set
    Cursor cursor = (Cursor) listView.getItemAtPosition(position);

    String chaptervalueselected = 
    cursor.getString(cursor.getColumnIndexOrThrow(TDAdb.COL_CHAPTER));

       mCallback.onChapterSelected(chaptervalueselected, position);
        Toast.makeText(getActivity(), "Chapter " + chaptervalueselected,     Toast.LENGTH_SHORT).show();

    // starts a new Intent to update/delete a Chapter
    // pass in row Id to create the Content URI for a single row
    //Intent chapterEdit = new Intent(getBaseContext(), ChapterEdit.class);
    //Bundle bundle = new Bundle();
    //bundle.putString("mode", "update");
    //bundle.putString("rowId", rowId);
    //chapterEdit.putExtras(bundle);
    //startActivity(chapterEdit);

   }
  });

 }

 // This is called when a new Loader needs to be created.
 @Override
 public Loader<Cursor> onCreateLoader(int id, Bundle args) {
     Log.i(TAG, " onCreateLoader");
  String[] projection = { 
    TDAdb.KEY_ROWID,    
    TDAdb.COL_CHAPTER, 
    TDAdb.COL_CHAPTERTITLE}; 

  CursorLoader cursorLoader = new CursorLoader(getActivity(),
  TDAProvider.CONTENT_URI, projection, null, null, null);
  return cursorLoader;
 }

 @Override
 public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
     Log.i(TAG, " ononLoadFinished");
  // Swap the new cursor in.  (The framework will take care of closing the
        // old cursor once we return.)
        dataAdapter.swapCursor(data);
 }

 @Override
 public void onLoaderReset(Loader<Cursor> loader) {
  // This is called when the last Cursor provided to onLoadFinished()
  // above is about to be closed.  We need to make sure we are no
  // longer using it.
     Log.i(TAG, " onLoaderReset");
  dataAdapter.swapCursor(null);
 } 


}

回答1:

If you are already using the add method of FragmentTransaction you must not include the <fragment tag in your layout. What if you just left your main activity XML like this:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fragment_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>


回答2:

In chapterFragment.java change your import

import android.app.Fragment

To

import android.support.v4.app.Fragment