Android Fragment简记

573 查看

Android Fragment简记

温习Android的知识。

本文更像是对CodePath Android Cliffnotes => Creating and Using Fragments的翻译及简化。

由于没有在CodePath Android Cliffnotes上找到lisence之类的信息,暂不知这样是否妥当。

Fragment一般可以理解成Activity的一部分(视图,UI)。

定义Fragment

一个Fragment包含两部分,View和Java类。

View可以是XML布局,也可以是纯Java代码的View。

Java类需要继承自Fragment类。在support library v4中的Fragment类可最低支持Api-4。

在Activity中加入Fragment

首先Activity要支持Fragment:如果使用的是support library中的Fragment,那么Activity也需要继承自support library中的FragmentActivity。

添加的方式有两种——静态的和动态的。

静态

直接在Activity的XML布局文件中加入Fragment。

class属性指定Java类。

<?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"
    android:orientation="vertical" >

   <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView" />

    <fragment
        android:id="@+id/fooFragment"
        android:layout_height="match_parent"
        android:layout_marginTop="?android:attr/actionBarSize"
        class="com.example.android.FooFragment" ></fragment>

</LinearLayout>

动态

使用FragmentManager。

但首先也需要在Activity的布局中有一个place holder给Fragment提供位置。

// Begin the transaction
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
// Replace the container with the new fragment
ft.replace(R.id.your_placeholder, new FooFragment());
// or ft.add(R.id.your_placeholder, new FooFragment());
// Execute the changes specified
ft.commit();

生命周期

  • onAttach() Fragment attach到Activity时调用
  • onCreate() 对Fragment做初始化
  • onCreateView() 当Fragment需要创建View时调用
  • onActivityCreated() 当宿主Activity完成了onCreate()方法时被调用
  • onDestroyView() 当Fragment开始被销毁时调用
  • onStart() 当Fragment可见时调用
  • onResume() 获取一些昂贵的资源,如位置、传感器等
  • onPause() 释放昂贵资源,提交更改

与Fragment的交互

Fragment不应该相互间直接通信,而应通过Activity来进行。有三个方法可以在Fragment和Activity之间进行通信。

带参数的Fragment

在某些情况下,Fragment可能需要特定的参数。(用来初始化Fragment。)

一个常用模式是使用newInstance()来创建带参数的Fragment。(这样做的原因是Fragment只能有一个无参的构造方法。)

public class DemoFragment extends Fragment {
    // Creates a new fragment given an int and title
    // DemoFragment.newInstance(5, "Hello");
    public static DemoFragment newInstance(int someInt, String someTitle) {
        DemoFragment fragmentDemo = new DemoFragment();
        Bundle args = new Bundle();
        args.putInt("someInt", someInt);
        args.putString("someTitle", someTitle);
        fragmentDemo.setArguments(args);
        return fragmentDemo;
    }
}

public class DemoFragment extends Fragment {
   @Override
   public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       // Get back arguments
       int SomeInt = getArguments().getInt("someInt", 0);   
       String someTitle = getArguments().getString("someTitle", "");    
   }
}

Activity调用Fragment方法

public class MainActivity extends FragmentActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        DemoFragment fragmentDemo = (DemoFragment) 
            getSupportFragmentManager().findFragmentById(R.id.fragmentDemo);
        fragmentDemo.doSomething("some param");
    }
}

在Fragment中的Listener

如果Fragment需要共享事件给Activity,则需要利用这种方法。

Fragment中定义一个接口,并且由Activity来实现这个接口。在onAttach()方法中将实现了这个接口的Activity获取到。

public class MyListFragment extends Fragment {
  // ...
  // Define the listener of the interface type
  // listener is the activity itself
  private OnItemSelectedListener listener;

  // Define the events that the fragment will use to communicate
  public interface OnItemSelectedListener {
    public void onRssItemSelected(String link);
  }

  // Store the listener (activity) that will have events fired once the fragment is attached
  @Override
  public void onAttach(Activity activity) {
    super.onAttach(activity);
      if (activity instanceof OnItemSelectedListener) {
        listener = (OnItemSelectedListener) activity;
      } else {
        throw new ClassCastException(activity.toString()
            + " must implement MyListFragment.OnItemSelectedListener");
      }
  }

  // Now we can fire the event when the user selects something in the fragment
  public void onSomeClick(View v) {
     listener.onRssItemSelected("some link");
  }
}

public class RssfeedActivity extends FragmentActivity implements
  MyListFragment.OnItemSelectedListener {
    DetailFragment fragment;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_rssfeed);
      fragment = (DetailFragment) getSupportFragmentManager()
            .findFragmentById(R.id.detailFragment);
  }

  // Now we can define the action to take in the activity when the fragment event fires
  @Override
  public void onRssItemSelected(String link) {
      if (fragment != null && fragment.isInLayout()) {
          fragment.setText(link);
      }
  }
}

Fragment与ActionBar菜单项

如果Fragment中有相关联的ActionBar菜单项,可以在Fragment中通过onCreateOptionsMenu()方法来进行设置,就与Activity中一致。

需要注意的是,只有事件没有在Activity中被处理掉时,Fragment中的事件回调才会被调用。

但你需要设置该Fragment中有菜单项。

@Override
public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setHasOptionsMenu(true);
}

创建菜单:

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
   inflater.inflate(R.menu.fragment_menu, menu);
}

响应:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
   // handle item selection
   switch (item.getItemId()) {
      case R.id.edit_item:
         // do s.th.
         return true;
      default:
         return super.onOptionsItemSelected(item);
   }
}

Fragment间的导航

可用:

  • ActionBar Tabs
  • Fragment Navigation Drawer
  • ViewPager

管理Fragment的回退栈

如果需要用后退键来回退Fragment,则在FragmentTransaction中调用addToBackstack()即可。

// Create the transaction
FragmentTransaction fts = getSupportFragmentManager().beginTransaction();
// Replace the content of the container
fts.replace(R.id.flContainer, new FirstFragment()); 
// Append this transaction to the backstack
fts.addToBackStack("optional tag");
// Commit the changes
fts.commit(); 

也可进行弹出:

FragmentManager fragmentManager = getSupportFragmentManager();
if (fragmentManager.getBackStackEntryCount() > 0) {
    fragmentManager.popBackStack();
} Android Fragment简记

Fragment一般可以理解成Activity的一部分(视图,UI)。

定义Fragment

一个Fragment包含两部分,View和Java类。

View可以是XML布局,也可以是纯Java代码的View。

Java类需要继承自Fragment类。在support library v4中的Fragment类可最低支持Android 2.1(API-7)。

在Activity中加入Fragment

首先Activity要支持Fragment:如果使用的是support library中的Fragment,那么Activity也需要继承自support library中的FragmentActivity。

添加的方式有两种——静态的和动态的。

静态

直接在Activity的XML布局文件中加入Fragment。

class属性指定Java类。

<?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"
    android:orientation="vertical" >

   <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView" />

    <fragment
        android:id="@+id/fooFragment"
        android:layout_height="match_parent"
        android:layout_marginTop="?android:attr/actionBarSize"
        class="com.example.android.FooFragment" ></fragment>

</LinearLayout>

动态

使用FragmentManager。

但首先也需要在Activity的布局中有一个place holder给Fragment提供位置。

// Begin the transaction
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
// Replace the container with the new fragment
ft.replace(R.id.your_placeholder, new FooFragment());
// or ft.add(R.id.your_placeholder, new FooFragment());
// Execute the changes specified
ft.commit();

生命周期

  • onAttach() Fragment attach到Activity时调用
  • onCreate() 对Fragment做初始化
  • onCreateView() 当Fragment需要创建View时调用
  • onActivityCreated() 当宿主Activity完成了onCreate()方法时被调用
  • onDestroyView() 当Fragment开始被销毁时调用
  • onStart() 当Fragment可见时调用
  • onResume() - 获取一些昂贵的资源,如位置、传感器等
  • onPause() - 释放昂贵资源,提交更改

与Fragment的交互

Fragment不应该相互间直接通信,而应通过Activity来进行。有三个方法可以在Fragment和Activity之间进行通信。

带参数的Fragment

在某些情况下,Fragment可能需要特定的参数。(用来初始化Fragment。)

一个常用模式是使用newInstance()来创建带参数的Fragment。(这样做的原因是Fragment只能有一个无参的构造方法。)

public class DemoFragment extends Fragment {
    // Creates a new fragment given an int and title
    // DemoFragment.newInstance(5, "Hello");
    public static DemoFragment newInstance(int someInt, String someTitle) {
        DemoFragment fragmentDemo = new DemoFragment();
        Bundle args = new Bundle();
        args.putInt("someInt", someInt);
        args.putString("someTitle", someTitle);
        fragmentDemo.setArguments(args);
        return fragmentDemo;
    }
}

public class DemoFragment extends Fragment {
   @Override
   public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       // Get back arguments
       int SomeInt = getArguments().getInt("someInt", 0);   
       String someTitle = getArguments().getString("someTitle", "");    
   }
}

Activity调用Fragment方法

public class MainActivity extends FragmentActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        DemoFragment fragmentDemo = (DemoFragment) 
            getSupportFragmentManager().findFragmentById(R.id.fragmentDemo);
        fragmentDemo.doSomething("some param");
    }
}

在Fragment中的Listener

如果Fragment需要共享事件给Activity,则需要利用这种方法。

Fragment中定义一个接口,并且由Activity来实现这个接口。在onAttach()方法中将实现了这个接口的Activity获取到。

public class MyListFragment extends Fragment {
  // ...
  // Define the listener of the interface type
  // listener is the activity itself
  private OnItemSelectedListener listener;

  // Define the events that the fragment will use to communicate
  public interface OnItemSelectedListener {
    public void onRssItemSelected(String link);
  }

  // Store the listener (activity) that will have events fired once the fragment is attached
  @Override
  public void onAttach(Activity activity) {
    super.onAttach(activity);
      if (activity instanceof OnItemSelectedListener) {
        listener = (OnItemSelectedListener) activity;
      } else {
        throw new ClassCastException(activity.toString()
            + " must implement MyListFragment.OnItemSelectedListener");
      }
  }

  // Now we can fire the event when the user selects something in the fragment
  public void onSomeClick(View v) {
     listener.onRssItemSelected("some link");
  }
}

public class RssfeedActivity extends FragmentActivity implements
  MyListFragment.OnItemSelectedListener {
    DetailFragment fragment;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_rssfeed);
      fragment = (DetailFragment) getSupportFragmentManager()
            .findFragmentById(R.id.detailFragment);
  }

  // Now we can define the action to take in the activity when the fragment event fires
  @Override
  public void onRssItemSelected(String link) {
      if (fragment != null && fragment.isInLayout()) {
          fragment.setText(link);
      }
  }
}

Fragment与ActionBar菜单项

如果Fragment中有相关联的ActionBar菜单项,可以在Fragment中通过onCreateOptionsMenu()方法来进行设置,就与Activity中一致。

需要注意的是,只有事件没有在Activity中被处理掉时,Fragment中的事件回调才会被调用。

但你需要设置该Fragment中有菜单项。

@Override
public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setHasOptionsMenu(true);
}

创建菜单:

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
   inflater.inflate(R.menu.fragment_menu, menu);
}

响应:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
   // handle item selection
   switch (item.getItemId()) {
      case R.id.edit_item:
         // do s.th.
         return true;
      default:
         return super.onOptionsItemSelected(item);
   }
}

Fragment间的导航

可用:

  • ActionBar Tabs
  • Fragment Navigation Drawer
  • ViewPager

管理Fragment的回退栈

如果需要用后退键来回退Fragment,则在FragmentTransaction中调用addToBackstack()即可。

// Create the transaction
FragmentTransaction fts = getSupportFragmentManager().beginTransaction();
// Replace the content of the container
fts.replace(R.id.flContainer, new FirstFragment()); 
// Append this transaction to the backstack
fts.addToBackStack("optional tag");
// Commit the changes
fts.commit(); 

也可进行弹出:

FragmentManager fragmentManager = getSupportFragmentManager();
if (fragmentManager.getBackStackEntryCount() > 0) {
    fragmentManager.popBackStack();
}