Android Compatibility packageを使って、Fragmentsを1.6上で動かす
Honeycomb(3.0)から使えるというFragmentsですが、これを1.6以上でも使えるようにするstatic libraryが公開されました。
http://android-developers.blogspot.com/2011/03/fragments-for-all.html
ぼくが持っているのはあのIS01で、(いろいろしない限り)1.6しか動きません。というわけで、このライブラリを早速使ってみることにしました。
libraryのインストール
- SDKのUpdate マネージャからダウンロードします。"Android Compatibility package, revision 1" です。
- extras/android/compatibility/v4/android-support-v4.jar をbuild pathに追加します。
- android.support.v4.app.* をimportします
これで使えるようになります。import元が3.0とは異なるのがちょっといやですね。
Fragment
Activity.getFragmentManager()はありませんが、代わりにFragmentActivity.getSupportFragmentManager()が定義されています。なお、Fragment.getFragmentManager()はNULLが返ってくるようです。
サンプル
こちらに掲載されているサンプルを1.6でも動くように手直しました。
ちなみに、1.6で動かすために以下の点にひっかかりました。
- match_parentはAPI Level 8から導入
- ListViewのidに制限
ちなみに、addToBackStackを呼んでいるので、ボタンを押すたびにFragmentがBackStackに積まれます。
Main.java
package com.example.test.fragment; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.support.v4.app.*; import com.example.test.fragment.R; public class Main extends FragmentActivity{ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); for(int i = 1;i < 6;i++){ int resId = getResources().getIdentifier("button" + i, "id", getPackageName()); setCallback((Button)findViewById(resId), i); } } private void setCallback(Button b, final int i){ b.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { stackAFragment(i); } }); } private void stackAFragment(int nAndroids) { Fragment f = new LogoFragment(nAndroids); FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.replace(R.id.the_frag, f); ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); ft.addToBackStack(null); ft.commit(); } }
LogoFragment.java
package com.example.test.fragment; import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; import android.support.v4.app.*; public class LogoFragment extends Fragment { private int nAndroids = 1; public LogoFragment(){ } public LogoFragment(int nAndroids) { this.nAndroids = nAndroids; } @Override public void onCreate(Bundle saved) { super.onCreate(saved); if (null != saved) { nAndroids = saved.getInt("nAndroids"); } } @Override public void onSaveInstanceState(Bundle toSave) { toSave.putInt("nAndroids", nAndroids); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle saved) { Context c = getActivity().getApplicationContext(); LinearLayout l = new LinearLayout(c); for (int n = 0; n < nAndroids; n++) { ImageView i = new ImageView(c); i.setImageResource(R.drawable.icon); l.addView(i); } return l; } }
main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_height="fill_parent" android:id="@+id/frags" android:layout_width="fill_parent"> <LinearLayout android:layout_height="fill_parent" android:id="@+id/linearLayout1" android:layout_width="wrap_content" android:orientation="vertical"> <Button android:text="Button" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> <Button android:text="Button" android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> <Button android:text="Button" android:id="@+id/button3" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> <Button android:text="Button" android:id="@+id/button4" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> <Button android:text="Button" android:id="@+id/button5" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> </LinearLayout> <fragment class="com.example.test.fragment.LogoFragment" android:id="@+id/the_frag" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </LinearLayout>
Fragment豆知識
removeとかreplaceしたときメモリはどうなるの?
addToBackStack()を呼んでいると、BackStackに積まれます。呼んでいないとメモリから破棄されます。つまり、onDetach()までが呼ばれます。
BackStackに積まれているときにBackボタンを押したらどうなるの?
その時表示されているFragmentは破棄され(onDetachまで呼ばれる)、BackStackの一番上にあるFragmentがpopされて表示されます。